Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
41 changes: 25 additions & 16 deletions include/log/fmt/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,38 @@
#include <log/log.hpp>
#include <log/module.hpp>

#include <stdx/bit.hpp>
#include <stdx/ct_format.hpp>
#include <stdx/tuple.hpp>
#include <stdx/tuple_algorithms.hpp>
#include <stdx/utility.hpp>
#include <stdx/type_traits.hpp>

#include <fmt/format.h>

#include <array>
#include <chrono>
#include <type_traits>
#include <iterator>
#include <string_view>
#include <utility>

namespace logging {
template <auto> 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 <logging::level L>
struct fmt::formatter<std::integral_constant<logging::level, L>> {
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 <typename FormatContext>
auto format(std::integral_constant<logging::level, L>,
FormatContext &ctx) const {
return ::fmt::format_to(ctx.out(), logging::to_text<L>());
}
};
template <logging::level L>
[[nodiscard]] constexpr auto format_as(level_wrapper<L>) -> std::string_view {
return level_text<L>;
}

namespace logging::fmt {
namespace fmt {
template <typename TDestinations> struct log_handler {
constexpr explicit log_handler(TDestinations &&ds) : dests{std::move(ds)} {}

Expand All @@ -43,7 +50,8 @@ template <typename TDestinations> 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_level(Env{}).value>{},
get_module(Env{}).value);
msg.apply(
[&]<typename StringType>(StringType, auto const &...args) {
::fmt::format_to(out, StringType::value, args...);
Expand All @@ -65,4 +73,5 @@ template <typename... TDestinations> struct config {

log_handler<destinations_tuple_t> logger;
};
} // namespace logging::fmt
} // namespace fmt
} // namespace logging
16 changes: 0 additions & 16 deletions include/log/level.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
#pragma once

#include <log/env.hpp>

#include <stdx/compiler.hpp>
#include <stdx/type_traits.hpp>

#include <array>
#include <cstdint>
#include <string_view>
#include <type_traits>
#include <utility>

namespace logging {
Expand All @@ -24,16 +18,6 @@ enum struct level : std::uint8_t {
TRACE = 7
};

template <level L>
[[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 <typename T>
CONSTEVAL auto operator()(T &&t) const noexcept(
Expand Down
16 changes: 8 additions & 8 deletions test/log/fmt_logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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::TRACE>());
logging::level_wrapper<logging::level::TRACE>{});
CHECK(level == "TRACE");
}
{
std::string level{};
fmt::format_to(std::back_inserter(level), "{}",
stdx::ct<logging::level::INFO>());
logging::level_wrapper<logging::level::INFO>{});
CHECK(level == "INFO");
}
{
std::string level{};
fmt::format_to(std::back_inserter(level), "{}",
stdx::ct<logging::level::WARN>());
logging::level_wrapper<logging::level::WARN>{});
CHECK(level == "WARN");
}
{
std::string level{};
fmt::format_to(std::back_inserter(level), "{}",
stdx::ct<logging::level::ERROR>());
logging::level_wrapper<logging::level::ERROR>{});
CHECK(level == "ERROR");
}
{
std::string level{};
fmt::format_to(std::back_inserter(level), "{}",
stdx::ct<logging::level::FATAL>());
logging::level_wrapper<logging::level::FATAL>{});
CHECK(level == "FATAL");
}
{
std::string level{};
fmt::format_to(std::back_inserter(level), "{}",
stdx::ct<logging::level::MAX>());
logging::level_wrapper<logging::level::MAX>{});
CHECK(level == "MAX");
}
{
std::string level{};
fmt::format_to(std::back_inserter(level), "{}",
stdx::ct<logging::level::USER1>());
logging::level_wrapper<logging::level::USER1>{});
CHECK(level == "USER1");
}
{
std::string level{};
fmt::format_to(std::back_inserter(level), "{}",
stdx::ct<logging::level::USER2>());
logging::level_wrapper<logging::level::USER2>{});
CHECK(level == "USER2");
}
}
Expand Down
37 changes: 24 additions & 13 deletions test/log/level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <cstdint>
#include <iterator>
#include <string>
#include <string_view>
#include <type_traits>

namespace {
Expand All @@ -19,23 +20,18 @@ enum struct custom_level { THE_ONE_LEVEL = 5 };
std::string buffer{};
} // namespace

namespace logging {
template <custom_level L>
[[nodiscard]] constexpr auto format_as(level_wrapper<L>) -> 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 <custom_level L>
struct fmt::formatter<std::integral_constant<custom_level, L>> {
constexpr static auto parse(format_parse_context &ctx) {
return ctx.begin();
}

template <typename FormatContext>
auto format(std::integral_constant<custom_level, L>,
FormatContext &ctx) const {
return ::fmt::format_to(ctx.out(), stdx::enum_as_string<L>());
}
};

TEST_CASE("fmt logger works with custom level", "[level]") {
CIB_LOG_ENV(logging::get_level, custom_level::THE_ONE_LEVEL);
buffer.clear();
Expand Down Expand Up @@ -66,3 +62,18 @@ TEST_CASE("mipi logger works with custom level", "[level]") {
cfg.logger.log_msg<cib_log_env_t>(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> = "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);
}
Loading