blob: 0ed47771c4253538aaa84687559f1e18eda8bb1e [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 -0700163struct FormatString
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164{
Ed Tanous62598e32023-07-17 17:06:25 -0700165 std::string_view str;
166 std::source_location loc;
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700167
Ed Tanous62598e32023-07-17 17:06:25 -0700168 // NOLINTNEXTLINE(google-explicit-constructor)
Ed Tanous8ece0e42024-01-02 13:16:50 -0800169 FormatString(const char* stringIn, const std::source_location& locIn =
170 std::source_location::current()) :
171 str(stringIn),
Ed Tanous62598e32023-07-17 17:06:25 -0700172 loc(locIn)
173 {}
Ed Tanous1e439872018-05-18 11:48:52 -0700174};
Ed Tanous62598e32023-07-17 17:06:25 -0700175
176template <typename T>
177const void* logPtr(T p)
178{
179 static_assert(std::is_pointer<T>::value,
180 "Can't use logPtr without pointer");
181 return std::bit_cast<const void*>(p);
182}
183
184template <LogLevel level>
185inline void vlog(const FormatString& format, std::format_args&& args)
186{
Myung Baed518a9b2023-08-01 16:12:35 -0400187 if constexpr (bmcwebCurrentLoggingLevel < level)
Ed Tanous62598e32023-07-17 17:06:25 -0700188 {
189 return;
190 }
191 constexpr size_t stringIndex = static_cast<size_t>(level);
192 static_assert(stringIndex < mapLogLevelFromName.size(),
193 "Missing string for level");
Ed Tanouse7245fe2023-07-24 17:01:38 -0700194 constexpr std::string_view levelString = mapLogLevelFromName[stringIndex];
Ed Tanous62598e32023-07-17 17:06:25 -0700195 std::string_view filename = format.loc.file_name();
Ed Tanouse7245fe2023-07-24 17:01:38 -0700196 filename = filename.substr(filename.rfind('/') + 1);
Ed Tanous62598e32023-07-17 17:06:25 -0700197 std::cout << std::format("[{} {}:{}] ", levelString, filename,
Ed Tanouse7245fe2023-07-24 17:01:38 -0700198 format.loc.line())
Ed Tanousdce4d232024-04-03 10:52:39 -0700199 << std::vformat(format.str, args) << '\n'
200 << std::flush;
Ed Tanous62598e32023-07-17 17:06:25 -0700201}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700202} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700203
Ed Tanous62598e32023-07-17 17:06:25 -0700204template <typename... Args>
205inline void BMCWEB_LOG_CRITICAL(const crow::FormatString& format,
206 Args&&... args)
207{
208 crow::vlog<crow::LogLevel::Critical>(
209 format, std::make_format_args(std::forward<Args>(args)...));
210}
Patrick Williamseb8a3992023-05-12 09:57:16 -0500211
Ed Tanous62598e32023-07-17 17:06:25 -0700212template <typename... Args>
213inline void BMCWEB_LOG_ERROR(const crow::FormatString& format, Args&&... args)
214{
215 crow::vlog<crow::LogLevel::Error>(
216 format, std::make_format_args(std::forward<Args>(args)...));
217}
Ed Tanous600d2392022-01-07 09:32:03 -0800218
Ed Tanous62598e32023-07-17 17:06:25 -0700219template <typename... Args>
220inline void BMCWEB_LOG_WARNING(const crow::FormatString& format, Args&&... args)
221{
222 crow::vlog<crow::LogLevel::Warning>(
223 format, std::make_format_args(std::forward<Args>(args)...));
224}
Ed Tanous600d2392022-01-07 09:32:03 -0800225
Ed Tanous62598e32023-07-17 17:06:25 -0700226template <typename... Args>
227inline void BMCWEB_LOG_INFO(const crow::FormatString& format, Args&&... args)
228{
229 crow::vlog<crow::LogLevel::Info>(
230 format, std::make_format_args(std::forward<Args>(args)...));
231}
Ed Tanous600d2392022-01-07 09:32:03 -0800232
Ed Tanous62598e32023-07-17 17:06:25 -0700233template <typename... Args>
234inline void BMCWEB_LOG_DEBUG(const crow::FormatString& format, Args&&... args)
235{
236 crow::vlog<crow::LogLevel::Debug>(
237 format, std::make_format_args(std::forward<Args>(args)...));
238}