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 <> 50a716aa74SEd Tanous struct std::formatter<boost::urls::url_view> 51a716aa74SEd Tanous { 52a716aa74SEd Tanous constexpr auto parse(std::format_parse_context& ctx) 53a716aa74SEd Tanous { 54a716aa74SEd Tanous return ctx.begin(); 55a716aa74SEd Tanous } 56a716aa74SEd Tanous auto format(const boost::urls::url& msg, auto& ctx) const 57a716aa74SEd Tanous { 58a716aa74SEd Tanous return std::format_to(ctx.out(), "{}", std::string_view(msg.buffer())); 59a716aa74SEd Tanous } 60a716aa74SEd Tanous }; 61a716aa74SEd Tanous 62a716aa74SEd Tanous template <> 6362598e31SEd Tanous struct std::formatter<boost::urls::url> 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::urls::url& msg, auto& ctx) const 7062598e31SEd Tanous { 7162598e31SEd Tanous return std::format_to(ctx.out(), "{}", std::string_view(msg.buffer())); 7262598e31SEd Tanous } 7362598e31SEd Tanous }; 7462598e31SEd Tanous 7562598e31SEd Tanous template <> 7662598e31SEd Tanous struct std::formatter<boost::core::string_view> 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 boost::core::string_view& msg, auto& ctx) const 8362598e31SEd Tanous { 8462598e31SEd Tanous return std::format_to(ctx.out(), "{}", std::string_view(msg)); 8562598e31SEd Tanous } 8662598e31SEd Tanous }; 8762598e31SEd Tanous 8862598e31SEd Tanous template <> 8962598e31SEd Tanous struct std::formatter<void*> 9062598e31SEd Tanous { 9162598e31SEd Tanous constexpr auto parse(std::format_parse_context& ctx) 9262598e31SEd Tanous { 9362598e31SEd Tanous return ctx.begin(); 9462598e31SEd Tanous } 9562598e31SEd Tanous auto format(const void*& ptr, auto& ctx) const 9662598e31SEd Tanous { 9762598e31SEd Tanous return std::format_to(ctx.out(), "{}", 9862598e31SEd Tanous std::to_string(std::bit_cast<size_t>(ptr))); 9962598e31SEd Tanous } 10062598e31SEd Tanous }; 10162598e31SEd Tanous 10262598e31SEd Tanous template <> 10362598e31SEd Tanous struct std::formatter<nlohmann::json::json_pointer> 10462598e31SEd Tanous { 10562598e31SEd Tanous 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_pointer& ptr, auto& ctx) const 11062598e31SEd Tanous { 11162598e31SEd Tanous return std::format_to(ctx.out(), "{}", ptr.to_string()); 11262598e31SEd Tanous } 11362598e31SEd Tanous }; 11462598e31SEd Tanous 11562598e31SEd Tanous template <> 11662598e31SEd Tanous struct std::formatter<nlohmann::json> 11762598e31SEd Tanous { 11862598e31SEd Tanous static constexpr auto parse(std::format_parse_context& ctx) 11962598e31SEd Tanous { 12062598e31SEd Tanous return ctx.begin(); 12162598e31SEd Tanous } 12262598e31SEd Tanous auto format(const nlohmann::json& json, auto& ctx) const 12362598e31SEd Tanous { 12462598e31SEd Tanous return std::format_to( 12562598e31SEd Tanous ctx.out(), "{}", 12662598e31SEd Tanous json.dump(-1, ' ', false, 12762598e31SEd Tanous nlohmann::json::error_handler_t::replace)); 12862598e31SEd Tanous } 12962598e31SEd Tanous }; 13062598e31SEd Tanous // NOLINTEND(readability-convert-member-functions-to-static, cert-dcl58-cpp) 13104e438cbSEd Tanous 13204e438cbSEd Tanous namespace crow 13304e438cbSEd Tanous { 13404e438cbSEd Tanous enum class LogLevel 13504e438cbSEd Tanous { 136662aa6e3SMyung Bae Disabled = 0, 13704e438cbSEd Tanous Critical, 138e7245fe8SEd Tanous Error, 139e7245fe8SEd Tanous Warning, 140e7245fe8SEd Tanous Info, 141e7245fe8SEd Tanous Debug, 142e7245fe8SEd Tanous Enabled, 14304e438cbSEd Tanous }; 14404e438cbSEd Tanous 145662aa6e3SMyung Bae // Mapping of the external loglvl name to internal loglvl 146e7245fe8SEd Tanous constexpr std::array<std::string_view, 7> mapLogLevelFromName{ 147e7245fe8SEd Tanous "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"}; 148662aa6e3SMyung Bae 149662aa6e3SMyung Bae constexpr crow::LogLevel getLogLevelFromName(std::string_view name) 150662aa6e3SMyung Bae { 151e7245fe8SEd Tanous const auto* iter = std::ranges::find(mapLogLevelFromName, name); 152e7245fe8SEd Tanous if (iter != mapLogLevelFromName.end()) 153662aa6e3SMyung Bae { 154e7245fe8SEd Tanous return static_cast<LogLevel>(iter - mapLogLevelFromName.begin()); 155662aa6e3SMyung Bae } 156662aa6e3SMyung Bae return crow::LogLevel::Disabled; 157662aa6e3SMyung Bae } 158662aa6e3SMyung Bae 159662aa6e3SMyung Bae // configured bmcweb LogLevel 160662aa6e3SMyung Bae constexpr crow::LogLevel bmcwebCurrentLoggingLevel = 161662aa6e3SMyung Bae getLogLevelFromName(bmcwebLoggingLevel); 162662aa6e3SMyung Bae 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 171*6ea90760SEd Tanous template <LogLevel level, typename... Args> 172*6ea90760SEd Tanous inline void vlog(std::format_string<Args...> format, Args... args, 173*6ea90760SEd Tanous const std::source_location& loc) noexcept 17462598e31SEd Tanous { 175d518a9beSMyung Bae if constexpr (bmcwebCurrentLoggingLevel < level) 17662598e31SEd Tanous { 17762598e31SEd Tanous return; 17862598e31SEd Tanous } 17962598e31SEd Tanous constexpr size_t stringIndex = static_cast<size_t>(level); 18062598e31SEd Tanous static_assert(stringIndex < mapLogLevelFromName.size(), 18162598e31SEd Tanous "Missing string for level"); 182e7245fe8SEd Tanous constexpr std::string_view levelString = mapLogLevelFromName[stringIndex]; 183*6ea90760SEd Tanous std::string_view filename = loc.file_name(); 184e7245fe8SEd Tanous filename = filename.substr(filename.rfind('/') + 1); 185*6ea90760SEd Tanous std::cout << std::format("[{} {}:{}] ", levelString, filename, loc.line()) 186*6ea90760SEd Tanous << std::format(format, std::forward<Args>(args)...) << '\n' 187dce4d230SEd Tanous << std::flush; 18862598e31SEd Tanous } 18904e438cbSEd Tanous } // namespace crow 19004e438cbSEd Tanous 19162598e31SEd Tanous template <typename... Args> 192*6ea90760SEd Tanous struct BMCWEB_LOG_CRITICAL 19362598e31SEd Tanous { 194*6ea90760SEd Tanous // NOLINTNEXTLINE(google-explicit-constructor) 195*6ea90760SEd Tanous BMCWEB_LOG_CRITICAL(std::format_string<Args...> format, Args&&... args, 196*6ea90760SEd Tanous const std::source_location& loc = 197*6ea90760SEd Tanous std::source_location::current()) noexcept 198*6ea90760SEd Tanous { 199*6ea90760SEd Tanous crow::vlog<crow::LogLevel::Critical, Args...>(format, args..., loc); 20062598e31SEd Tanous } 201*6ea90760SEd Tanous }; 202eb8a3998SPatrick Williams 20362598e31SEd Tanous template <typename... Args> 204*6ea90760SEd Tanous struct BMCWEB_LOG_ERROR 20562598e31SEd Tanous { 206*6ea90760SEd Tanous // NOLINTNEXTLINE(google-explicit-constructor) 207*6ea90760SEd Tanous BMCWEB_LOG_ERROR(std::format_string<Args...> format, Args&&... args, 208*6ea90760SEd Tanous const std::source_location& loc = 209*6ea90760SEd Tanous std::source_location::current()) noexcept 210*6ea90760SEd Tanous { 211*6ea90760SEd Tanous crow::vlog<crow::LogLevel::Error, Args...>(format, args..., loc); 21262598e31SEd Tanous } 213*6ea90760SEd Tanous }; 214600d2394SEd Tanous 21562598e31SEd Tanous template <typename... Args> 216*6ea90760SEd Tanous struct BMCWEB_LOG_WARNING 21762598e31SEd Tanous { 218*6ea90760SEd Tanous // NOLINTNEXTLINE(google-explicit-constructor) 219*6ea90760SEd Tanous BMCWEB_LOG_WARNING(std::format_string<Args...> format, Args&&... args, 220*6ea90760SEd Tanous const std::source_location& loc = 221*6ea90760SEd Tanous std::source_location::current()) noexcept 222*6ea90760SEd Tanous { 223*6ea90760SEd Tanous crow::vlog<crow::LogLevel::Warning, Args...>(format, args..., loc); 22462598e31SEd Tanous } 225*6ea90760SEd Tanous }; 226600d2394SEd Tanous 22762598e31SEd Tanous template <typename... Args> 228*6ea90760SEd Tanous struct BMCWEB_LOG_INFO 22962598e31SEd Tanous { 230*6ea90760SEd Tanous // NOLINTNEXTLINE(google-explicit-constructor) 231*6ea90760SEd Tanous BMCWEB_LOG_INFO(std::format_string<Args...> format, Args&&... args, 232*6ea90760SEd Tanous const std::source_location& loc = 233*6ea90760SEd Tanous std::source_location::current()) noexcept 234*6ea90760SEd Tanous { 235*6ea90760SEd Tanous crow::vlog<crow::LogLevel::Info, Args...>(format, args..., loc); 23662598e31SEd Tanous } 237*6ea90760SEd Tanous }; 238600d2394SEd Tanous 23962598e31SEd Tanous template <typename... Args> 240*6ea90760SEd Tanous struct BMCWEB_LOG_DEBUG 24162598e31SEd Tanous { 242*6ea90760SEd Tanous // NOLINTNEXTLINE(google-explicit-constructor) 243*6ea90760SEd Tanous BMCWEB_LOG_DEBUG(std::format_string<Args...> format, Args&&... args, 244*6ea90760SEd Tanous const std::source_location& loc = 245*6ea90760SEd Tanous std::source_location::current()) noexcept 246*6ea90760SEd Tanous { 247*6ea90760SEd Tanous crow::vlog<crow::LogLevel::Debug, Args...>(format, args..., loc); 24862598e31SEd Tanous } 249*6ea90760SEd Tanous }; 250*6ea90760SEd Tanous 251*6ea90760SEd Tanous template <typename... Args> 252*6ea90760SEd Tanous BMCWEB_LOG_CRITICAL(std::format_string<Args...>, Args&&...) 253*6ea90760SEd Tanous -> BMCWEB_LOG_CRITICAL<Args...>; 254*6ea90760SEd Tanous 255*6ea90760SEd Tanous template <typename... Args> 256*6ea90760SEd Tanous BMCWEB_LOG_ERROR(std::format_string<Args...>, Args&&...) 257*6ea90760SEd Tanous -> BMCWEB_LOG_ERROR<Args...>; 258*6ea90760SEd Tanous 259*6ea90760SEd Tanous template <typename... Args> 260*6ea90760SEd Tanous BMCWEB_LOG_WARNING(std::format_string<Args...>, Args&&...) 261*6ea90760SEd Tanous -> BMCWEB_LOG_WARNING<Args...>; 262*6ea90760SEd Tanous 263*6ea90760SEd Tanous template <typename... Args> 264*6ea90760SEd Tanous BMCWEB_LOG_INFO(std::format_string<Args...>, Args&&...) 265*6ea90760SEd Tanous -> BMCWEB_LOG_INFO<Args...>; 266*6ea90760SEd Tanous 267*6ea90760SEd Tanous template <typename... Args> 268*6ea90760SEd Tanous BMCWEB_LOG_DEBUG(std::format_string<Args...>, Args&&...) 269*6ea90760SEd Tanous -> BMCWEB_LOG_DEBUG<Args...>; 270