diff --git a/CMakeLists.txt b/CMakeLists.txt index 499dc8dc..3d86d885 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package( include(cmake/string_catalog.cmake) add_versioned_package("gh:boostorg/mp11#boost-1.83.0") -fmt_recipe(10.2.1) +fmt_recipe(11.1.3) add_versioned_package("gh:intel/cpp-baremetal-concurrency#7c5b26c") add_versioned_package("gh:intel/cpp-std-extensions#37cc9c5") add_versioned_package("gh:intel/cpp-baremetal-senders-and-receivers#73d95bc") diff --git a/include/log/fmt/logger.hpp b/include/log/fmt/logger.hpp index 644c076d..c5987c75 100644 --- a/include/log/fmt/logger.hpp +++ b/include/log/fmt/logger.hpp @@ -4,31 +4,38 @@ #include #include +#include #include -#include #include -#include +#include #include +#include #include -#include +#include +#include #include +namespace logging { +template struct level_wrapper {}; + +namespace fmt_detail { +using namespace std::string_view_literals; +constexpr std::array level_text{"MAX"sv, "FATAL"sv, "ERROR"sv, "WARN"sv, + "INFO"sv, "USER1"sv, "USER2"sv, "TRACE"sv}; +} // namespace fmt_detail + template -struct fmt::formatter> { - constexpr static auto parse(format_parse_context &ctx) { - return ctx.begin(); - } +constexpr std::string_view level_text = + fmt_detail::level_text[stdx::to_underlying(L)]; - template - auto format(std::integral_constant, - FormatContext &ctx) const { - return ::fmt::format_to(ctx.out(), logging::to_text()); - } -}; +template +[[nodiscard]] constexpr auto format_as(level_wrapper) -> std::string_view { + return level_text; +} -namespace logging::fmt { +namespace fmt { template struct log_handler { constexpr explicit log_handler(TDestinations &&ds) : dests{std::move(ds)} {} @@ -43,7 +50,8 @@ template struct log_handler { stdx::for_each( [&](auto &out) { ::fmt::format_to(out, "{:>8}us {} [{}]: ", currentTime, - get_level(Env{}), get_module(Env{}).value); + level_wrapper{}, + get_module(Env{}).value); msg.apply( [&](StringType, auto const &...args) { ::fmt::format_to(out, StringType::value, args...); @@ -65,4 +73,5 @@ template struct config { log_handler logger; }; -} // namespace logging::fmt +} // namespace fmt +} // namespace logging diff --git a/include/log/level.hpp b/include/log/level.hpp index 42bc632c..c2eafcd7 100644 --- a/include/log/level.hpp +++ b/include/log/level.hpp @@ -1,14 +1,8 @@ #pragma once -#include - #include -#include -#include #include -#include -#include #include namespace logging { @@ -24,16 +18,6 @@ enum struct level : std::uint8_t { TRACE = 7 }; -template -[[nodiscard]] constexpr auto to_text() -> std::string_view - requires(L <= level::TRACE) -{ - using namespace std::string_view_literals; - constexpr std::array level_text{"MAX"sv, "FATAL"sv, "ERROR"sv, "WARN"sv, - "INFO"sv, "USER1"sv, "USER2"sv, "TRACE"sv}; - return level_text[stdx::to_underlying(L)]; -} - [[maybe_unused]] constexpr inline struct get_level_t { template CONSTEVAL auto operator()(T &&t) const noexcept( diff --git a/test/log/fmt_logger.cpp b/test/log/fmt_logger.cpp index 723dc1d2..af3385c1 100644 --- a/test/log/fmt_logger.cpp +++ b/test/log/fmt_logger.cpp @@ -63,49 +63,49 @@ TEST_CASE("log levels are properly represented", "[fmt_logger]") { { std::string level{}; fmt::format_to(std::back_inserter(level), "{}", - stdx::ct()); + logging::level_wrapper{}); CHECK(level == "TRACE"); } { std::string level{}; fmt::format_to(std::back_inserter(level), "{}", - stdx::ct()); + logging::level_wrapper{}); CHECK(level == "INFO"); } { std::string level{}; fmt::format_to(std::back_inserter(level), "{}", - stdx::ct()); + logging::level_wrapper{}); CHECK(level == "WARN"); } { std::string level{}; fmt::format_to(std::back_inserter(level), "{}", - stdx::ct()); + logging::level_wrapper{}); CHECK(level == "ERROR"); } { std::string level{}; fmt::format_to(std::back_inserter(level), "{}", - stdx::ct()); + logging::level_wrapper{}); CHECK(level == "FATAL"); } { std::string level{}; fmt::format_to(std::back_inserter(level), "{}", - stdx::ct()); + logging::level_wrapper{}); CHECK(level == "MAX"); } { std::string level{}; fmt::format_to(std::back_inserter(level), "{}", - stdx::ct()); + logging::level_wrapper{}); CHECK(level == "USER1"); } { std::string level{}; fmt::format_to(std::back_inserter(level), "{}", - stdx::ct()); + logging::level_wrapper{}); CHECK(level == "USER2"); } } diff --git a/test/log/level.cpp b/test/log/level.cpp index af18196f..5c3b0575 100644 --- a/test/log/level.cpp +++ b/test/log/level.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace { @@ -19,23 +20,18 @@ enum struct custom_level { THE_ONE_LEVEL = 5 }; std::string buffer{}; } // namespace +namespace logging { +template +[[nodiscard]] constexpr auto format_as(level_wrapper) -> std::string_view { + static_assert(L == custom_level::THE_ONE_LEVEL); + return "THE_ONE_LEVEL"; +} +} // namespace logging + template <> inline auto logging::config<> = logging::fmt::config{std::back_inserter(buffer)}; -template -struct fmt::formatter> { - constexpr static auto parse(format_parse_context &ctx) { - return ctx.begin(); - } - - template - auto format(std::integral_constant, - FormatContext &ctx) const { - return ::fmt::format_to(ctx.out(), stdx::enum_as_string()); - } -}; - TEST_CASE("fmt logger works with custom level", "[level]") { CIB_LOG_ENV(logging::get_level, custom_level::THE_ONE_LEVEL); buffer.clear(); @@ -66,3 +62,18 @@ TEST_CASE("mipi logger works with custom level", "[level]") { cfg.logger.log_msg(sc::format("Hello {} {}"_sc, 17, 42)); CHECK(log_calls == 1); } + +namespace { +constexpr auto MY_LEVEL = logging::level::USER1; +} +namespace logging { +template <> constexpr std::string_view level_text = "MY_LEVEL"; +} + +TEST_CASE("mipi logger USER level can be renamed", "[level]") { + CIB_LOG_ENV(logging::get_level, MY_LEVEL); + buffer.clear(); + CIB_LOG("Hello"); + CAPTURE(buffer); + CHECK(buffer.find("MY_LEVEL [default]:") != std::string::npos); +}