blob: 2f88c90b14d4d09a1b605279e5370794bdbc92fb [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
2
Myung Bae662aa6e2023-01-10 14:20:28 -06003#include "bmcweb_config.h"
4
Ed Tanous62598e32023-07-17 17:06:25 -07005#include <boost/system/error_code.hpp>
6#include <boost/url/pct_string_view.hpp>
7#include <boost/url/string_view.hpp>
8#include <boost/url/url.hpp>
9#include <nlohmann/json.hpp>
10
11#include <bit>
12#include <format>
Ed Tanous4d92cbf2017-06-22 15:41:02 -070013#include <iostream>
Ed Tanous62598e32023-07-17 17:06:25 -070014#include <source_location>
Myung Bae662aa6e2023-01-10 14:20:28 -060015#include <string_view>
Ed Tanous62598e32023-07-17 17:06:25 -070016#include <system_error>
17
18// Clang-tidy would rather these be static, but using static causes the template
19// specialization to not function. Ignore the warning.
20// NOLINTBEGIN(readability-convert-member-functions-to-static, cert-dcl58-cpp)
21template <>
22struct std::formatter<boost::system::error_code>
23{
24 constexpr auto parse(std::format_parse_context& ctx)
25 {
26 return ctx.begin();
27 }
28
29 auto format(const boost::system::error_code& ec, auto& ctx) const
30 {
31 return std::format_to(ctx.out(), "{}", ec.what());
32 }
33};
34
35template <>
36struct std::formatter<boost::urls::pct_string_view>
37{
38 constexpr auto parse(std::format_parse_context& ctx)
39 {
40 return ctx.begin();
41 }
42 auto format(const boost::urls::pct_string_view& msg, auto& ctx) const
43 {
44 return std::format_to(ctx.out(), "{}",
45 std::string_view(msg.data(), msg.size()));
46 }
47};
48
49template <>
Ed Tanousa716aa72023-08-01 11:35:53 -070050struct std::formatter<boost::urls::url_view>
51{
52 constexpr auto parse(std::format_parse_context& ctx)
53 {
54 return ctx.begin();
55 }
56 auto format(const boost::urls::url& msg, auto& ctx) const
57 {
58 return std::format_to(ctx.out(), "{}", std::string_view(msg.buffer()));
59 }
60};
61
62template <>
Ed Tanous62598e32023-07-17 17:06:25 -070063struct std::formatter<boost::urls::url>
64{
65 constexpr auto parse(std::format_parse_context& ctx)
66 {
67 return ctx.begin();
68 }
69 auto format(const boost::urls::url& msg, auto& ctx) const
70 {
71 return std::format_to(ctx.out(), "{}", std::string_view(msg.buffer()));
72 }
73};
74
75template <>
76struct std::formatter<boost::core::string_view>
77{
78 constexpr auto parse(std::format_parse_context& ctx)
79 {
80 return ctx.begin();
81 }
82 auto format(const boost::core::string_view& msg, auto& ctx) const
83 {
84 return std::format_to(ctx.out(), "{}", std::string_view(msg));
85 }
86};
87
88template <>
89struct std::formatter<void*>
90{
91 constexpr auto parse(std::format_parse_context& ctx)
92 {
93 return ctx.begin();
94 }
95 auto format(const void*& ptr, auto& ctx) const
96 {
97 return std::format_to(ctx.out(), "{}",
98 std::to_string(std::bit_cast<size_t>(ptr)));
99 }
100};
101
102template <>
103struct std::formatter<nlohmann::json::json_pointer>
104{
105 constexpr auto parse(std::format_parse_context& ctx)
106 {
107 return ctx.begin();
108 }
109 auto format(const nlohmann::json::json_pointer& ptr, auto& ctx) const
110 {
111 return std::format_to(ctx.out(), "{}", ptr.to_string());
112 }
113};
114
115template <>
116struct std::formatter<nlohmann::json>
117{
118 static constexpr auto parse(std::format_parse_context& ctx)
119 {
120 return ctx.begin();
121 }
122 auto format(const nlohmann::json& json, auto& ctx) const
123 {
124 return std::format_to(
125 ctx.out(), "{}",
126 json.dump(-1, ' ', false,
127 nlohmann::json::error_handler_t::replace));
128 }
129};
130// NOLINTEND(readability-convert-member-functions-to-static, cert-dcl58-cpp)
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700131
Ed Tanous1abe55e2018-09-05 08:30:59 -0700132namespace crow
133{
134enum class LogLevel
135{
Myung Bae662aa6e2023-01-10 14:20:28 -0600136 Disabled = 0,
Ed Tanous1abe55e2018-09-05 08:30:59 -0700137 Critical,
Ed Tanouse7245fe2023-07-24 17:01:38 -0700138 Error,
139 Warning,
140 Info,
141 Debug,
142 Enabled,
Ed Tanous1e439872018-05-18 11:48:52 -0700143};
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700144
Myung Bae662aa6e2023-01-10 14:20:28 -0600145// Mapping of the external loglvl name to internal loglvl
Ed Tanouse7245fe2023-07-24 17:01:38 -0700146constexpr std::array<std::string_view, 7> mapLogLevelFromName{
147 "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
Myung Bae662aa6e2023-01-10 14:20:28 -0600148
149constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
150{
Ed Tanouse7245fe2023-07-24 17:01:38 -0700151 const auto* iter = std::ranges::find(mapLogLevelFromName, name);
152 if (iter != mapLogLevelFromName.end())
Myung Bae662aa6e2023-01-10 14:20:28 -0600153 {
Ed Tanouse7245fe2023-07-24 17:01:38 -0700154 return static_cast<LogLevel>(iter - mapLogLevelFromName.begin());
Myung Bae662aa6e2023-01-10 14:20:28 -0600155 }
156 return crow::LogLevel::Disabled;
157}
158
159// configured bmcweb LogLevel
160constexpr crow::LogLevel bmcwebCurrentLoggingLevel =
161 getLogLevelFromName(bmcwebLoggingLevel);
162
Ed Tanous62598e32023-07-17 17:06:25 -0700163template <typename T>
164const void* logPtr(T p)
165{
166 static_assert(std::is_pointer<T>::value,
167 "Can't use logPtr without pointer");
168 return std::bit_cast<const void*>(p);
169}
170
Ed Tanous6ea90762024-04-07 08:38:44 -0700171template <LogLevel level, typename... Args>
172inline void vlog(std::format_string<Args...> format, Args... args,
173 const std::source_location& loc) noexcept
Ed Tanous62598e32023-07-17 17:06:25 -0700174{
Myung Baed518a9b2023-08-01 16:12:35 -0400175 if constexpr (bmcwebCurrentLoggingLevel < level)
Ed Tanous62598e32023-07-17 17:06:25 -0700176 {
177 return;
178 }
179 constexpr size_t stringIndex = static_cast<size_t>(level);
180 static_assert(stringIndex < mapLogLevelFromName.size(),
181 "Missing string for level");
Ed Tanouse7245fe2023-07-24 17:01:38 -0700182 constexpr std::string_view levelString = mapLogLevelFromName[stringIndex];
Ed Tanous6ea90762024-04-07 08:38:44 -0700183 std::string_view filename = loc.file_name();
Ed Tanouse7245fe2023-07-24 17:01:38 -0700184 filename = filename.substr(filename.rfind('/') + 1);
Ed Tanous6ea90762024-04-07 08:38:44 -0700185 std::cout << std::format("[{} {}:{}] ", levelString, filename, loc.line())
186 << std::format(format, std::forward<Args>(args)...) << '\n'
Ed Tanousdce4d232024-04-03 10:52:39 -0700187 << std::flush;
Ed Tanous62598e32023-07-17 17:06:25 -0700188}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700189} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700190
Ed Tanous62598e32023-07-17 17:06:25 -0700191template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700192struct BMCWEB_LOG_CRITICAL
Ed Tanous62598e32023-07-17 17:06:25 -0700193{
Ed Tanous6ea90762024-04-07 08:38:44 -0700194 // NOLINTNEXTLINE(google-explicit-constructor)
195 BMCWEB_LOG_CRITICAL(std::format_string<Args...> format, Args&&... args,
196 const std::source_location& loc =
197 std::source_location::current()) noexcept
198 {
199 crow::vlog<crow::LogLevel::Critical, Args...>(format, args..., loc);
200 }
201};
Patrick Williamseb8a3992023-05-12 09:57:16 -0500202
Ed Tanous62598e32023-07-17 17:06:25 -0700203template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700204struct BMCWEB_LOG_ERROR
Ed Tanous62598e32023-07-17 17:06:25 -0700205{
Ed Tanous6ea90762024-04-07 08:38:44 -0700206 // NOLINTNEXTLINE(google-explicit-constructor)
207 BMCWEB_LOG_ERROR(std::format_string<Args...> format, Args&&... args,
208 const std::source_location& loc =
209 std::source_location::current()) noexcept
210 {
211 crow::vlog<crow::LogLevel::Error, Args...>(format, args..., loc);
212 }
213};
Ed Tanous600d2392022-01-07 09:32:03 -0800214
Ed Tanous62598e32023-07-17 17:06:25 -0700215template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700216struct BMCWEB_LOG_WARNING
Ed Tanous62598e32023-07-17 17:06:25 -0700217{
Ed Tanous6ea90762024-04-07 08:38:44 -0700218 // NOLINTNEXTLINE(google-explicit-constructor)
219 BMCWEB_LOG_WARNING(std::format_string<Args...> format, Args&&... args,
220 const std::source_location& loc =
221 std::source_location::current()) noexcept
222 {
223 crow::vlog<crow::LogLevel::Warning, Args...>(format, args..., loc);
224 }
225};
Ed Tanous600d2392022-01-07 09:32:03 -0800226
Ed Tanous62598e32023-07-17 17:06:25 -0700227template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700228struct BMCWEB_LOG_INFO
Ed Tanous62598e32023-07-17 17:06:25 -0700229{
Ed Tanous6ea90762024-04-07 08:38:44 -0700230 // NOLINTNEXTLINE(google-explicit-constructor)
231 BMCWEB_LOG_INFO(std::format_string<Args...> format, Args&&... args,
232 const std::source_location& loc =
233 std::source_location::current()) noexcept
234 {
235 crow::vlog<crow::LogLevel::Info, Args...>(format, args..., loc);
236 }
237};
Ed Tanous600d2392022-01-07 09:32:03 -0800238
Ed Tanous62598e32023-07-17 17:06:25 -0700239template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700240struct BMCWEB_LOG_DEBUG
Ed Tanous62598e32023-07-17 17:06:25 -0700241{
Ed Tanous6ea90762024-04-07 08:38:44 -0700242 // NOLINTNEXTLINE(google-explicit-constructor)
243 BMCWEB_LOG_DEBUG(std::format_string<Args...> format, Args&&... args,
244 const std::source_location& loc =
245 std::source_location::current()) noexcept
246 {
247 crow::vlog<crow::LogLevel::Debug, Args...>(format, args..., loc);
248 }
249};
250
251template <typename... Args>
252BMCWEB_LOG_CRITICAL(std::format_string<Args...>, Args&&...)
253 -> BMCWEB_LOG_CRITICAL<Args...>;
254
255template <typename... Args>
256BMCWEB_LOG_ERROR(std::format_string<Args...>, Args&&...)
257 -> BMCWEB_LOG_ERROR<Args...>;
258
259template <typename... Args>
260BMCWEB_LOG_WARNING(std::format_string<Args...>, Args&&...)
261 -> BMCWEB_LOG_WARNING<Args...>;
262
263template <typename... Args>
264BMCWEB_LOG_INFO(std::format_string<Args...>, Args&&...)
265 -> BMCWEB_LOG_INFO<Args...>;
266
267template <typename... Args>
268BMCWEB_LOG_DEBUG(std::format_string<Args...>, Args&&...)
269 -> BMCWEB_LOG_DEBUG<Args...>;