blob: 0671577d4f3d3be8f25ccf60da2dbadfd7144c70 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Ed Tanous7045c8d2017-04-03 10:04:37 -07003#pragma once
4
Myung Bae662aa6e2023-01-10 14:20:28 -06005#include "bmcweb_config.h"
6
Ed Tanousd7857202025-01-28 15:32:26 -08007#include <algorithm>
8#include <array>
Ed Tanous62598e32023-07-17 17:06:25 -07009#include <bit>
Ed Tanousd7857202025-01-28 15:32:26 -080010#include <cstddef>
11#include <cstdio>
Ed Tanous62598e32023-07-17 17:06:25 -070012#include <format>
Ed Tanous62598e32023-07-17 17:06:25 -070013#include <source_location>
Ed Tanousd7857202025-01-28 15:32:26 -080014#include <string>
Myung Bae662aa6e2023-01-10 14:20:28 -060015#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080016#include <type_traits>
Ed Tanous62598e32023-07-17 17:06:25 -070017
Ed Tanous62598e32023-07-17 17:06:25 -070018// NOLINTBEGIN(readability-convert-member-functions-to-static, cert-dcl58-cpp)
19template <>
Ed Tanous62598e32023-07-17 17:06:25 -070020struct std::formatter<void*>
21{
22 constexpr auto parse(std::format_parse_context& ctx)
23 {
24 return ctx.begin();
25 }
26 auto format(const void*& ptr, auto& ctx) const
27 {
28 return std::format_to(ctx.out(), "{}",
29 std::to_string(std::bit_cast<size_t>(ptr)));
30 }
31};
Ed Tanous62598e32023-07-17 17:06:25 -070032// NOLINTEND(readability-convert-member-functions-to-static, cert-dcl58-cpp)
Ed Tanous4d92cbf2017-06-22 15:41:02 -070033
Ed Tanous1abe55e2018-09-05 08:30:59 -070034namespace crow
35{
36enum class LogLevel
37{
Myung Bae662aa6e2023-01-10 14:20:28 -060038 Disabled = 0,
Ed Tanous1abe55e2018-09-05 08:30:59 -070039 Critical,
Ed Tanouse7245fe2023-07-24 17:01:38 -070040 Error,
41 Warning,
42 Info,
43 Debug,
44 Enabled,
Ed Tanous1e439872018-05-18 11:48:52 -070045};
Ed Tanous4d92cbf2017-06-22 15:41:02 -070046
Ed Tanousee993dc2024-11-19 19:52:46 -080047constexpr int toSystemdLevel(LogLevel level)
48{
49 std::array<std::pair<LogLevel, int>, 5> mapping{
50 {// EMERGENCY 0
51 // ALERT 1
52 {LogLevel::Critical, 2},
53 {LogLevel::Error, 3},
54 {LogLevel::Warning, 4},
55 // NOTICE 5
56 {LogLevel::Info, 6},
57 {LogLevel::Debug, 7}}};
58
59 auto* it = std::ranges::find_if(
60 mapping, [level](const std::pair<LogLevel, int>& elem) {
61 return elem.first == level;
62 });
63
64 // Unknown log level. Just assume debug
65 if (it != mapping.end())
66 {
67 return 7;
68 }
69
70 return it->second;
71}
72
Myung Bae662aa6e2023-01-10 14:20:28 -060073// Mapping of the external loglvl name to internal loglvl
Ed Tanouse7245fe2023-07-24 17:01:38 -070074constexpr std::array<std::string_view, 7> mapLogLevelFromName{
75 "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
Myung Bae662aa6e2023-01-10 14:20:28 -060076
77constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
78{
Ed Tanouse7245fe2023-07-24 17:01:38 -070079 const auto* iter = std::ranges::find(mapLogLevelFromName, name);
80 if (iter != mapLogLevelFromName.end())
Myung Bae662aa6e2023-01-10 14:20:28 -060081 {
Ed Tanouse7245fe2023-07-24 17:01:38 -070082 return static_cast<LogLevel>(iter - mapLogLevelFromName.begin());
Myung Bae662aa6e2023-01-10 14:20:28 -060083 }
84 return crow::LogLevel::Disabled;
85}
86
87// configured bmcweb LogLevel
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070088inline crow::LogLevel& getBmcwebCurrentLoggingLevel()
89{
90 static crow::LogLevel level = getLogLevelFromName(BMCWEB_LOGGING_LEVEL);
91 return level;
92}
93
94struct FormatString
95{
96 std::string_view str;
97 std::source_location loc;
98
99 // NOLINTNEXTLINE(google-explicit-constructor)
100 FormatString(const char* stringIn, const std::source_location& locIn =
101 std::source_location::current()) :
Ed Tanous7a16ddc2024-08-25 12:48:43 -0700102 str(stringIn), loc(locIn)
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -0700103 {}
104};
Myung Bae662aa6e2023-01-10 14:20:28 -0600105
Ed Tanous62598e32023-07-17 17:06:25 -0700106template <typename T>
107const void* logPtr(T p)
108{
109 static_assert(std::is_pointer<T>::value,
110 "Can't use logPtr without pointer");
111 return std::bit_cast<const void*>(p);
112}
113
Ed Tanous6ea90762024-04-07 08:38:44 -0700114template <LogLevel level, typename... Args>
Ed Tanous17c47242024-04-08 17:18:12 -0700115inline void vlog(std::format_string<Args...>&& format, Args&&... args,
Ed Tanous6ea90762024-04-07 08:38:44 -0700116 const std::source_location& loc) noexcept
Ed Tanous62598e32023-07-17 17:06:25 -0700117{
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -0700118 if (getBmcwebCurrentLoggingLevel() < level)
Ed Tanous62598e32023-07-17 17:06:25 -0700119 {
120 return;
121 }
Ed Tanousee993dc2024-11-19 19:52:46 -0800122 constexpr int systemdLevel = toSystemdLevel(level);
Ed Tanous6ea90762024-04-07 08:38:44 -0700123 std::string_view filename = loc.file_name();
Ed Tanousea5e2242024-08-06 10:28:35 -0700124 filename = filename.substr(filename.rfind('/'));
125 if (!filename.empty())
126 {
127 filename.remove_prefix(1);
128 }
Ed Tanous17c47242024-04-08 17:18:12 -0700129 std::string logLocation;
Ed Tanous17c47242024-04-08 17:18:12 -0700130 try
131 {
132 // TODO, multiple static analysis tools flag that this could potentially
133 // throw Based on the documentation, it shouldn't throw, so long as none
134 // of the formatters throw, so unclear at this point why this try/catch
135 // is required, but add it to silence the static analysis tools.
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400136 logLocation =
Ed Tanousee993dc2024-11-19 19:52:46 -0800137 std::format("<{}>[{}:{}] ", systemdLevel, filename, loc.line());
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400138 logLocation +=
139 std::format(std::move(format), std::forward<Args>(args)...);
Ed Tanous17c47242024-04-08 17:18:12 -0700140 }
141 catch (const std::format_error& /*error*/)
142 {
143 logLocation += "Failed to format";
144 // Nothing more we can do here if logging is broken.
145 }
146 logLocation += '\n';
147 // Intentionally ignore error return.
148 fwrite(logLocation.data(), sizeof(std::string::value_type),
149 logLocation.size(), stdout);
150 fflush(stdout);
Ed Tanous62598e32023-07-17 17:06:25 -0700151}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700152} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700153
Ed Tanous62598e32023-07-17 17:06:25 -0700154template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700155struct BMCWEB_LOG_CRITICAL
Ed Tanous62598e32023-07-17 17:06:25 -0700156{
Ed Tanous6ea90762024-04-07 08:38:44 -0700157 // NOLINTNEXTLINE(google-explicit-constructor)
158 BMCWEB_LOG_CRITICAL(std::format_string<Args...> format, Args&&... args,
159 const std::source_location& loc =
160 std::source_location::current()) noexcept
161 {
Ed Tanous17c47242024-04-08 17:18:12 -0700162 crow::vlog<crow::LogLevel::Critical, Args...>(
163 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700164 }
165};
Patrick Williamseb8a3992023-05-12 09:57:16 -0500166
Ed Tanous62598e32023-07-17 17:06:25 -0700167template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700168struct BMCWEB_LOG_ERROR
Ed Tanous62598e32023-07-17 17:06:25 -0700169{
Ed Tanous6ea90762024-04-07 08:38:44 -0700170 // NOLINTNEXTLINE(google-explicit-constructor)
171 BMCWEB_LOG_ERROR(std::format_string<Args...> format, Args&&... args,
172 const std::source_location& loc =
173 std::source_location::current()) noexcept
174 {
Ed Tanous17c47242024-04-08 17:18:12 -0700175 crow::vlog<crow::LogLevel::Error, Args...>(
176 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700177 }
178};
Ed Tanous600d2392022-01-07 09:32:03 -0800179
Ed Tanous62598e32023-07-17 17:06:25 -0700180template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700181struct BMCWEB_LOG_WARNING
Ed Tanous62598e32023-07-17 17:06:25 -0700182{
Ed Tanous6ea90762024-04-07 08:38:44 -0700183 // NOLINTNEXTLINE(google-explicit-constructor)
184 BMCWEB_LOG_WARNING(std::format_string<Args...> format, Args&&... args,
185 const std::source_location& loc =
186 std::source_location::current()) noexcept
187 {
Ed Tanous17c47242024-04-08 17:18:12 -0700188 crow::vlog<crow::LogLevel::Warning, Args...>(
189 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700190 }
191};
Ed Tanous600d2392022-01-07 09:32:03 -0800192
Ed Tanous62598e32023-07-17 17:06:25 -0700193template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700194struct BMCWEB_LOG_INFO
Ed Tanous62598e32023-07-17 17:06:25 -0700195{
Ed Tanous6ea90762024-04-07 08:38:44 -0700196 // NOLINTNEXTLINE(google-explicit-constructor)
197 BMCWEB_LOG_INFO(std::format_string<Args...> format, Args&&... args,
198 const std::source_location& loc =
199 std::source_location::current()) noexcept
200 {
Ed Tanous17c47242024-04-08 17:18:12 -0700201 crow::vlog<crow::LogLevel::Info, Args...>(
202 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700203 }
204};
Ed Tanous600d2392022-01-07 09:32:03 -0800205
Ed Tanous62598e32023-07-17 17:06:25 -0700206template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700207struct BMCWEB_LOG_DEBUG
Ed Tanous62598e32023-07-17 17:06:25 -0700208{
Ed Tanous6ea90762024-04-07 08:38:44 -0700209 // NOLINTNEXTLINE(google-explicit-constructor)
210 BMCWEB_LOG_DEBUG(std::format_string<Args...> format, Args&&... args,
211 const std::source_location& loc =
212 std::source_location::current()) noexcept
213 {
Ed Tanous17c47242024-04-08 17:18:12 -0700214 crow::vlog<crow::LogLevel::Debug, Args...>(
215 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700216 }
217};
218
219template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800220BMCWEB_LOG_CRITICAL(std::format_string<Args...>, Args&&...)
221 -> BMCWEB_LOG_CRITICAL<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700222
223template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800224BMCWEB_LOG_ERROR(std::format_string<Args...>, Args&&...)
225 -> BMCWEB_LOG_ERROR<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700226
227template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800228BMCWEB_LOG_WARNING(std::format_string<Args...>, Args&&...)
229 -> BMCWEB_LOG_WARNING<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700230
231template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800232BMCWEB_LOG_INFO(std::format_string<Args...>, Args&&...)
233 -> BMCWEB_LOG_INFO<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700234
235template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800236BMCWEB_LOG_DEBUG(std::format_string<Args...>, Args&&...)
237 -> BMCWEB_LOG_DEBUG<Args...>;