blob: a9cf9a355985431947f79cc5d95379d81e821605 [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 <bit>
6#include <format>
Ed Tanous4d92cbf2017-06-22 15:41:02 -07007#include <iostream>
Ed Tanous62598e32023-07-17 17:06:25 -07008#include <source_location>
Myung Bae662aa6e2023-01-10 14:20:28 -06009#include <string_view>
Ed Tanous62598e32023-07-17 17:06:25 -070010#include <system_error>
11
Ed Tanous62598e32023-07-17 17:06:25 -070012// NOLINTBEGIN(readability-convert-member-functions-to-static, cert-dcl58-cpp)
13template <>
Ed Tanous62598e32023-07-17 17:06:25 -070014struct std::formatter<void*>
15{
16 constexpr auto parse(std::format_parse_context& ctx)
17 {
18 return ctx.begin();
19 }
20 auto format(const void*& ptr, auto& ctx) const
21 {
22 return std::format_to(ctx.out(), "{}",
23 std::to_string(std::bit_cast<size_t>(ptr)));
24 }
25};
Ed Tanous62598e32023-07-17 17:06:25 -070026// NOLINTEND(readability-convert-member-functions-to-static, cert-dcl58-cpp)
Ed Tanous4d92cbf2017-06-22 15:41:02 -070027
Ed Tanous1abe55e2018-09-05 08:30:59 -070028namespace crow
29{
30enum class LogLevel
31{
Myung Bae662aa6e2023-01-10 14:20:28 -060032 Disabled = 0,
Ed Tanous1abe55e2018-09-05 08:30:59 -070033 Critical,
Ed Tanouse7245fe2023-07-24 17:01:38 -070034 Error,
35 Warning,
36 Info,
37 Debug,
38 Enabled,
Ed Tanous1e439872018-05-18 11:48:52 -070039};
Ed Tanous4d92cbf2017-06-22 15:41:02 -070040
Myung Bae662aa6e2023-01-10 14:20:28 -060041// Mapping of the external loglvl name to internal loglvl
Ed Tanouse7245fe2023-07-24 17:01:38 -070042constexpr std::array<std::string_view, 7> mapLogLevelFromName{
43 "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
Myung Bae662aa6e2023-01-10 14:20:28 -060044
45constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
46{
Ed Tanouse7245fe2023-07-24 17:01:38 -070047 const auto* iter = std::ranges::find(mapLogLevelFromName, name);
48 if (iter != mapLogLevelFromName.end())
Myung Bae662aa6e2023-01-10 14:20:28 -060049 {
Ed Tanouse7245fe2023-07-24 17:01:38 -070050 return static_cast<LogLevel>(iter - mapLogLevelFromName.begin());
Myung Bae662aa6e2023-01-10 14:20:28 -060051 }
52 return crow::LogLevel::Disabled;
53}
54
55// configured bmcweb LogLevel
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070056inline crow::LogLevel& getBmcwebCurrentLoggingLevel()
57{
58 static crow::LogLevel level = getLogLevelFromName(BMCWEB_LOGGING_LEVEL);
59 return level;
60}
61
62struct FormatString
63{
64 std::string_view str;
65 std::source_location loc;
66
67 // NOLINTNEXTLINE(google-explicit-constructor)
68 FormatString(const char* stringIn, const std::source_location& locIn =
69 std::source_location::current()) :
Ed Tanous7a16ddc2024-08-25 12:48:43 -070070 str(stringIn), loc(locIn)
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070071 {}
72};
Myung Bae662aa6e2023-01-10 14:20:28 -060073
Ed Tanous62598e32023-07-17 17:06:25 -070074template <typename T>
75const void* logPtr(T p)
76{
77 static_assert(std::is_pointer<T>::value,
78 "Can't use logPtr without pointer");
79 return std::bit_cast<const void*>(p);
80}
81
Ed Tanous6ea90762024-04-07 08:38:44 -070082template <LogLevel level, typename... Args>
Ed Tanous17c47242024-04-08 17:18:12 -070083inline void vlog(std::format_string<Args...>&& format, Args&&... args,
Ed Tanous6ea90762024-04-07 08:38:44 -070084 const std::source_location& loc) noexcept
Ed Tanous62598e32023-07-17 17:06:25 -070085{
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070086 if (getBmcwebCurrentLoggingLevel() < level)
Ed Tanous62598e32023-07-17 17:06:25 -070087 {
88 return;
89 }
90 constexpr size_t stringIndex = static_cast<size_t>(level);
91 static_assert(stringIndex < mapLogLevelFromName.size(),
92 "Missing string for level");
Ed Tanouse7245fe2023-07-24 17:01:38 -070093 constexpr std::string_view levelString = mapLogLevelFromName[stringIndex];
Ed Tanous6ea90762024-04-07 08:38:44 -070094 std::string_view filename = loc.file_name();
Ed Tanousea5e2242024-08-06 10:28:35 -070095 filename = filename.substr(filename.rfind('/'));
96 if (!filename.empty())
97 {
98 filename.remove_prefix(1);
99 }
Ed Tanous17c47242024-04-08 17:18:12 -0700100 std::string logLocation;
Ed Tanous17c47242024-04-08 17:18:12 -0700101 try
102 {
103 // TODO, multiple static analysis tools flag that this could potentially
104 // throw Based on the documentation, it shouldn't throw, so long as none
105 // of the formatters throw, so unclear at this point why this try/catch
106 // is required, but add it to silence the static analysis tools.
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400107 logLocation =
108 std::format("[{} {}:{}] ", levelString, filename, loc.line());
109 logLocation +=
110 std::format(std::move(format), std::forward<Args>(args)...);
Ed Tanous17c47242024-04-08 17:18:12 -0700111 }
112 catch (const std::format_error& /*error*/)
113 {
114 logLocation += "Failed to format";
115 // Nothing more we can do here if logging is broken.
116 }
117 logLocation += '\n';
118 // Intentionally ignore error return.
119 fwrite(logLocation.data(), sizeof(std::string::value_type),
120 logLocation.size(), stdout);
121 fflush(stdout);
Ed Tanous62598e32023-07-17 17:06:25 -0700122}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700123} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700124
Ed Tanous62598e32023-07-17 17:06:25 -0700125template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700126struct BMCWEB_LOG_CRITICAL
Ed Tanous62598e32023-07-17 17:06:25 -0700127{
Ed Tanous6ea90762024-04-07 08:38:44 -0700128 // NOLINTNEXTLINE(google-explicit-constructor)
129 BMCWEB_LOG_CRITICAL(std::format_string<Args...> format, Args&&... args,
130 const std::source_location& loc =
131 std::source_location::current()) noexcept
132 {
Ed Tanous17c47242024-04-08 17:18:12 -0700133 crow::vlog<crow::LogLevel::Critical, Args...>(
134 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700135 }
136};
Patrick Williamseb8a3992023-05-12 09:57:16 -0500137
Ed Tanous62598e32023-07-17 17:06:25 -0700138template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700139struct BMCWEB_LOG_ERROR
Ed Tanous62598e32023-07-17 17:06:25 -0700140{
Ed Tanous6ea90762024-04-07 08:38:44 -0700141 // NOLINTNEXTLINE(google-explicit-constructor)
142 BMCWEB_LOG_ERROR(std::format_string<Args...> format, Args&&... args,
143 const std::source_location& loc =
144 std::source_location::current()) noexcept
145 {
Ed Tanous17c47242024-04-08 17:18:12 -0700146 crow::vlog<crow::LogLevel::Error, Args...>(
147 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700148 }
149};
Ed Tanous600d2392022-01-07 09:32:03 -0800150
Ed Tanous62598e32023-07-17 17:06:25 -0700151template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700152struct BMCWEB_LOG_WARNING
Ed Tanous62598e32023-07-17 17:06:25 -0700153{
Ed Tanous6ea90762024-04-07 08:38:44 -0700154 // NOLINTNEXTLINE(google-explicit-constructor)
155 BMCWEB_LOG_WARNING(std::format_string<Args...> format, Args&&... args,
156 const std::source_location& loc =
157 std::source_location::current()) noexcept
158 {
Ed Tanous17c47242024-04-08 17:18:12 -0700159 crow::vlog<crow::LogLevel::Warning, Args...>(
160 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700161 }
162};
Ed Tanous600d2392022-01-07 09:32:03 -0800163
Ed Tanous62598e32023-07-17 17:06:25 -0700164template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700165struct BMCWEB_LOG_INFO
Ed Tanous62598e32023-07-17 17:06:25 -0700166{
Ed Tanous6ea90762024-04-07 08:38:44 -0700167 // NOLINTNEXTLINE(google-explicit-constructor)
168 BMCWEB_LOG_INFO(std::format_string<Args...> format, Args&&... args,
169 const std::source_location& loc =
170 std::source_location::current()) noexcept
171 {
Ed Tanous17c47242024-04-08 17:18:12 -0700172 crow::vlog<crow::LogLevel::Info, Args...>(
173 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700174 }
175};
Ed Tanous600d2392022-01-07 09:32:03 -0800176
Ed Tanous62598e32023-07-17 17:06:25 -0700177template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700178struct BMCWEB_LOG_DEBUG
Ed Tanous62598e32023-07-17 17:06:25 -0700179{
Ed Tanous6ea90762024-04-07 08:38:44 -0700180 // NOLINTNEXTLINE(google-explicit-constructor)
181 BMCWEB_LOG_DEBUG(std::format_string<Args...> format, Args&&... args,
182 const std::source_location& loc =
183 std::source_location::current()) noexcept
184 {
Ed Tanous17c47242024-04-08 17:18:12 -0700185 crow::vlog<crow::LogLevel::Debug, Args...>(
186 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700187 }
188};
189
190template <typename... Args>
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400191BMCWEB_LOG_CRITICAL(std::format_string<Args...>,
192 Args&&...) -> BMCWEB_LOG_CRITICAL<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700193
194template <typename... Args>
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400195BMCWEB_LOG_ERROR(std::format_string<Args...>,
196 Args&&...) -> BMCWEB_LOG_ERROR<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700197
198template <typename... Args>
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400199BMCWEB_LOG_WARNING(std::format_string<Args...>,
200 Args&&...) -> BMCWEB_LOG_WARNING<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700201
202template <typename... Args>
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400203BMCWEB_LOG_INFO(std::format_string<Args...>,
204 Args&&...) -> BMCWEB_LOG_INFO<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700205
206template <typename... Args>
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400207BMCWEB_LOG_DEBUG(std::format_string<Args...>,
208 Args&&...) -> BMCWEB_LOG_DEBUG<Args...>;