xref: /openbmc/bmcweb/http/logging.hpp (revision e7245fe847e7282522a7979f816fd76f925348d3)
104e438cbSEd Tanous #pragma once
204e438cbSEd Tanous 
3662aa6e3SMyung Bae #include "bmcweb_config.h"
4662aa6e3SMyung Bae 
562598e31SEd Tanous #include <boost/system/error_code.hpp>
662598e31SEd Tanous #include <boost/url/pct_string_view.hpp>
762598e31SEd Tanous #include <boost/url/string_view.hpp>
862598e31SEd Tanous #include <boost/url/url.hpp>
962598e31SEd Tanous #include <nlohmann/json.hpp>
1062598e31SEd Tanous 
1162598e31SEd Tanous #include <bit>
1262598e31SEd Tanous #include <format>
1304e438cbSEd Tanous #include <iostream>
1462598e31SEd Tanous #include <source_location>
15662aa6e3SMyung Bae #include <string_view>
1662598e31SEd Tanous #include <system_error>
1762598e31SEd Tanous 
1862598e31SEd Tanous // Clang-tidy would rather these be static, but using static causes the template
1962598e31SEd Tanous // specialization to not function.  Ignore the warning.
2062598e31SEd Tanous // NOLINTBEGIN(readability-convert-member-functions-to-static, cert-dcl58-cpp)
2162598e31SEd Tanous template <>
2262598e31SEd Tanous struct std::formatter<boost::system::error_code>
2362598e31SEd Tanous {
2462598e31SEd Tanous     constexpr auto parse(std::format_parse_context& ctx)
2562598e31SEd Tanous     {
2662598e31SEd Tanous         return ctx.begin();
2762598e31SEd Tanous     }
2862598e31SEd Tanous 
2962598e31SEd Tanous     auto format(const boost::system::error_code& ec, auto& ctx) const
3062598e31SEd Tanous     {
3162598e31SEd Tanous         return std::format_to(ctx.out(), "{}", ec.what());
3262598e31SEd Tanous     }
3362598e31SEd Tanous };
3462598e31SEd Tanous 
3562598e31SEd Tanous template <>
3662598e31SEd Tanous struct std::formatter<boost::urls::pct_string_view>
3762598e31SEd Tanous {
3862598e31SEd Tanous     constexpr auto parse(std::format_parse_context& ctx)
3962598e31SEd Tanous     {
4062598e31SEd Tanous         return ctx.begin();
4162598e31SEd Tanous     }
4262598e31SEd Tanous     auto format(const boost::urls::pct_string_view& msg, auto& ctx) const
4362598e31SEd Tanous     {
4462598e31SEd Tanous         return std::format_to(ctx.out(), "{}",
4562598e31SEd Tanous                               std::string_view(msg.data(), msg.size()));
4662598e31SEd Tanous     }
4762598e31SEd Tanous };
4862598e31SEd Tanous 
4962598e31SEd Tanous template <>
5062598e31SEd Tanous struct std::formatter<boost::urls::url>
5162598e31SEd Tanous {
5262598e31SEd Tanous     constexpr auto parse(std::format_parse_context& ctx)
5362598e31SEd Tanous     {
5462598e31SEd Tanous         return ctx.begin();
5562598e31SEd Tanous     }
5662598e31SEd Tanous     auto format(const boost::urls::url& msg, auto& ctx) const
5762598e31SEd Tanous     {
5862598e31SEd Tanous         return std::format_to(ctx.out(), "{}", std::string_view(msg.buffer()));
5962598e31SEd Tanous     }
6062598e31SEd Tanous };
6162598e31SEd Tanous 
6262598e31SEd Tanous template <>
6362598e31SEd Tanous struct std::formatter<boost::core::string_view>
6462598e31SEd Tanous {
6562598e31SEd Tanous     constexpr auto parse(std::format_parse_context& ctx)
6662598e31SEd Tanous     {
6762598e31SEd Tanous         return ctx.begin();
6862598e31SEd Tanous     }
6962598e31SEd Tanous     auto format(const boost::core::string_view& msg, auto& ctx) const
7062598e31SEd Tanous     {
7162598e31SEd Tanous         return std::format_to(ctx.out(), "{}", std::string_view(msg));
7262598e31SEd Tanous     }
7362598e31SEd Tanous };
7462598e31SEd Tanous 
7562598e31SEd Tanous template <>
7662598e31SEd Tanous struct std::formatter<void*>
7762598e31SEd Tanous {
7862598e31SEd Tanous     constexpr auto parse(std::format_parse_context& ctx)
7962598e31SEd Tanous     {
8062598e31SEd Tanous         return ctx.begin();
8162598e31SEd Tanous     }
8262598e31SEd Tanous     auto format(const void*& ptr, auto& ctx) const
8362598e31SEd Tanous     {
8462598e31SEd Tanous         return std::format_to(ctx.out(), "{}",
8562598e31SEd Tanous                               std::to_string(std::bit_cast<size_t>(ptr)));
8662598e31SEd Tanous     }
8762598e31SEd Tanous };
8862598e31SEd Tanous 
8962598e31SEd Tanous template <>
9062598e31SEd Tanous struct std::formatter<nlohmann::json::json_pointer>
9162598e31SEd Tanous {
9262598e31SEd Tanous     constexpr auto parse(std::format_parse_context& ctx)
9362598e31SEd Tanous     {
9462598e31SEd Tanous         return ctx.begin();
9562598e31SEd Tanous     }
9662598e31SEd Tanous     auto format(const nlohmann::json::json_pointer& ptr, auto& ctx) const
9762598e31SEd Tanous     {
9862598e31SEd Tanous         return std::format_to(ctx.out(), "{}", ptr.to_string());
9962598e31SEd Tanous     }
10062598e31SEd Tanous };
10162598e31SEd Tanous 
10262598e31SEd Tanous template <>
10362598e31SEd Tanous struct std::formatter<nlohmann::json>
10462598e31SEd Tanous {
10562598e31SEd Tanous     static constexpr auto parse(std::format_parse_context& ctx)
10662598e31SEd Tanous     {
10762598e31SEd Tanous         return ctx.begin();
10862598e31SEd Tanous     }
10962598e31SEd Tanous     auto format(const nlohmann::json& json, auto& ctx) const
11062598e31SEd Tanous     {
11162598e31SEd Tanous         return std::format_to(
11262598e31SEd Tanous             ctx.out(), "{}",
11362598e31SEd Tanous             json.dump(-1, ' ', false,
11462598e31SEd Tanous                       nlohmann::json::error_handler_t::replace));
11562598e31SEd Tanous     }
11662598e31SEd Tanous };
11762598e31SEd Tanous // NOLINTEND(readability-convert-member-functions-to-static, cert-dcl58-cpp)
11804e438cbSEd Tanous 
11904e438cbSEd Tanous namespace crow
12004e438cbSEd Tanous {
12104e438cbSEd Tanous enum class LogLevel
12204e438cbSEd Tanous {
123662aa6e3SMyung Bae     Disabled = 0,
12404e438cbSEd Tanous     Critical,
125*e7245fe8SEd Tanous     Error,
126*e7245fe8SEd Tanous     Warning,
127*e7245fe8SEd Tanous     Info,
128*e7245fe8SEd Tanous     Debug,
129*e7245fe8SEd Tanous     Enabled,
13004e438cbSEd Tanous };
13104e438cbSEd Tanous 
132662aa6e3SMyung Bae // Mapping of the external loglvl name to internal loglvl
133*e7245fe8SEd Tanous constexpr std::array<std::string_view, 7> mapLogLevelFromName{
134*e7245fe8SEd Tanous     "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
135662aa6e3SMyung Bae 
136662aa6e3SMyung Bae constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
137662aa6e3SMyung Bae {
138*e7245fe8SEd Tanous     const auto* iter = std::ranges::find(mapLogLevelFromName, name);
139*e7245fe8SEd Tanous     if (iter != mapLogLevelFromName.end())
140662aa6e3SMyung Bae     {
141*e7245fe8SEd Tanous         return static_cast<LogLevel>(iter - mapLogLevelFromName.begin());
142662aa6e3SMyung Bae     }
143662aa6e3SMyung Bae     return crow::LogLevel::Disabled;
144662aa6e3SMyung Bae }
145662aa6e3SMyung Bae 
146662aa6e3SMyung Bae // configured bmcweb LogLevel
147662aa6e3SMyung Bae constexpr crow::LogLevel bmcwebCurrentLoggingLevel =
148662aa6e3SMyung Bae     getLogLevelFromName(bmcwebLoggingLevel);
149662aa6e3SMyung Bae 
15062598e31SEd Tanous struct FormatString
15104e438cbSEd Tanous {
15262598e31SEd Tanous     std::string_view str;
15362598e31SEd Tanous     std::source_location loc;
15404e438cbSEd Tanous 
15562598e31SEd Tanous     // NOLINTNEXTLINE(google-explicit-constructor)
15662598e31SEd Tanous     FormatString(const char* strIn, const std::source_location& locIn =
15762598e31SEd Tanous                                         std::source_location::current()) :
15862598e31SEd Tanous         str(strIn),
15962598e31SEd Tanous         loc(locIn)
16062598e31SEd Tanous     {}
16104e438cbSEd Tanous };
16262598e31SEd Tanous 
16362598e31SEd Tanous template <typename T>
16462598e31SEd Tanous const void* logPtr(T p)
16562598e31SEd Tanous {
16662598e31SEd Tanous     static_assert(std::is_pointer<T>::value,
16762598e31SEd Tanous                   "Can't use logPtr without pointer");
16862598e31SEd Tanous     return std::bit_cast<const void*>(p);
16962598e31SEd Tanous }
17062598e31SEd Tanous 
17162598e31SEd Tanous template <LogLevel level>
17262598e31SEd Tanous inline void vlog(const FormatString& format, std::format_args&& args)
17362598e31SEd Tanous {
174*e7245fe8SEd Tanous     if constexpr (bmcwebCurrentLoggingLevel <= level)
17562598e31SEd Tanous     {
17662598e31SEd Tanous         return;
17762598e31SEd Tanous     }
17862598e31SEd Tanous     constexpr size_t stringIndex = static_cast<size_t>(level);
17962598e31SEd Tanous     static_assert(stringIndex < mapLogLevelFromName.size(),
18062598e31SEd Tanous                   "Missing string for level");
181*e7245fe8SEd Tanous     constexpr std::string_view levelString = mapLogLevelFromName[stringIndex];
18262598e31SEd Tanous     std::string_view filename = format.loc.file_name();
183*e7245fe8SEd Tanous     filename = filename.substr(filename.rfind('/') + 1);
18462598e31SEd Tanous     std::cout << std::format("[{} {}:{}] ", levelString, filename,
185*e7245fe8SEd Tanous                              format.loc.line())
186*e7245fe8SEd Tanous               << std::vformat(format.str, args) << '\n';
18762598e31SEd Tanous }
18804e438cbSEd Tanous } // namespace crow
18904e438cbSEd Tanous 
19062598e31SEd Tanous template <typename... Args>
19162598e31SEd Tanous inline void BMCWEB_LOG_CRITICAL(const crow::FormatString& format,
19262598e31SEd Tanous                                 Args&&... args)
19362598e31SEd Tanous {
19462598e31SEd Tanous     crow::vlog<crow::LogLevel::Critical>(
19562598e31SEd Tanous         format, std::make_format_args(std::forward<Args>(args)...));
19662598e31SEd Tanous }
197eb8a3998SPatrick Williams 
19862598e31SEd Tanous template <typename... Args>
19962598e31SEd Tanous inline void BMCWEB_LOG_ERROR(const crow::FormatString& format, Args&&... args)
20062598e31SEd Tanous {
20162598e31SEd Tanous     crow::vlog<crow::LogLevel::Error>(
20262598e31SEd Tanous         format, std::make_format_args(std::forward<Args>(args)...));
20362598e31SEd Tanous }
204600d2394SEd Tanous 
20562598e31SEd Tanous template <typename... Args>
20662598e31SEd Tanous inline void BMCWEB_LOG_WARNING(const crow::FormatString& format, Args&&... args)
20762598e31SEd Tanous {
20862598e31SEd Tanous     crow::vlog<crow::LogLevel::Warning>(
20962598e31SEd Tanous         format, std::make_format_args(std::forward<Args>(args)...));
21062598e31SEd Tanous }
211600d2394SEd Tanous 
21262598e31SEd Tanous template <typename... Args>
21362598e31SEd Tanous inline void BMCWEB_LOG_INFO(const crow::FormatString& format, Args&&... args)
21462598e31SEd Tanous {
21562598e31SEd Tanous     crow::vlog<crow::LogLevel::Info>(
21662598e31SEd Tanous         format, std::make_format_args(std::forward<Args>(args)...));
21762598e31SEd Tanous }
218600d2394SEd Tanous 
21962598e31SEd Tanous template <typename... Args>
22062598e31SEd Tanous inline void BMCWEB_LOG_DEBUG(const crow::FormatString& format, Args&&... args)
22162598e31SEd Tanous {
22262598e31SEd Tanous     crow::vlog<crow::LogLevel::Debug>(
22362598e31SEd Tanous         format, std::make_format_args(std::forward<Args>(args)...));
22462598e31SEd Tanous }
225