blob: a8d85e2ee6fdbbe2b5625e28ce859d4327a6ed2a [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
Myung Bae662aa6e2023-01-10 14:20:28 -060047// Mapping of the external loglvl name to internal loglvl
Ed Tanouse7245fe2023-07-24 17:01:38 -070048constexpr std::array<std::string_view, 7> mapLogLevelFromName{
49 "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
Myung Bae662aa6e2023-01-10 14:20:28 -060050
51constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
52{
Ed Tanouse7245fe2023-07-24 17:01:38 -070053 const auto* iter = std::ranges::find(mapLogLevelFromName, name);
54 if (iter != mapLogLevelFromName.end())
Myung Bae662aa6e2023-01-10 14:20:28 -060055 {
Ed Tanouse7245fe2023-07-24 17:01:38 -070056 return static_cast<LogLevel>(iter - mapLogLevelFromName.begin());
Myung Bae662aa6e2023-01-10 14:20:28 -060057 }
58 return crow::LogLevel::Disabled;
59}
60
61// configured bmcweb LogLevel
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070062inline crow::LogLevel& getBmcwebCurrentLoggingLevel()
63{
64 static crow::LogLevel level = getLogLevelFromName(BMCWEB_LOGGING_LEVEL);
65 return level;
66}
67
68struct FormatString
69{
70 std::string_view str;
71 std::source_location loc;
72
73 // NOLINTNEXTLINE(google-explicit-constructor)
74 FormatString(const char* stringIn, const std::source_location& locIn =
75 std::source_location::current()) :
Ed Tanous7a16ddc2024-08-25 12:48:43 -070076 str(stringIn), loc(locIn)
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070077 {}
78};
Myung Bae662aa6e2023-01-10 14:20:28 -060079
Ed Tanous62598e32023-07-17 17:06:25 -070080template <typename T>
81const void* logPtr(T p)
82{
83 static_assert(std::is_pointer<T>::value,
84 "Can't use logPtr without pointer");
85 return std::bit_cast<const void*>(p);
86}
87
Ed Tanous6ea90762024-04-07 08:38:44 -070088template <LogLevel level, typename... Args>
Ed Tanous17c47242024-04-08 17:18:12 -070089inline void vlog(std::format_string<Args...>&& format, Args&&... args,
Ed Tanous6ea90762024-04-07 08:38:44 -070090 const std::source_location& loc) noexcept
Ed Tanous62598e32023-07-17 17:06:25 -070091{
Aushim Nagarkattibd1299b2024-08-12 17:11:04 -070092 if (getBmcwebCurrentLoggingLevel() < level)
Ed Tanous62598e32023-07-17 17:06:25 -070093 {
94 return;
95 }
96 constexpr size_t stringIndex = static_cast<size_t>(level);
97 static_assert(stringIndex < mapLogLevelFromName.size(),
98 "Missing string for level");
Ed Tanouse7245fe2023-07-24 17:01:38 -070099 constexpr std::string_view levelString = mapLogLevelFromName[stringIndex];
Ed Tanous6ea90762024-04-07 08:38:44 -0700100 std::string_view filename = loc.file_name();
Ed Tanousea5e2242024-08-06 10:28:35 -0700101 filename = filename.substr(filename.rfind('/'));
102 if (!filename.empty())
103 {
104 filename.remove_prefix(1);
105 }
Ed Tanous17c47242024-04-08 17:18:12 -0700106 std::string logLocation;
Ed Tanous17c47242024-04-08 17:18:12 -0700107 try
108 {
109 // TODO, multiple static analysis tools flag that this could potentially
110 // throw Based on the documentation, it shouldn't throw, so long as none
111 // of the formatters throw, so unclear at this point why this try/catch
112 // is required, but add it to silence the static analysis tools.
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400113 logLocation =
114 std::format("[{} {}:{}] ", levelString, filename, loc.line());
115 logLocation +=
116 std::format(std::move(format), std::forward<Args>(args)...);
Ed Tanous17c47242024-04-08 17:18:12 -0700117 }
118 catch (const std::format_error& /*error*/)
119 {
120 logLocation += "Failed to format";
121 // Nothing more we can do here if logging is broken.
122 }
123 logLocation += '\n';
124 // Intentionally ignore error return.
125 fwrite(logLocation.data(), sizeof(std::string::value_type),
126 logLocation.size(), stdout);
127 fflush(stdout);
Ed Tanous62598e32023-07-17 17:06:25 -0700128}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700129} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700130
Ed Tanous62598e32023-07-17 17:06:25 -0700131template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700132struct BMCWEB_LOG_CRITICAL
Ed Tanous62598e32023-07-17 17:06:25 -0700133{
Ed Tanous6ea90762024-04-07 08:38:44 -0700134 // NOLINTNEXTLINE(google-explicit-constructor)
135 BMCWEB_LOG_CRITICAL(std::format_string<Args...> format, Args&&... args,
136 const std::source_location& loc =
137 std::source_location::current()) noexcept
138 {
Ed Tanous17c47242024-04-08 17:18:12 -0700139 crow::vlog<crow::LogLevel::Critical, Args...>(
140 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700141 }
142};
Patrick Williamseb8a3992023-05-12 09:57:16 -0500143
Ed Tanous62598e32023-07-17 17:06:25 -0700144template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700145struct BMCWEB_LOG_ERROR
Ed Tanous62598e32023-07-17 17:06:25 -0700146{
Ed Tanous6ea90762024-04-07 08:38:44 -0700147 // NOLINTNEXTLINE(google-explicit-constructor)
148 BMCWEB_LOG_ERROR(std::format_string<Args...> format, Args&&... args,
149 const std::source_location& loc =
150 std::source_location::current()) noexcept
151 {
Ed Tanous17c47242024-04-08 17:18:12 -0700152 crow::vlog<crow::LogLevel::Error, Args...>(
153 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700154 }
155};
Ed Tanous600d2392022-01-07 09:32:03 -0800156
Ed Tanous62598e32023-07-17 17:06:25 -0700157template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700158struct BMCWEB_LOG_WARNING
Ed Tanous62598e32023-07-17 17:06:25 -0700159{
Ed Tanous6ea90762024-04-07 08:38:44 -0700160 // NOLINTNEXTLINE(google-explicit-constructor)
161 BMCWEB_LOG_WARNING(std::format_string<Args...> format, Args&&... args,
162 const std::source_location& loc =
163 std::source_location::current()) noexcept
164 {
Ed Tanous17c47242024-04-08 17:18:12 -0700165 crow::vlog<crow::LogLevel::Warning, Args...>(
166 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700167 }
168};
Ed Tanous600d2392022-01-07 09:32:03 -0800169
Ed Tanous62598e32023-07-17 17:06:25 -0700170template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700171struct BMCWEB_LOG_INFO
Ed Tanous62598e32023-07-17 17:06:25 -0700172{
Ed Tanous6ea90762024-04-07 08:38:44 -0700173 // NOLINTNEXTLINE(google-explicit-constructor)
174 BMCWEB_LOG_INFO(std::format_string<Args...> format, Args&&... args,
175 const std::source_location& loc =
176 std::source_location::current()) noexcept
177 {
Ed Tanous17c47242024-04-08 17:18:12 -0700178 crow::vlog<crow::LogLevel::Info, Args...>(
179 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700180 }
181};
Ed Tanous600d2392022-01-07 09:32:03 -0800182
Ed Tanous62598e32023-07-17 17:06:25 -0700183template <typename... Args>
Ed Tanous6ea90762024-04-07 08:38:44 -0700184struct BMCWEB_LOG_DEBUG
Ed Tanous62598e32023-07-17 17:06:25 -0700185{
Ed Tanous6ea90762024-04-07 08:38:44 -0700186 // NOLINTNEXTLINE(google-explicit-constructor)
187 BMCWEB_LOG_DEBUG(std::format_string<Args...> format, Args&&... args,
188 const std::source_location& loc =
189 std::source_location::current()) noexcept
190 {
Ed Tanous17c47242024-04-08 17:18:12 -0700191 crow::vlog<crow::LogLevel::Debug, Args...>(
192 std::move(format), std::forward<Args>(args)..., loc);
Ed Tanous6ea90762024-04-07 08:38:44 -0700193 }
194};
195
196template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800197BMCWEB_LOG_CRITICAL(std::format_string<Args...>, Args&&...)
198 -> BMCWEB_LOG_CRITICAL<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700199
200template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800201BMCWEB_LOG_ERROR(std::format_string<Args...>, Args&&...)
202 -> BMCWEB_LOG_ERROR<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700203
204template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800205BMCWEB_LOG_WARNING(std::format_string<Args...>, Args&&...)
206 -> BMCWEB_LOG_WARNING<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700207
208template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800209BMCWEB_LOG_INFO(std::format_string<Args...>, Args&&...)
210 -> BMCWEB_LOG_INFO<Args...>;
Ed Tanous6ea90762024-04-07 08:38:44 -0700211
212template <typename... Args>
Ed Tanous0f441f02024-12-18 10:57:19 -0800213BMCWEB_LOG_DEBUG(std::format_string<Args...>, Args&&...)
214 -> BMCWEB_LOG_DEBUG<Args...>;