Skip to content

Commit

Permalink
Merge pull request #679 from elbeno/log-env
Browse files Browse the repository at this point in the history
✨ Introduce log environment
  • Loading branch information
lukevalenty authored Jan 13, 2025
2 parents 3545e85 + de2b4ae commit 5726ca9
Show file tree
Hide file tree
Showing 14 changed files with 232 additions and 75 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ include(cmake/string_catalog.cmake)
add_versioned_package("gh:boostorg/mp11#boost-1.83.0")
fmt_recipe(10.2.1)
add_versioned_package("gh:intel/cpp-baremetal-concurrency#7c5b26c")
add_versioned_package("gh:intel/cpp-std-extensions#4d57b2e")
add_versioned_package("gh:intel/cpp-std-extensions#2834680")
add_versioned_package("gh:intel/cpp-baremetal-senders-and-receivers#73d95bc")

set(GEN_STR_CATALOG
Expand Down
2 changes: 1 addition & 1 deletion include/cib/detail/runtime_conditional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ operator and(runtime_condition<LhsName, LhsPs...> const &lhs,
constexpr auto name =
stdx::ct_format<"{} and {}">(CX_VALUE(LhsName), CX_VALUE(RhsName));

return runtime_condition<name, LhsPs..., RhsPs...>{};
return runtime_condition<name.str.value, LhsPs..., RhsPs...>{};
}
}

Expand Down
21 changes: 11 additions & 10 deletions include/log/catalog/mipi_encoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <conc/concurrency.hpp>
#include <log/catalog/catalog.hpp>
#include <log/log.hpp>
#include <log/module.hpp>
#include <msg/message.hpp>

#include <stdx/bit.hpp>
Expand All @@ -14,6 +15,7 @@
#include <algorithm>
#include <concepts>
#include <cstdint>
#include <string_view>
#include <utility>

namespace logging::mipi {
Expand All @@ -28,11 +30,10 @@ constexpr auto to_message() {
}(std::make_integer_sequence<std::size_t, std::size(s)>{});
}

template <typename S> constexpr auto to_module() {
constexpr auto s = S::value;
using char_t = typename std::remove_cv_t<decltype(s)>::value_type;
template <stdx::ct_string S> constexpr auto to_module() {
constexpr auto s = std::string_view{S};
return [&]<std::size_t... Is>(std::integer_sequence<std::size_t, Is...>) {
return sc::module_string<sc::undefined<void, char_t, s[Is]...>>{};
return sc::module_string<sc::undefined<void, char, s[Is]...>>{};
}(std::make_integer_sequence<std::size_t, std::size(s)>{});
}
} // namespace detail
Expand Down Expand Up @@ -102,19 +103,19 @@ using catalog_msg_t =
template <typename TDestinations> struct log_handler {
constexpr explicit log_handler(TDestinations &&ds) : dests{std::move(ds)} {}

template <logging::level Level, typename ModuleId,
typename FilenameStringType, typename LineNumberType,
typename MsgType>
template <logging::level Level, typename Env, typename FilenameStringType,
typename LineNumberType, typename MsgType>
ALWAYS_INLINE auto log(FilenameStringType, LineNumberType,
MsgType const &msg) -> void {
log_msg<Level, ModuleId>(msg);
log_msg<Level, Env>(msg);
}

template <logging::level Level, typename ModuleId, typename Msg>
template <logging::level Level, typename Env, typename Msg>
ALWAYS_INLINE auto log_msg(Msg msg) -> void {
msg.apply([&]<typename S, typename... Args>(S, Args... args) {
using Message = decltype(detail::to_message<Level, S, Args...>());
using Module = decltype(detail::to_module<ModuleId>());
using Module =
decltype(detail::to_module<get_module(Env{}).value>());
dispatch_message<Level>(catalog<Message>(), module<Module>(),
static_cast<std::uint32_t>(args)...);
});
Expand Down
91 changes: 91 additions & 0 deletions include/log/env.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#pragma once

#include <stdx/compiler.hpp>
#include <stdx/ct_string.hpp>
#include <stdx/utility.hpp>

#include <boost/mp11/algorithm.hpp>

#ifdef __clang__
#define CIB_PRAGMA_SEMI
#else
#define CIB_PRAGMA_SEMI ;
#endif

namespace logging {
template <auto Query, auto Value> struct prop {
[[nodiscard]] CONSTEVAL static auto query(decltype(Query)) noexcept {
return Value;
}
};

namespace detail {
template <typename Q, typename Env>
concept valid_query_for = requires { Env::query(Q{}); };

template <typename Q, typename... Envs>
concept valid_query_over = (... or valid_query_for<Q, Envs>);

template <typename Q> struct has_query {
template <typename Env>
using fn = std::bool_constant<valid_query_for<Q, Env>>;
};
} // namespace detail

template <typename... Envs> struct env {
template <detail::valid_query_over<Envs...> Q>
CONSTEVAL static auto query(Q) noexcept {
using I = boost::mp11::mp_find_if_q<boost::mp11::mp_list<Envs...>,
detail::has_query<Q>>;
using E = boost::mp11::mp_at<boost::mp11::mp_list<Envs...>, I>;
return Q{}(E{});
}
};

namespace detail {
template <typename T> struct autowrap {
CONSTEVAL autowrap(T t) : value(t) {}
T value;
};

template <std::size_t N> using str_lit_t = char const (&)[N];

template <std::size_t N> struct autowrap<str_lit_t<N>> {
CONSTEVAL autowrap(str_lit_t<N> str) : value(str) {}
stdx::ct_string<N> value;
};

template <typename T> autowrap(T) -> autowrap<T>;
template <std::size_t N> autowrap(str_lit_t<N>) -> autowrap<str_lit_t<N>>;

template <auto V> struct wrap {
constexpr static auto value = V;
};

template <typename> struct for_each_pair;
template <std::size_t... Is> struct for_each_pair<std::index_sequence<Is...>> {
template <auto... Args>
using type = env<
prop<boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
2 * Is>::value.value,
stdx::ct<boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
2 * Is + 1>::value.value>()>...>;
};
} // namespace detail
} // namespace logging

using cib_log_env_t = logging::env<>;

// NOLINTBEGIN(cppcoreguidelines-macro-usage)
#define CIB_LOG_ENV(...) \
STDX_PRAGMA(diagnostic push) \
STDX_PRAGMA(diagnostic ignored "-Wshadow") \
using cib_log_env_t [[maybe_unused]] = \
decltype([]<logging::detail::autowrap... Args> { \
using new_env_t = typename logging::detail::for_each_pair< \
std::make_index_sequence<sizeof...(Args) / \
2>>::template type<Args...>; \
return boost::mp11::mp_append<new_env_t, cib_log_env_t>{}; \
}.template operator()<__VA_ARGS__>()) CIB_PRAGMA_SEMI \
STDX_PRAGMA(diagnostic pop)
// NOLINTEND(cppcoreguidelines-macro-usage)
6 changes: 4 additions & 2 deletions include/log/fmt/logger.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include <log/log.hpp>
#include <log/module.hpp>

#include <stdx/ct_format.hpp>
#include <stdx/tuple.hpp>
#include <stdx/tuple_algorithms.hpp>

Expand All @@ -25,7 +27,7 @@ namespace logging::fmt {
template <typename TDestinations> struct log_handler {
constexpr explicit log_handler(TDestinations &&ds) : dests{std::move(ds)} {}

template <logging::level L, typename ModuleId, typename FilenameStringType,
template <logging::level L, typename Env, typename FilenameStringType,
typename LineNumberType, typename MsgType>
auto log(FilenameStringType, LineNumberType, MsgType const &msg) -> void {
auto const currentTime =
Expand All @@ -36,7 +38,7 @@ template <typename TDestinations> struct log_handler {
stdx::for_each(
[&](auto &out) {
::fmt::format_to(out, "{:>8}us {} [{}]: ", currentTime,
level_constant<L>{}, ModuleId::value);
level_constant<L>{}, get_module(Env{}).value);
msg.apply(
[&]<typename StringType>(StringType, auto const &...args) {
::fmt::format_to(out, StringType::value, args...);
Expand Down
31 changes: 7 additions & 24 deletions include/log/log.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once

#include <log/env.hpp>
#include <log/level.hpp>
#include <log/module.hpp>
#include <sc/format.hpp>
#include <sc/fwd.hpp>

Expand Down Expand Up @@ -44,37 +46,18 @@ ALWAYS_INLINE constexpr static auto get_config() -> auto & {
}
}

template <typename Flavor, level L, typename ModuleId, typename... Ts,
template <typename Flavor, level L, typename Env, typename... Ts,
typename... TArgs>
ALWAYS_INLINE static auto log(TArgs &&...args) -> void {
auto &cfg = get_config<Flavor, Ts...>();
cfg.logger.template log<L, ModuleId>(std::forward<TArgs>(args)...);
cfg.logger.template log<L, Env>(std::forward<TArgs>(args)...);
}

template <stdx::ct_string S> struct module_id_t {
using type = decltype(stdx::ct_string_to_type<S, sc::string_constant>());
};
} // namespace logging

using cib_log_module_id_t = typename logging::module_id_t<"default">::type;

// NOLINTBEGIN(cppcoreguidelines-macro-usage)

#ifdef __clang__
#define CIB_PRAGMA_SEMI
#else
#define CIB_PRAGMA_SEMI ;
#endif

#define CIB_LOG_MODULE(S) \
STDX_PRAGMA(diagnostic push) \
STDX_PRAGMA(diagnostic ignored "-Wshadow") \
using cib_log_module_id_t [[maybe_unused]] = \
typename logging::module_id_t<S>::type CIB_PRAGMA_SEMI STDX_PRAGMA( \
diagnostic pop)

#define CIB_LOG(FLAVOR, LEVEL, MSG, ...) \
logging::log<FLAVOR, LEVEL, cib_log_module_id_t>( \
logging::log<FLAVOR, LEVEL, cib_log_env_t>( \
__FILE__, __LINE__, sc::format(MSG##_sc __VA_OPT__(, ) __VA_ARGS__))

#define CIB_TRACE(...) \
Expand All @@ -90,7 +73,7 @@ using cib_log_module_id_t = typename logging::module_id_t<"default">::type;
[] { \
constexpr auto str = sc::format(MSG##_sc __VA_OPT__(, ) __VA_ARGS__); \
logging::log<logging::default_flavor_t, logging::level::FATAL, \
cib_log_module_id_t>(__FILE__, __LINE__, str); \
cib_log_env_t>(__FILE__, __LINE__, str); \
str.apply([]<typename S, typename... Args>(S s, Args... args) { \
constexpr auto cts = stdx::ct_string_from_type(s); \
stdx::panic<cts>(args...); \
Expand All @@ -111,7 +94,7 @@ ALWAYS_INLINE static auto log_version() -> void {
}) {
l_cfg.logger.template log_build<v_cfg.build_id, v_cfg.version_string>();
} else {
l_cfg.logger.template log<level::MAX, cib_log_module_id_t>(
l_cfg.logger.template log<level::MAX, cib_log_env_t>(
"", 0,
sc::format("Version: {} ({})"_sc, sc::uint_<v_cfg.build_id>,
stdx::ct_string_to_type<v_cfg.version_string,
Expand Down
27 changes: 27 additions & 0 deletions include/log/module.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <log/env.hpp>

#include <stdx/ct_string.hpp>

#include <utility>

namespace logging {
[[maybe_unused]] constexpr inline struct get_module_t {
template <typename T>
requires true // more constrained
CONSTEVAL auto operator()(T &&t) const noexcept(
noexcept(std::forward<T>(t).query(std::declval<get_module_t>())))
-> decltype(std::forward<T>(t).query(*this)) {
return std::forward<T>(t).query(*this);
}

CONSTEVAL auto operator()(auto &&) const {
using namespace stdx::literals;
return "default"_ctst;
}
} get_module;
} // namespace logging

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define CIB_LOG_MODULE(S) CIB_LOG_ENV(logging::get_module, S)
2 changes: 1 addition & 1 deletion test/log/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
add_tests(FILES log module_id LIBRARIES cib_log)
add_tests(FILES log module_id env LIBRARIES cib_log)
add_tests(FILES fmt_logger LIBRARIES cib_log_fmt)
add_tests(FILES mipi_encoder mipi_logger LIBRARIES cib_log_mipi)

Expand Down
10 changes: 5 additions & 5 deletions test/log/catalog1_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,32 @@ auto log_with_fixed_module_id() -> void;

auto log_zero_args() -> void {
auto cfg = logging::mipi::config{test_log_args_destination{}};
cfg.logger.log_msg<logging::level::TRACE, cib_log_module_id_t>(
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
"A string with no placeholders"_sc);
}

auto log_one_ct_arg() -> void {
auto cfg = logging::mipi::config{test_log_args_destination{}};
cfg.logger.log_msg<logging::level::TRACE, cib_log_module_id_t>(
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
format("B string with {} placeholder"_sc, "one"_sc));
}

auto log_one_rt_arg() -> void {
auto cfg = logging::mipi::config{test_log_args_destination{}};
cfg.logger.log_msg<logging::level::TRACE, cib_log_module_id_t>(
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
format("C string with {} placeholder"_sc, 1));
}

auto log_with_non_default_module_id() -> void {
CIB_LOG_MODULE("not default");
auto cfg = logging::mipi::config{test_log_args_destination{}};
cfg.logger.log_msg<logging::level::TRACE, cib_log_module_id_t>(
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
format("ModuleID string with {} placeholder"_sc, 1));
}

auto log_with_fixed_module_id() -> void {
CIB_LOG_MODULE("fixed");
auto cfg = logging::mipi::config{test_log_args_destination{}};
cfg.logger.log_msg<logging::level::TRACE, cib_log_module_id_t>(
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
format("Fixed ModuleID string with {} placeholder"_sc, 1));
}
2 changes: 1 addition & 1 deletion test/log/catalog2a_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ auto log_two_rt_args() -> void;

auto log_two_rt_args() -> void {
auto cfg = logging::mipi::config{test_log_args_destination{}};
cfg.logger.log_msg<logging::level::TRACE, cib_log_module_id_t>(
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
format("D string with {} and {} placeholder"_sc, 1, 2));
}
2 changes: 1 addition & 1 deletion test/log/catalog2b_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ auto log_rt_enum_arg() -> void;
auto log_rt_enum_arg() -> void {
auto cfg = logging::mipi::config{test_log_args_destination{}};
using namespace ns;
cfg.logger.log_msg<logging::level::TRACE, cib_log_module_id_t>(
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
format("E string with {} placeholder"_sc, E::value));
}
Loading

0 comments on commit 5726ca9

Please sign in to comment.