xref: /openbmc/bmcweb/http/logging.hpp (revision 36c0f2a3)
1 #pragma once
2 
3 #include "bmcweb_config.h"
4 
5 #include <bit>
6 #include <format>
7 #include <iostream>
8 #include <source_location>
9 #include <string_view>
10 #include <system_error>
11 
12 // NOLINTBEGIN(readability-convert-member-functions-to-static, cert-dcl58-cpp)
13 template <>
14 struct 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 };
26 // NOLINTEND(readability-convert-member-functions-to-static, cert-dcl58-cpp)
27 
28 namespace crow
29 {
30 enum class LogLevel
31 {
32     Disabled = 0,
33     Critical,
34     Error,
35     Warning,
36     Info,
37     Debug,
38     Enabled,
39 };
40 
41 // Mapping of the external loglvl name to internal loglvl
42 constexpr std::array<std::string_view, 7> mapLogLevelFromName{
43     "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
44 
45 constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
46 {
47     const auto* iter = std::ranges::find(mapLogLevelFromName, name);
48     if (iter != mapLogLevelFromName.end())
49     {
50         return static_cast<LogLevel>(iter - mapLogLevelFromName.begin());
51     }
52     return crow::LogLevel::Disabled;
53 }
54 
55 // configured bmcweb LogLevel
56 constexpr crow::LogLevel bmcwebCurrentLoggingLevel =
57     getLogLevelFromName(bmcwebLoggingLevel);
58 
59 template <typename T>
60 const void* logPtr(T p)
61 {
62     static_assert(std::is_pointer<T>::value,
63                   "Can't use logPtr without pointer");
64     return std::bit_cast<const void*>(p);
65 }
66 
67 template <LogLevel level, typename... Args>
68 inline void vlog(std::format_string<Args...> format, Args... args,
69                  const std::source_location& loc) noexcept
70 {
71     if constexpr (bmcwebCurrentLoggingLevel < level)
72     {
73         return;
74     }
75     constexpr size_t stringIndex = static_cast<size_t>(level);
76     static_assert(stringIndex < mapLogLevelFromName.size(),
77                   "Missing string for level");
78     constexpr std::string_view levelString = mapLogLevelFromName[stringIndex];
79     std::string_view filename = loc.file_name();
80     filename = filename.substr(filename.rfind('/') + 1);
81     std::cout << std::format("[{} {}:{}] ", levelString, filename, loc.line())
82               << std::format(format, std::forward<Args>(args)...) << '\n'
83               << std::flush;
84 }
85 } // namespace crow
86 
87 template <typename... Args>
88 struct BMCWEB_LOG_CRITICAL
89 {
90     // NOLINTNEXTLINE(google-explicit-constructor)
91     BMCWEB_LOG_CRITICAL(std::format_string<Args...> format, Args&&... args,
92                         const std::source_location& loc =
93                             std::source_location::current()) noexcept
94     {
95         crow::vlog<crow::LogLevel::Critical, Args...>(format, args..., loc);
96     }
97 };
98 
99 template <typename... Args>
100 struct BMCWEB_LOG_ERROR
101 {
102     // NOLINTNEXTLINE(google-explicit-constructor)
103     BMCWEB_LOG_ERROR(std::format_string<Args...> format, Args&&... args,
104                      const std::source_location& loc =
105                          std::source_location::current()) noexcept
106     {
107         crow::vlog<crow::LogLevel::Error, Args...>(format, args..., loc);
108     }
109 };
110 
111 template <typename... Args>
112 struct BMCWEB_LOG_WARNING
113 {
114     // NOLINTNEXTLINE(google-explicit-constructor)
115     BMCWEB_LOG_WARNING(std::format_string<Args...> format, Args&&... args,
116                        const std::source_location& loc =
117                            std::source_location::current()) noexcept
118     {
119         crow::vlog<crow::LogLevel::Warning, Args...>(format, args..., loc);
120     }
121 };
122 
123 template <typename... Args>
124 struct BMCWEB_LOG_INFO
125 {
126     // NOLINTNEXTLINE(google-explicit-constructor)
127     BMCWEB_LOG_INFO(std::format_string<Args...> format, Args&&... args,
128                     const std::source_location& loc =
129                         std::source_location::current()) noexcept
130     {
131         crow::vlog<crow::LogLevel::Info, Args...>(format, args..., loc);
132     }
133 };
134 
135 template <typename... Args>
136 struct BMCWEB_LOG_DEBUG
137 {
138     // NOLINTNEXTLINE(google-explicit-constructor)
139     BMCWEB_LOG_DEBUG(std::format_string<Args...> format, Args&&... args,
140                      const std::source_location& loc =
141                          std::source_location::current()) noexcept
142     {
143         crow::vlog<crow::LogLevel::Debug, Args...>(format, args..., loc);
144     }
145 };
146 
147 template <typename... Args>
148 BMCWEB_LOG_CRITICAL(std::format_string<Args...>, Args&&...)
149     -> BMCWEB_LOG_CRITICAL<Args...>;
150 
151 template <typename... Args>
152 BMCWEB_LOG_ERROR(std::format_string<Args...>, Args&&...)
153     -> BMCWEB_LOG_ERROR<Args...>;
154 
155 template <typename... Args>
156 BMCWEB_LOG_WARNING(std::format_string<Args...>, Args&&...)
157     -> BMCWEB_LOG_WARNING<Args...>;
158 
159 template <typename... Args>
160 BMCWEB_LOG_INFO(std::format_string<Args...>, Args&&...)
161     -> BMCWEB_LOG_INFO<Args...>;
162 
163 template <typename... Args>
164 BMCWEB_LOG_DEBUG(std::format_string<Args...>, Args&&...)
165     -> BMCWEB_LOG_DEBUG<Args...>;
166