blob: ed82eb0911b63570286fded5114413fc37c34ec1 [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 Tanousc35475f2025-02-17 14:30:18 -080017#include <utility>
Ed Tanous62598e32023-07-17 17:06:25 -070018
Ed Tanous62598e32023-07-17 17:06:25 -070019// NOLINTBEGIN(readability-convert-member-functions-to-static, cert-dcl58-cpp)
20template <>
Ed Tanous62598e32023-07-17 17:06:25 -070021struct std::formatter<void*>
22{
23 constexpr auto parse(std::format_parse_context& ctx)
24 {
25 return ctx.begin();
26 }
27 auto format(const void*& ptr, auto& ctx) const
28 {
29 return std::format_to(ctx.out(), "{}",
30 std::to_string(std::bit_cast<size_t>(ptr)));
31 }
32};
Ed Tanous62598e32023-07-17 17:06:25 -070033// NOLINTEND(readability-convert-member-functions-to-static, cert-dcl58-cpp)
Ed Tanous4d92cbf2017-06-22 15:41:02 -070034
Ed Tanous1abe55e2018-09-05 08:30:59 -070035namespace crow
36{
37enum class LogLevel
38{
Myung Bae662aa6e2023-01-10 14:20:28 -060039 Disabled = 0,
Ed Tanous1abe55e2018-09-05 08:30:59 -070040 Critical,
Ed Tanouse7245fe2023-07-24 17:01:38 -070041 Error,
42 Warning,
43 Info,
44 Debug,
45 Enabled,
Ed Tanous1e439872018-05-18 11:48:52 -070046};
Ed Tanous4d92cbf2017-06-22 15:41:02 -070047
Ed Tanousee993dc2024-11-19 19:52:46 -080048constexpr int toSystemdLevel(LogLevel level)
49{
Ed Tanousc35475f2025-02-17 14:30:18 -080050 constexpr std::array<std::pair<LogLevel, int>, 5> mapping{
Ed Tanousee993dc2024-11-19 19:52:46 -080051 {// EMERGENCY 0
52 // ALERT 1
53 {LogLevel::Critical, 2},
54 {LogLevel::Error, 3},
55 {LogLevel::Warning, 4},
56 // NOTICE 5
57 {LogLevel::Info, 6},
Ed Tanousab00bd82025-03-03 10:30:50 -080058 // Note, debug here is actually mapped to info level, because OpenBMC
59 // has a MaxLevelSyslog and MaxLevelStore of info, so DEBUG level will
60 // never be stored.
61 {LogLevel::Debug, 6}}};
Ed Tanousee993dc2024-11-19 19:52:46 -080062
Ed Tanousc35475f2025-02-17 14:30:18 -080063 const auto* it = std::ranges::find_if(
Ed Tanousee993dc2024-11-19 19:52:46 -080064 mapping, [level](const std::pair<LogLevel, int>& elem) {
65 return elem.first == level;
66 });
67
68 // Unknown log level. Just assume debug
69 if (it != mapping.end())
70 {
Ed Tanousab00bd82025-03-03 10:30:50 -080071 return 6;
Ed Tanousee993dc2024-11-19 19:52:46 -080072 }
73
74 return it->second;
75}
76
Myung Bae662aa6e2023-01-10 14:20:28 -060077// Mapping of the external loglvl name to internal loglvl
Ed Tanouse7245fe2023-07-24 17:01:38 -070078constexpr std::array<std::string_view, 7> mapLogLevelFromName{
79 "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
Myung Bae662aa6e2023-01-10 14:20:28 -060080
81constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
82{
Ed Tanouse7245fe2023-07-24 17:01:38 -070083 const auto* iter = std::ranges::find(mapLogLevelFromName, name);
84 if (iter != mapLogLevelFromName.end())
Myung Bae662aa6e2023-01-10 14:20:28 -060085 {
Ed Tanouse7245fe2023-07-24 17:01:38 -070086 return static_cast<LogLevel>(iter - mapLogLevelFromName.begin());
Myung Bae662aa6e2023-01-10 14:20:28 -060087 }
88 return crow::LogLevel::Disabled;
89}
90
91// configured bmcweb LogLevel
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070092inline crow::LogLevel& getBmcwebCurrentLoggingLevel()
93{
94 static crow::LogLevel level = getLogLevelFromName(BMCWEB_LOGGING_LEVEL);
95 return level;
96}
97
98struct FormatString
99{
100 std::string_view str;
101 std::source_location loc;
102
103 // NOLINTNEXTLINE(google-explicit-constructor)
104 FormatString(const char* stringIn, const std::source_location& locIn =
105 std::source_location::current()) :
Ed Tanous7a16ddc2024-08-25 12:48:43 -0700106 str(stringIn), loc(locIn)
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -0700107 {}
108};
Myung Bae662aa6e2023-01-10 14:20:28 -0600109
Ed Tanous62598e32023-07-17 17:06:25 -0700110template <typename T>
111const void* logPtr(T p)
112{
113 static_assert(std::is_pointer<T>::value,
114 "Can't use logPtr without pointer");
115 return std::bit_cast<const void*>(p);
116}
117
Ed Tanous6ea90762024-04-07 08:38:44 -0700118template <LogLevel level, typename... Args>
Ed Tanous17c47242024-04-08 17:18:12 -0700119inline void vlog(std::format_string<Args...>&& format, Args&&... args,
Ed Tanous6ea90762024-04-07 08:38:44 -0700120 const std::source_location& loc) noexcept
Ed Tanous62598e32023-07-17 17:06:25 -0700121{
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -0700122 if (getBmcwebCurrentLoggingLevel() < level)
Ed Tanous62598e32023-07-17 17:06:25 -0700123 {
124 return;
125 }
Ed Tanousee993dc2024-11-19 19:52:46 -0800126 constexpr int systemdLevel = toSystemdLevel(level);
Ed Tanous6ea90762024-04-07 08:38:44 -0700127 std::string_view filename = loc.file_name();
Ed Tanousea5e2242024-08-06 10:28:35 -0700128 filename = filename.substr(filename.rfind('/'));
129 if (!filename.empty())
130 {
131 filename.remove_prefix(1);
132 }
Ed Tanous17c47242024-04-08 17:18:12 -0700133 std::string logLocation;
Ed Tanous17c47242024-04-08 17:18:12 -0700134 try
135 {
136 // TODO, multiple static analysis tools flag that this could potentially
137 // throw Based on the documentation, it shouldn't throw, so long as none
138 // of the formatters throw, so unclear at this point why this try/catch
139 // is required, but add it to silence the static analysis tools.
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400140 logLocation =
Ed Tanousee993dc2024-11-19 19:52:46 -0800141 std::format("<{}>[{}:{}] ", systemdLevel, filename, loc.line());
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400142 logLocation +=
143 std::format(std::move(format), std::forward<Args>(args)...);
Ed Tanous17c47242024-04-08 17:18:12 -0700144 }
145 catch (const std::format_error& /*error*/)
146 {
147 logLocation += "Failed to format";
148 // Nothing more we can do here if logging is broken.
149 }
150 logLocation += '\n';
151 // Intentionally ignore error return.
152 fwrite(logLocation.data(), sizeof(std::string::value_type),
153 logLocation.size(), stdout);
154 fflush(stdout);
Ed Tanous62598e32023-07-17 17:06:25 -0700155}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700156} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700157
Ed Tanous62598e32023-07-17 17:06:25 -0700158template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700159struct BMCWEB_LOG_CRITICAL
Ed Tanous62598e32023-07-17 17:06:25 -0700160{
Ed Tanous6ea90762024-04-07 08:38:44 -0700161 // NOLINTNEXTLINE(google-explicit-constructor)
162 BMCWEB_LOG_CRITICAL(std::format_string<Args...> format, Args&&... args,
163 const std::source_location& loc =
164 std::source_location::current()) noexcept
165 {
Ed Tanous17c47242024-04-08 17:18:12 -0700166 crow::vlog<crow::LogLevel::Critical, Args...>(
167 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700168 }
169};
Patrick Williamseb8a3992023-05-12 09:57:16 -0500170
Ed Tanous62598e32023-07-17 17:06:25 -0700171template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700172struct BMCWEB_LOG_ERROR
Ed Tanous62598e32023-07-17 17:06:25 -0700173{
Ed Tanous6ea90762024-04-07 08:38:44 -0700174 // NOLINTNEXTLINE(google-explicit-constructor)
175 BMCWEB_LOG_ERROR(std::format_string<Args...> format, Args&&... args,
176 const std::source_location& loc =
177 std::source_location::current()) noexcept
178 {
Ed Tanous17c47242024-04-08 17:18:12 -0700179 crow::vlog<crow::LogLevel::Error, Args...>(
180 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700181 }
182};
Ed Tanous600d2392022-01-07 09:32:03 -0800183
Ed Tanous62598e32023-07-17 17:06:25 -0700184template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700185struct BMCWEB_LOG_WARNING
Ed Tanous62598e32023-07-17 17:06:25 -0700186{
Ed Tanous6ea90762024-04-07 08:38:44 -0700187 // NOLINTNEXTLINE(google-explicit-constructor)
188 BMCWEB_LOG_WARNING(std::format_string<Args...> format, Args&&... args,
189 const std::source_location& loc =
190 std::source_location::current()) noexcept
191 {
Ed Tanous17c47242024-04-08 17:18:12 -0700192 crow::vlog<crow::LogLevel::Warning, Args...>(
193 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700194 }
195};
Ed Tanous600d2392022-01-07 09:32:03 -0800196
Ed Tanous62598e32023-07-17 17:06:25 -0700197template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700198struct BMCWEB_LOG_INFO
Ed Tanous62598e32023-07-17 17:06:25 -0700199{
Ed Tanous6ea90762024-04-07 08:38:44 -0700200 // NOLINTNEXTLINE(google-explicit-constructor)
201 BMCWEB_LOG_INFO(std::format_string<Args...> format, Args&&... args,
202 const std::source_location& loc =
203 std::source_location::current()) noexcept
204 {
Ed Tanous17c47242024-04-08 17:18:12 -0700205 crow::vlog<crow::LogLevel::Info, Args...>(
206 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700207 }
208};
Ed Tanous600d2392022-01-07 09:32:03 -0800209
Ed Tanous62598e32023-07-17 17:06:25 -0700210template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700211struct BMCWEB_LOG_DEBUG
Ed Tanous62598e32023-07-17 17:06:25 -0700212{
Ed Tanous6ea90762024-04-07 08:38:44 -0700213 // NOLINTNEXTLINE(google-explicit-constructor)
214 BMCWEB_LOG_DEBUG(std::format_string<Args...> format, Args&&... args,
215 const std::source_location& loc =
216 std::source_location::current()) noexcept
217 {
Ed Tanous17c47242024-04-08 17:18:12 -0700218 crow::vlog<crow::LogLevel::Debug, Args...>(
219 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700220 }
221};
222
223template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800224BMCWEB_LOG_CRITICAL(std::format_string<Args...>, Args&&...)
225 -> BMCWEB_LOG_CRITICAL<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700226
227template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800228BMCWEB_LOG_ERROR(std::format_string<Args...>, Args&&...)
229 -> BMCWEB_LOG_ERROR<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700230
231template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800232BMCWEB_LOG_WARNING(std::format_string<Args...>, Args&&...)
233 -> BMCWEB_LOG_WARNING<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700234
235template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800236BMCWEB_LOG_INFO(std::format_string<Args...>, Args&&...)
237 -> BMCWEB_LOG_INFO<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700238
239template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800240BMCWEB_LOG_DEBUG(std::format_string<Args...>, Args&&...)
241 -> BMCWEB_LOG_DEBUG<Args...>;