blob: 1028ca6e7bd896f27e61c94a144a59d1b879eb66 [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 Tanous62598e32023-07-17 17:06:25 -07007#include <bit>
8#include <format>
Ed Tanous4d92cbf2017-06-22 15:41:02 -07009#include <iostream>
Ed Tanous62598e32023-07-17 17:06:25 -070010#include <source_location>
Myung Bae662aa6e2023-01-10 14:20:28 -060011#include <string_view>
Ed Tanous62598e32023-07-17 17:06:25 -070012#include <system_error>
13
Ed Tanous62598e32023-07-17 17:06:25 -070014// NOLINTBEGIN(readability-convert-member-functions-to-static, cert-dcl58-cpp)
15template <>
Ed Tanous62598e32023-07-17 17:06:25 -070016struct std::formatter<void*>
17{
18 constexpr auto parse(std::format_parse_context& ctx)
19 {
20 return ctx.begin();
21 }
22 auto format(const void*& ptr, auto& ctx) const
23 {
24 return std::format_to(ctx.out(), "{}",
25 std::to_string(std::bit_cast<size_t>(ptr)));
26 }
27};
Ed Tanous62598e32023-07-17 17:06:25 -070028// NOLINTEND(readability-convert-member-functions-to-static, cert-dcl58-cpp)
Ed Tanous4d92cbf2017-06-22 15:41:02 -070029
Ed Tanous1abe55e2018-09-05 08:30:59 -070030namespace crow
31{
32enum class LogLevel
33{
Myung Bae662aa6e2023-01-10 14:20:28 -060034 Disabled = 0,
Ed Tanous1abe55e2018-09-05 08:30:59 -070035 Critical,
Ed Tanouse7245fe2023-07-24 17:01:38 -070036 Error,
37 Warning,
38 Info,
39 Debug,
40 Enabled,
Ed Tanous1e439872018-05-18 11:48:52 -070041};
Ed Tanous4d92cbf2017-06-22 15:41:02 -070042
Myung Bae662aa6e2023-01-10 14:20:28 -060043// Mapping of the external loglvl name to internal loglvl
Ed Tanouse7245fe2023-07-24 17:01:38 -070044constexpr std::array<std::string_view, 7> mapLogLevelFromName{
45 "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
Myung Bae662aa6e2023-01-10 14:20:28 -060046
47constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
48{
Ed Tanouse7245fe2023-07-24 17:01:38 -070049 const auto* iter = std::ranges::find(mapLogLevelFromName, name);
50 if (iter != mapLogLevelFromName.end())
Myung Bae662aa6e2023-01-10 14:20:28 -060051 {
Ed Tanouse7245fe2023-07-24 17:01:38 -070052 return static_cast<LogLevel>(iter - mapLogLevelFromName.begin());
Myung Bae662aa6e2023-01-10 14:20:28 -060053 }
54 return crow::LogLevel::Disabled;
55}
56
57// configured bmcweb LogLevel
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070058inline crow::LogLevel& getBmcwebCurrentLoggingLevel()
59{
60 static crow::LogLevel level = getLogLevelFromName(BMCWEB_LOGGING_LEVEL);
61 return level;
62}
63
64struct FormatString
65{
66 std::string_view str;
67 std::source_location loc;
68
69 // NOLINTNEXTLINE(google-explicit-constructor)
70 FormatString(const char* stringIn, const std::source_location& locIn =
71 std::source_location::current()) :
Ed Tanous7a16ddc2024-08-25 12:48:43 -070072 str(stringIn), loc(locIn)
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070073 {}
74};
Myung Bae662aa6e2023-01-10 14:20:28 -060075
Ed Tanous62598e32023-07-17 17:06:25 -070076template <typename T>
77const void* logPtr(T p)
78{
79 static_assert(std::is_pointer<T>::value,
80 "Can't use logPtr without pointer");
81 return std::bit_cast<const void*>(p);
82}
83
Ed Tanous6ea90762024-04-07 08:38:44 -070084template <LogLevel level, typename... Args>
Ed Tanous17c47242024-04-08 17:18:12 -070085inline void vlog(std::format_string<Args...>&& format, Args&&... args,
Ed Tanous6ea90762024-04-07 08:38:44 -070086 const std::source_location& loc) noexcept
Ed Tanous62598e32023-07-17 17:06:25 -070087{
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070088 if (getBmcwebCurrentLoggingLevel() < level)
Ed Tanous62598e32023-07-17 17:06:25 -070089 {
90 return;
91 }
92 constexpr size_t stringIndex = static_cast<size_t>(level);
93 static_assert(stringIndex < mapLogLevelFromName.size(),
94 "Missing string for level");
Ed Tanouse7245fe2023-07-24 17:01:38 -070095 constexpr std::string_view levelString = mapLogLevelFromName[stringIndex];
Ed Tanous6ea90762024-04-07 08:38:44 -070096 std::string_view filename = loc.file_name();
Ed Tanousea5e2242024-08-06 10:28:35 -070097 filename = filename.substr(filename.rfind('/'));
98 if (!filename.empty())
99 {
100 filename.remove_prefix(1);
101 }
Ed Tanous17c47242024-04-08 17:18:12 -0700102 std::string logLocation;
Ed Tanous17c47242024-04-08 17:18:12 -0700103 try
104 {
105 // TODO, multiple static analysis tools flag that this could potentially
106 // throw Based on the documentation, it shouldn't throw, so long as none
107 // of the formatters throw, so unclear at this point why this try/catch
108 // is required, but add it to silence the static analysis tools.
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400109 logLocation =
110 std::format("[{} {}:{}] ", levelString, filename, loc.line());
111 logLocation +=
112 std::format(std::move(format), std::forward<Args>(args)...);
Ed Tanous17c47242024-04-08 17:18:12 -0700113 }
114 catch (const std::format_error& /*error*/)
115 {
116 logLocation += "Failed to format";
117 // Nothing more we can do here if logging is broken.
118 }
119 logLocation += '\n';
120 // Intentionally ignore error return.
121 fwrite(logLocation.data(), sizeof(std::string::value_type),
122 logLocation.size(), stdout);
123 fflush(stdout);
Ed Tanous62598e32023-07-17 17:06:25 -0700124}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700125} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700126
Ed Tanous62598e32023-07-17 17:06:25 -0700127template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700128struct BMCWEB_LOG_CRITICAL
Ed Tanous62598e32023-07-17 17:06:25 -0700129{
Ed Tanous6ea90762024-04-07 08:38:44 -0700130 // NOLINTNEXTLINE(google-explicit-constructor)
131 BMCWEB_LOG_CRITICAL(std::format_string<Args...> format, Args&&... args,
132 const std::source_location& loc =
133 std::source_location::current()) noexcept
134 {
Ed Tanous17c47242024-04-08 17:18:12 -0700135 crow::vlog<crow::LogLevel::Critical, Args...>(
136 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700137 }
138};
Patrick Williamseb8a3992023-05-12 09:57:16 -0500139
Ed Tanous62598e32023-07-17 17:06:25 -0700140template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700141struct BMCWEB_LOG_ERROR
Ed Tanous62598e32023-07-17 17:06:25 -0700142{
Ed Tanous6ea90762024-04-07 08:38:44 -0700143 // NOLINTNEXTLINE(google-explicit-constructor)
144 BMCWEB_LOG_ERROR(std::format_string<Args...> format, Args&&... args,
145 const std::source_location& loc =
146 std::source_location::current()) noexcept
147 {
Ed Tanous17c47242024-04-08 17:18:12 -0700148 crow::vlog<crow::LogLevel::Error, Args...>(
149 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700150 }
151};
Ed Tanous600d2392022-01-07 09:32:03 -0800152
Ed Tanous62598e32023-07-17 17:06:25 -0700153template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700154struct BMCWEB_LOG_WARNING
Ed Tanous62598e32023-07-17 17:06:25 -0700155{
Ed Tanous6ea90762024-04-07 08:38:44 -0700156 // NOLINTNEXTLINE(google-explicit-constructor)
157 BMCWEB_LOG_WARNING(std::format_string<Args...> format, Args&&... args,
158 const std::source_location& loc =
159 std::source_location::current()) noexcept
160 {
Ed Tanous17c47242024-04-08 17:18:12 -0700161 crow::vlog<crow::LogLevel::Warning, Args...>(
162 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700163 }
164};
Ed Tanous600d2392022-01-07 09:32:03 -0800165
Ed Tanous62598e32023-07-17 17:06:25 -0700166template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700167struct BMCWEB_LOG_INFO
Ed Tanous62598e32023-07-17 17:06:25 -0700168{
Ed Tanous6ea90762024-04-07 08:38:44 -0700169 // NOLINTNEXTLINE(google-explicit-constructor)
170 BMCWEB_LOG_INFO(std::format_string<Args...> format, Args&&... args,
171 const std::source_location& loc =
172 std::source_location::current()) noexcept
173 {
Ed Tanous17c47242024-04-08 17:18:12 -0700174 crow::vlog<crow::LogLevel::Info, Args...>(
175 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700176 }
177};
Ed Tanous600d2392022-01-07 09:32:03 -0800178
Ed Tanous62598e32023-07-17 17:06:25 -0700179template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700180struct BMCWEB_LOG_DEBUG
Ed Tanous62598e32023-07-17 17:06:25 -0700181{
Ed Tanous6ea90762024-04-07 08:38:44 -0700182 // NOLINTNEXTLINE(google-explicit-constructor)
183 BMCWEB_LOG_DEBUG(std::format_string<Args...> format, Args&&... args,
184 const std::source_location& loc =
185 std::source_location::current()) noexcept
186 {
Ed Tanous17c47242024-04-08 17:18:12 -0700187 crow::vlog<crow::LogLevel::Debug, Args...>(
188 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700189 }
190};
191
192template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800193BMCWEB_LOG_CRITICAL(std::format_string<Args...>, Args&&...)
194 -> BMCWEB_LOG_CRITICAL<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700195
196template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800197BMCWEB_LOG_ERROR(std::format_string<Args...>, Args&&...)
198 -> BMCWEB_LOG_ERROR<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700199
200template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800201BMCWEB_LOG_WARNING(std::format_string<Args...>, Args&&...)
202 -> BMCWEB_LOG_WARNING<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700203
204template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800205BMCWEB_LOG_INFO(std::format_string<Args...>, Args&&...)
206 -> BMCWEB_LOG_INFO<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700207
208template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800209BMCWEB_LOG_DEBUG(std::format_string<Args...>, Args&&...)
210 -> BMCWEB_LOG_DEBUG<Args...>;