blob: bf5e42eb7932695405bdbcd6a0233a0fb85ec011 [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 <>
50struct std::formatter<boost::urls::url>
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 <>
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,
124 Debug,
Ed Tanous1abe55e2018-09-05 08:30:59 -0700125 Info,
126 Warning,
127 Error,
128 Critical,
Ed Tanous1e439872018-05-18 11:48:52 -0700129};
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700130
Myung Bae662aa6e2023-01-10 14:20:28 -0600131// Mapping of the external loglvl name to internal loglvl
132constexpr std::array<std::pair<std::string_view, crow::LogLevel>, 7>
133 mapLogLevelFromName{{{"disabled", crow::LogLevel::Disabled},
134 {"enabled", crow::LogLevel::Debug},
135 {"debug", crow::LogLevel::Debug},
136 {"info", crow::LogLevel::Info},
137 {"warning", crow::LogLevel::Warning},
138 {"error", crow::LogLevel::Error},
139 {"critical", crow::LogLevel::Critical}}};
140
141constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
142{
143 const auto* iter =
144 std::find_if(begin(mapLogLevelFromName), end(mapLogLevelFromName),
145 [&name](const auto& v) { return v.first == name; });
146 if (iter != end(mapLogLevelFromName))
147 {
148 return iter->second;
149 }
150 return crow::LogLevel::Disabled;
151}
152
153// configured bmcweb LogLevel
154constexpr crow::LogLevel bmcwebCurrentLoggingLevel =
155 getLogLevelFromName(bmcwebLoggingLevel);
156
Ed Tanous62598e32023-07-17 17:06:25 -0700157struct FormatString
Ed Tanous1abe55e2018-09-05 08:30:59 -0700158{
Ed Tanous62598e32023-07-17 17:06:25 -0700159 std::string_view str;
160 std::source_location loc;
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700161
Ed Tanous62598e32023-07-17 17:06:25 -0700162 // NOLINTNEXTLINE(google-explicit-constructor)
163 FormatString(const char* strIn, const std::source_location& locIn =
164 std::source_location::current()) :
165 str(strIn),
166 loc(locIn)
167 {}
Ed Tanous1e439872018-05-18 11:48:52 -0700168};
Ed Tanous62598e32023-07-17 17:06:25 -0700169
170template <typename T>
171const void* logPtr(T p)
172{
173 static_assert(std::is_pointer<T>::value,
174 "Can't use logPtr without pointer");
175 return std::bit_cast<const void*>(p);
176}
177
178template <LogLevel level>
179inline void vlog(const FormatString& format, std::format_args&& args)
180{
181 if constexpr (bmcwebCurrentLoggingLevel > level)
182 {
183 return;
184 }
185 constexpr size_t stringIndex = static_cast<size_t>(level);
186 static_assert(stringIndex < mapLogLevelFromName.size(),
187 "Missing string for level");
188 constexpr std::string_view levelString =
189 mapLogLevelFromName[stringIndex].first;
190 std::string_view filename = format.loc.file_name();
191 if (filename.starts_with("../"))
192 {
193 filename = filename.substr(3);
194 }
195 std::cout << std::format("[{} {}:{}] ", levelString, filename,
196 format.loc.line());
197 std::cout << std::vformat(format.str, args);
198 std::putc('\n', stdout);
199}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700200} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700201
Ed Tanous62598e32023-07-17 17:06:25 -0700202template <typename... Args>
203inline void BMCWEB_LOG_CRITICAL(const crow::FormatString& format,
204 Args&&... args)
205{
206 crow::vlog<crow::LogLevel::Critical>(
207 format, std::make_format_args(std::forward<Args>(args)...));
208}
Patrick Williamseb8a3992023-05-12 09:57:16 -0500209
Ed Tanous62598e32023-07-17 17:06:25 -0700210template <typename... Args>
211inline void BMCWEB_LOG_ERROR(const crow::FormatString& format, Args&&... args)
212{
213 crow::vlog<crow::LogLevel::Error>(
214 format, std::make_format_args(std::forward<Args>(args)...));
215}
Ed Tanous600d2392022-01-07 09:32:03 -0800216
Ed Tanous62598e32023-07-17 17:06:25 -0700217template <typename... Args>
218inline void BMCWEB_LOG_WARNING(const crow::FormatString& format, Args&&... args)
219{
220 crow::vlog<crow::LogLevel::Warning>(
221 format, std::make_format_args(std::forward<Args>(args)...));
222}
Ed Tanous600d2392022-01-07 09:32:03 -0800223
Ed Tanous62598e32023-07-17 17:06:25 -0700224template <typename... Args>
225inline void BMCWEB_LOG_INFO(const crow::FormatString& format, Args&&... args)
226{
227 crow::vlog<crow::LogLevel::Info>(
228 format, std::make_format_args(std::forward<Args>(args)...));
229}
Ed Tanous600d2392022-01-07 09:32:03 -0800230
Ed Tanous62598e32023-07-17 17:06:25 -0700231template <typename... Args>
232inline void BMCWEB_LOG_DEBUG(const crow::FormatString& format, Args&&... args)
233{
234 crow::vlog<crow::LogLevel::Debug>(
235 format, std::make_format_args(std::forward<Args>(args)...));
236}