blob: de14d99e8f244a1267c951bd74d4c9aef22150a2 [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>
Ed Tanous4a7fbef2024-04-06 16:03:49 -07008#include <boost/url/url_view_base.hpp>
Ed Tanous62598e32023-07-17 17:06:25 -07009#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
Ed Tanous4a7fbef2024-04-06 16:03:49 -070049template <std::derived_from<boost::urls::url_view_base> URL>
50struct std::formatter<URL>
Ed Tanousa716aa72023-08-01 11:35:53 -070051{
52 constexpr auto parse(std::format_parse_context& ctx)
53 {
54 return ctx.begin();
55 }
Ed Tanous4a7fbef2024-04-06 16:03:49 -070056 auto format(const URL& msg, auto& ctx) const
Ed Tanous62598e32023-07-17 17:06:25 -070057 {
58 return std::format_to(ctx.out(), "{}", std::string_view(msg.buffer()));
59 }
60};
61
62template <>
63struct std::formatter<boost::core::string_view>
64{
65 constexpr auto parse(std::format_parse_context& ctx)
66 {
67 return ctx.begin();
68 }
69 auto format(const boost::core::string_view& msg, auto& ctx) const
70 {
71 return std::format_to(ctx.out(), "{}", std::string_view(msg));
72 }
73};
74
75template <>
76struct std::formatter<void*>
77{
78 constexpr auto parse(std::format_parse_context& ctx)
79 {
80 return ctx.begin();
81 }
82 auto format(const void*& ptr, auto& ctx) const
83 {
84 return std::format_to(ctx.out(), "{}",
85 std::to_string(std::bit_cast<size_t>(ptr)));
86 }
87};
88
89template <>
90struct std::formatter<nlohmann::json::json_pointer>
91{
92 constexpr auto parse(std::format_parse_context& ctx)
93 {
94 return ctx.begin();
95 }
96 auto format(const nlohmann::json::json_pointer& ptr, auto& ctx) const
97 {
98 return std::format_to(ctx.out(), "{}", ptr.to_string());
99 }
100};
101
102template <>
103struct std::formatter<nlohmann::json>
104{
105 static constexpr auto parse(std::format_parse_context& ctx)
106 {
107 return ctx.begin();
108 }
109 auto format(const nlohmann::json& json, auto& ctx) const
110 {
111 return std::format_to(
112 ctx.out(), "{}",
113 json.dump(-1, ' ', false,
114 nlohmann::json::error_handler_t::replace));
115 }
116};
117// NOLINTEND(readability-convert-member-functions-to-static, cert-dcl58-cpp)
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700118
Ed Tanous1abe55e2018-09-05 08:30:59 -0700119namespace crow
120{
121enum class LogLevel
122{
Myung Bae662aa6e2023-01-10 14:20:28 -0600123 Disabled = 0,
Ed Tanous1abe55e2018-09-05 08:30:59 -0700124 Critical,
Ed Tanouse7245fe2023-07-24 17:01:38 -0700125 Error,
126 Warning,
127 Info,
128 Debug,
129 Enabled,
Ed Tanous1e439872018-05-18 11:48:52 -0700130};
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700131
Myung Bae662aa6e2023-01-10 14:20:28 -0600132// Mapping of the external loglvl name to internal loglvl
Ed Tanouse7245fe2023-07-24 17:01:38 -0700133constexpr std::array<std::string_view, 7> mapLogLevelFromName{
134 "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
Myung Bae662aa6e2023-01-10 14:20:28 -0600135
136constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
137{
Ed Tanouse7245fe2023-07-24 17:01:38 -0700138 const auto* iter = std::ranges::find(mapLogLevelFromName, name);
139 if (iter != mapLogLevelFromName.end())
Myung Bae662aa6e2023-01-10 14:20:28 -0600140 {
Ed Tanouse7245fe2023-07-24 17:01:38 -0700141 return static_cast<LogLevel>(iter - mapLogLevelFromName.begin());
Myung Bae662aa6e2023-01-10 14:20:28 -0600142 }
143 return crow::LogLevel::Disabled;
144}
145
146// configured bmcweb LogLevel
147constexpr crow::LogLevel bmcwebCurrentLoggingLevel =
148 getLogLevelFromName(bmcwebLoggingLevel);
149
Ed Tanous62598e32023-07-17 17:06:25 -0700150template <typename T>
151const void* logPtr(T p)
152{
153 static_assert(std::is_pointer<T>::value,
154 "Can't use logPtr without pointer");
155 return std::bit_cast<const void*>(p);
156}
157
Ed Tanous6ea90762024-04-07 08:38:44 -0700158template <LogLevel level, typename... Args>
159inline void vlog(std::format_string<Args...> format, Args... args,
160 const std::source_location& loc) noexcept
Ed Tanous62598e32023-07-17 17:06:25 -0700161{
Myung Baed518a9b2023-08-01 16:12:35 -0400162 if constexpr (bmcwebCurrentLoggingLevel < level)
Ed Tanous62598e32023-07-17 17:06:25 -0700163 {
164 return;
165 }
166 constexpr size_t stringIndex = static_cast<size_t>(level);
167 static_assert(stringIndex < mapLogLevelFromName.size(),
168 "Missing string for level");
Ed Tanouse7245fe2023-07-24 17:01:38 -0700169 constexpr std::string_view levelString = mapLogLevelFromName[stringIndex];
Ed Tanous6ea90762024-04-07 08:38:44 -0700170 std::string_view filename = loc.file_name();
Ed Tanouse7245fe2023-07-24 17:01:38 -0700171 filename = filename.substr(filename.rfind('/') + 1);
Ed Tanous6ea90762024-04-07 08:38:44 -0700172 std::cout << std::format("[{} {}:{}] ", levelString, filename, loc.line())
173 << std::format(format, std::forward<Args>(args)...) << '\n'
Ed Tanousdce4d232024-04-03 10:52:39 -0700174 << std::flush;
Ed Tanous62598e32023-07-17 17:06:25 -0700175}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700176} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700177
Ed Tanous62598e32023-07-17 17:06:25 -0700178template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700179struct BMCWEB_LOG_CRITICAL
Ed Tanous62598e32023-07-17 17:06:25 -0700180{
Ed Tanous6ea90762024-04-07 08:38:44 -0700181 // NOLINTNEXTLINE(google-explicit-constructor)
182 BMCWEB_LOG_CRITICAL(std::format_string<Args...> format, Args&&... args,
183 const std::source_location& loc =
184 std::source_location::current()) noexcept
185 {
186 crow::vlog<crow::LogLevel::Critical, Args...>(format, args..., loc);
187 }
188};
Patrick Williamseb8a3992023-05-12 09:57:16 -0500189
Ed Tanous62598e32023-07-17 17:06:25 -0700190template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700191struct BMCWEB_LOG_ERROR
Ed Tanous62598e32023-07-17 17:06:25 -0700192{
Ed Tanous6ea90762024-04-07 08:38:44 -0700193 // NOLINTNEXTLINE(google-explicit-constructor)
194 BMCWEB_LOG_ERROR(std::format_string<Args...> format, Args&&... args,
195 const std::source_location& loc =
196 std::source_location::current()) noexcept
197 {
198 crow::vlog<crow::LogLevel::Error, Args...>(format, args..., loc);
199 }
200};
Ed Tanous600d2392022-01-07 09:32:03 -0800201
Ed Tanous62598e32023-07-17 17:06:25 -0700202template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700203struct BMCWEB_LOG_WARNING
Ed Tanous62598e32023-07-17 17:06:25 -0700204{
Ed Tanous6ea90762024-04-07 08:38:44 -0700205 // NOLINTNEXTLINE(google-explicit-constructor)
206 BMCWEB_LOG_WARNING(std::format_string<Args...> format, Args&&... args,
207 const std::source_location& loc =
208 std::source_location::current()) noexcept
209 {
210 crow::vlog<crow::LogLevel::Warning, Args...>(format, args..., loc);
211 }
212};
Ed Tanous600d2392022-01-07 09:32:03 -0800213
Ed Tanous62598e32023-07-17 17:06:25 -0700214template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700215struct BMCWEB_LOG_INFO
Ed Tanous62598e32023-07-17 17:06:25 -0700216{
Ed Tanous6ea90762024-04-07 08:38:44 -0700217 // NOLINTNEXTLINE(google-explicit-constructor)
218 BMCWEB_LOG_INFO(std::format_string<Args...> format, Args&&... args,
219 const std::source_location& loc =
220 std::source_location::current()) noexcept
221 {
222 crow::vlog<crow::LogLevel::Info, Args...>(format, args..., loc);
223 }
224};
Ed Tanous600d2392022-01-07 09:32:03 -0800225
Ed Tanous62598e32023-07-17 17:06:25 -0700226template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700227struct BMCWEB_LOG_DEBUG
Ed Tanous62598e32023-07-17 17:06:25 -0700228{
Ed Tanous6ea90762024-04-07 08:38:44 -0700229 // NOLINTNEXTLINE(google-explicit-constructor)
230 BMCWEB_LOG_DEBUG(std::format_string<Args...> format, Args&&... args,
231 const std::source_location& loc =
232 std::source_location::current()) noexcept
233 {
234 crow::vlog<crow::LogLevel::Debug, Args...>(format, args..., loc);
235 }
236};
237
238template <typename... Args>
239BMCWEB_LOG_CRITICAL(std::format_string<Args...>, Args&&...)
240 -> BMCWEB_LOG_CRITICAL<Args...>;
241
242template <typename... Args>
243BMCWEB_LOG_ERROR(std::format_string<Args...>, Args&&...)
244 -> BMCWEB_LOG_ERROR<Args...>;
245
246template <typename... Args>
247BMCWEB_LOG_WARNING(std::format_string<Args...>, Args&&...)
248 -> BMCWEB_LOG_WARNING<Args...>;
249
250template <typename... Args>
251BMCWEB_LOG_INFO(std::format_string<Args...>, Args&&...)
252 -> BMCWEB_LOG_INFO<Args...>;
253
254template <typename... Args>
255BMCWEB_LOG_DEBUG(std::format_string<Args...>, Args&&...)
256 -> BMCWEB_LOG_DEBUG<Args...>;