Skip to content

Commit 903437b

Browse files
authored
Merge pull request #683 from elbeno/custom-log-level
✨ Allow custom log levels
2 parents 7371d3b + 4dbdb14 commit 903437b

16 files changed

+230
-100
lines changed

include/flow/impl.hpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#include <flow/common.hpp>
44
#include <flow/log.hpp>
5+
#include <log/env.hpp>
6+
#include <log/level.hpp>
57
#include <log/log.hpp>
68

79
#include <stdx/ct_string.hpp>
@@ -20,9 +22,9 @@ constexpr auto run_func() -> void {
2022
if constexpr (not FlowName.empty()) {
2123
using log_spec_t =
2224
decltype(get_log_spec<CTNode, log_spec_id_t<FlowName>>());
23-
CIB_LOG(typename log_spec_t::flavor, log_spec_t::level,
24-
"flow.{}({})", typename CTNode::type_t{},
25-
typename CTNode::name_t{});
25+
CIB_LOG_ENV(logging::get_level, log_spec_t::level);
26+
CIB_LOG(typename log_spec_t::flavor, "flow.{}({})",
27+
typename CTNode::type_t{}, typename CTNode::name_t{});
2628
}
2729
typename CTNode::func_t{}();
2830
}
@@ -60,16 +62,16 @@ template <stdx::ct_string Name, auto... FuncPtrs> struct inlined_func_list {
6062

6163
if constexpr (loggingEnabled) {
6264
using log_spec_t = decltype(get_log_spec<inlined_func_list>());
63-
CIB_LOG(typename log_spec_t::flavor, log_spec_t::level,
64-
"flow.start({})", name);
65+
CIB_LOG_ENV(logging::get_level, log_spec_t::level);
66+
CIB_LOG(typename log_spec_t::flavor, "flow.start({})", name);
6567
}
6668

6769
(FuncPtrs(), ...);
6870

6971
if constexpr (loggingEnabled) {
7072
using log_spec_t = decltype(get_log_spec<inlined_func_list>());
71-
CIB_LOG(typename log_spec_t::flavor, log_spec_t::level,
72-
"flow.end({})", name);
73+
CIB_LOG_ENV(logging::get_level, log_spec_t::level);
74+
CIB_LOG(typename log_spec_t::flavor, "flow.end({})", name);
7375
}
7476
}
7577
};

include/log/catalog/mipi_encoder.hpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@
2020

2121
namespace logging::mipi {
2222
namespace detail {
23-
template <logging::level L, typename S, typename... Args>
24-
constexpr auto to_message() {
23+
template <auto L, typename S, typename... Args> constexpr auto to_message() {
2524
constexpr auto s = S::value;
2625
using char_t = typename std::remove_cv_t<decltype(s)>::value_type;
2726
return [&]<std::size_t... Is>(std::integer_sequence<std::size_t, Is...>) {
2827
return sc::message<
29-
L, sc::undefined<sc::args<Args...>, char_t, s[Is]...>>{};
28+
static_cast<logging::level>(L),
29+
sc::undefined<sc::args<Args...>, char_t, s[Is]...>>{};
3030
}(std::make_integer_sequence<std::size_t, std::size(s)>{});
3131
}
3232

@@ -103,21 +103,22 @@ using catalog_msg_t =
103103
template <typename TDestinations> struct log_handler {
104104
constexpr explicit log_handler(TDestinations &&ds) : dests{std::move(ds)} {}
105105

106-
template <logging::level Level, typename Env, typename FilenameStringType,
106+
template <typename Env, typename FilenameStringType,
107107
typename LineNumberType, typename MsgType>
108108
ALWAYS_INLINE auto log(FilenameStringType, LineNumberType,
109109
MsgType const &msg) -> void {
110-
log_msg<Level, Env>(msg);
110+
log_msg<Env>(msg);
111111
}
112112

113-
template <logging::level Level, typename Env, typename Msg>
113+
template <typename Env, typename Msg>
114114
ALWAYS_INLINE auto log_msg(Msg msg) -> void {
115115
msg.apply([&]<typename S, typename... Args>(S, Args... args) {
116-
using Message = decltype(detail::to_message<Level, S, Args...>());
116+
constexpr auto L = stdx::to_underlying(get_level(Env{}).value);
117+
using Message = decltype(detail::to_message<L, S, Args...>());
117118
using Module =
118119
decltype(detail::to_module<get_module(Env{}).value>());
119-
dispatch_message<Level>(catalog<Message>(), module<Module>(),
120-
static_cast<std::uint32_t>(args)...);
120+
dispatch_message<L>(catalog<Message>(), module<Module>(),
121+
static_cast<std::uint32_t>(args)...);
121122
});
122123
}
123124

@@ -173,7 +174,7 @@ template <typename TDestinations> struct log_handler {
173174
dests);
174175
}
175176

176-
template <logging::level Level, std::same_as<std::uint32_t>... MsgDataTypes>
177+
template <auto Level, std::same_as<std::uint32_t>... MsgDataTypes>
177178
ALWAYS_INLINE auto dispatch_message(string_id id,
178179
[[maybe_unused]] module_id m,
179180
MsgDataTypes... msg_data) -> void {

include/log/env.hpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,16 @@ template <std::size_t... Is> struct for_each_pair<std::index_sequence<Is...>> {
6969
2 * Is + 1>::value.value>()>...>;
7070
};
7171
} // namespace detail
72+
73+
template <typename Env = env<>>
74+
constexpr auto make_env = []<detail::autowrap... Args> {
75+
using new_env_t = typename detail::for_each_pair<
76+
std::make_index_sequence<sizeof...(Args) / 2>>::template type<Args...>;
77+
return boost::mp11::mp_append<new_env_t, Env>{};
78+
};
79+
80+
template <detail::autowrap... Args>
81+
using make_env_t = decltype(make_env<>.template operator()<Args...>());
7282
} // namespace logging
7383

7484
using cib_log_env_t = logging::env<>;
@@ -82,10 +92,11 @@ using cib_log_env_t = logging::env<>;
8292
#endif
8393

8494
#define CIB_LOG_ENV_DECL(...) \
85-
[[maybe_unused]] typedef decltype([]<logging::detail::autowrap... Args> { \
95+
[[maybe_unused]] typedef decltype([]<logging::detail:: \
96+
autowrap... _env_args> { \
8697
using new_env_t = \
8798
typename logging::detail::for_each_pair<std::make_index_sequence< \
88-
sizeof...(Args) / 2>>::template type<Args...>; \
99+
sizeof...(_env_args) / 2>>::template type<_env_args...>; \
89100
return boost::mp11::mp_append<new_env_t, cib_log_env_t>{}; \
90101
}.template operator()<__VA_ARGS__>()) cib_log_env_t
91102

include/log/fmt/logger.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
#pragma once
22

3+
#include <log/level.hpp>
34
#include <log/log.hpp>
45
#include <log/module.hpp>
56

67
#include <stdx/ct_format.hpp>
78
#include <stdx/tuple.hpp>
89
#include <stdx/tuple_algorithms.hpp>
10+
#include <stdx/utility.hpp>
911

1012
#include <fmt/format.h>
1113

1214
#include <chrono>
15+
#include <type_traits>
1316
#include <utility>
1417

15-
template <auto L> struct fmt::formatter<logging::level_constant<L>> {
18+
template <logging::level L>
19+
struct fmt::formatter<std::integral_constant<logging::level, L>> {
1620
constexpr static auto parse(format_parse_context &ctx) {
1721
return ctx.begin();
1822
}
1923

2024
template <typename FormatContext>
21-
auto format(logging::level_constant<L>, FormatContext &ctx) const {
25+
auto format(std::integral_constant<logging::level, L>,
26+
FormatContext &ctx) const {
2227
return ::fmt::format_to(ctx.out(), logging::to_text<L>());
2328
}
2429
};
@@ -27,7 +32,7 @@ namespace logging::fmt {
2732
template <typename TDestinations> struct log_handler {
2833
constexpr explicit log_handler(TDestinations &&ds) : dests{std::move(ds)} {}
2934

30-
template <logging::level L, typename Env, typename FilenameStringType,
35+
template <typename Env, typename FilenameStringType,
3136
typename LineNumberType, typename MsgType>
3237
auto log(FilenameStringType, LineNumberType, MsgType const &msg) -> void {
3338
auto const currentTime =
@@ -38,7 +43,7 @@ template <typename TDestinations> struct log_handler {
3843
stdx::for_each(
3944
[&](auto &out) {
4045
::fmt::format_to(out, "{:>8}us {} [{}]: ", currentTime,
41-
level_constant<L>{}, get_module(Env{}).value);
46+
get_level(Env{}), get_module(Env{}).value);
4247
msg.apply(
4348
[&]<typename StringType>(StringType, auto const &...args) {
4449
::fmt::format_to(out, StringType::value, args...);

include/log/level.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
#pragma once
22

3+
#include <log/env.hpp>
4+
35
#include <stdx/type_traits.hpp>
46

57
#include <array>
68
#include <cstdint>
79
#include <string_view>
810
#include <type_traits>
11+
#include <utility>
912

1013
namespace logging {
1114
// enum assignment is according to Mipi_Sys-T Severity definition
@@ -30,5 +33,12 @@ template <level L>
3033
return level_text[stdx::to_underlying(L)];
3134
}
3235

33-
template <level L> struct level_constant : std::integral_constant<level, L> {};
36+
[[maybe_unused]] constexpr inline struct get_level_t {
37+
template <typename T>
38+
CONSTEVAL auto operator()(T &&t) const noexcept(
39+
noexcept(std::forward<T>(t).query(std::declval<get_level_t>())))
40+
-> decltype(std::forward<T>(t).query(*this)) {
41+
return std::forward<T>(t).query(*this);
42+
}
43+
} get_level;
3444
} // namespace logging

include/log/log.hpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace logging {
2727
namespace null {
2828
struct config {
2929
struct {
30-
template <level, typename>
30+
template <typename>
3131
constexpr auto log(auto &&...) const noexcept -> void {}
3232
} logger;
3333
};
@@ -46,33 +46,39 @@ ALWAYS_INLINE constexpr static auto get_config() -> auto & {
4646
}
4747
}
4848

49-
template <typename Flavor, level L, typename Env, typename... Ts,
50-
typename... TArgs>
49+
template <typename Flavor, typename Env, typename... Ts, typename... TArgs>
5150
ALWAYS_INLINE static auto log(TArgs &&...args) -> void {
5251
auto &cfg = get_config<Flavor, Ts...>();
53-
cfg.logger.template log<L, Env>(std::forward<TArgs>(args)...);
52+
cfg.logger.template log<Env>(std::forward<TArgs>(args)...);
5453
}
5554
} // namespace logging
5655

5756
// NOLINTBEGIN(cppcoreguidelines-macro-usage)
5857

59-
#define CIB_LOG(FLAVOR, LEVEL, MSG, ...) \
60-
logging::log<FLAVOR, LEVEL, cib_log_env_t>( \
58+
#define CIB_LOG(FLAVOR, MSG, ...) \
59+
logging::log<FLAVOR, cib_log_env_t>( \
6160
__FILE__, __LINE__, sc::format(MSG##_sc __VA_OPT__(, ) __VA_ARGS__))
6261

62+
#define CIB_LOG_WITH_LEVEL(LEVEL, ...) \
63+
do { \
64+
CIB_LOG_ENV(logging::get_level, LEVEL); \
65+
CIB_LOG(logging::default_flavor_t __VA_OPT__(, ) __VA_ARGS__); \
66+
} while (false)
67+
6368
#define CIB_TRACE(...) \
64-
CIB_LOG(logging::default_flavor_t, logging::level::TRACE, __VA_ARGS__)
69+
CIB_LOG_WITH_LEVEL(logging::level::TRACE __VA_OPT__(, ) __VA_ARGS__)
6570
#define CIB_INFO(...) \
66-
CIB_LOG(logging::default_flavor_t, logging::level::INFO, __VA_ARGS__)
71+
CIB_LOG_WITH_LEVEL(logging::level::INFO __VA_OPT__(, ) __VA_ARGS__)
6772
#define CIB_WARN(...) \
68-
CIB_LOG(logging::default_flavor_t, logging::level::WARN, __VA_ARGS__)
73+
CIB_LOG_WITH_LEVEL(logging::level::WARN __VA_OPT__(, ) __VA_ARGS__)
6974
#define CIB_ERROR(...) \
70-
CIB_LOG(logging::default_flavor_t, logging::level::ERROR, __VA_ARGS__)
75+
CIB_LOG_WITH_LEVEL(logging::level::ERROR __VA_OPT__(, ) __VA_ARGS__)
7176

7277
#define CIB_FATAL(MSG, ...) \
7378
[](auto &&str) { \
74-
logging::log<logging::default_flavor_t, logging::level::FATAL, \
75-
cib_log_env_t>(__FILE__, __LINE__, str); \
79+
CIB_LOG_ENV(logging::get_level, logging::level::FATAL); \
80+
logging::log<logging::default_flavor_t, cib_log_env_t>(__FILE__, \
81+
__LINE__, str); \
7682
FWD(str).apply([]<typename S, typename... Args>(S s, Args... args) { \
7783
constexpr auto cts = stdx::ct_string_from_type(s); \
7884
stdx::panic<cts>(args...); \
@@ -93,7 +99,8 @@ ALWAYS_INLINE static auto log_version() -> void {
9399
}) {
94100
l_cfg.logger.template log_build<v_cfg.build_id, v_cfg.version_string>();
95101
} else {
96-
l_cfg.logger.template log<level::MAX, cib_log_env_t>(
102+
CIB_LOG_ENV(logging::get_level, logging::level::MAX);
103+
l_cfg.logger.template log<cib_log_env_t>(
97104
"", 0,
98105
sc::format("Version: {} ({})"_sc, sc::uint_<v_cfg.build_id>,
99106
stdx::ct_string_to_type<v_cfg.version_string,

test/flow/custom_log_levels.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <cib/cib.hpp>
22
#include <flow/flow.hpp>
3+
#include <log/level.hpp>
34

45
#include <catch2/catch_test_macros.hpp>
56

@@ -37,11 +38,10 @@ constexpr auto msB = flow::milestone<"msB">();
3738

3839
struct log_config {
3940
struct log_handler {
40-
template <logging::level Level, typename ModuleId,
41-
typename FilenameStringType, typename LineNumberType,
42-
typename MsgType>
41+
template <typename Env, typename FilenameStringType,
42+
typename LineNumberType, typename MsgType>
4343
auto log(FilenameStringType, LineNumberType, MsgType const &) -> void {
44-
log_calls.push_back(Level);
44+
log_calls.push_back(logging::get_level(Env{}).value);
4545
}
4646
};
4747
log_handler logger;

test/flow/log_levels.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <cib/cib.hpp>
22
#include <flow/flow.hpp>
3+
#include <log/level.hpp>
34

45
#include <catch2/catch_test_macros.hpp>
56

@@ -34,11 +35,10 @@ constexpr auto ms = flow::milestone<"ms">();
3435

3536
struct log_config {
3637
struct log_handler {
37-
template <logging::level Level, typename ModuleId,
38-
typename FilenameStringType, typename LineNumberType,
39-
typename MsgType>
38+
template <typename Env, typename FilenameStringType,
39+
typename LineNumberType, typename MsgType>
4040
auto log(FilenameStringType, LineNumberType, MsgType const &) -> void {
41-
log_calls.push_back(Level);
41+
log_calls.push_back(logging::get_level(Env{}).value);
4242
}
4343
};
4444
log_handler logger;

test/log/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
add_tests(FILES log module_id env LIBRARIES cib_log)
1+
add_tests(
2+
FILES
3+
level
4+
log
5+
module_id
6+
env
7+
LIBRARIES
8+
cib_log)
29
add_tests(FILES fmt_logger LIBRARIES cib_log_fmt)
310
add_tests(FILES mipi_encoder mipi_logger LIBRARIES cib_log_mipi)
411

test/log/catalog1_lib.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ struct test_log_args_destination {
1717
last_header = hdr;
1818
}
1919
};
20+
21+
using log_env1 = logging::make_env_t<logging::get_level, logging::level::TRACE>;
2022
} // namespace
2123

2224
auto log_zero_args() -> void;
@@ -27,32 +29,34 @@ auto log_with_fixed_module_id() -> void;
2729

2830
auto log_zero_args() -> void {
2931
auto cfg = logging::mipi::config{test_log_args_destination{}};
30-
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
31-
"A string with no placeholders"_sc);
32+
cfg.logger.log_msg<log_env1>("A string with no placeholders"_sc);
3233
}
3334

3435
auto log_one_ct_arg() -> void {
3536
auto cfg = logging::mipi::config{test_log_args_destination{}};
36-
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
37+
cfg.logger.log_msg<log_env1>(
3738
format("B string with {} placeholder"_sc, "one"_sc));
3839
}
3940

4041
auto log_one_rt_arg() -> void {
4142
auto cfg = logging::mipi::config{test_log_args_destination{}};
42-
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
43-
format("C string with {} placeholder"_sc, 1));
43+
cfg.logger.log_msg<log_env1>(format("C string with {} placeholder"_sc, 1));
4444
}
4545

4646
auto log_with_non_default_module_id() -> void {
47-
CIB_LOG_MODULE("not default");
48-
auto cfg = logging::mipi::config{test_log_args_destination{}};
49-
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
50-
format("ModuleID string with {} placeholder"_sc, 1));
47+
CIB_WITH_LOG_ENV(logging::get_level, logging::level::TRACE,
48+
logging::get_module, "not default") {
49+
auto cfg = logging::mipi::config{test_log_args_destination{}};
50+
cfg.logger.log_msg<cib_log_env_t>(
51+
format("ModuleID string with {} placeholder"_sc, 1));
52+
}
5153
}
5254

5355
auto log_with_fixed_module_id() -> void {
54-
CIB_LOG_MODULE("fixed");
55-
auto cfg = logging::mipi::config{test_log_args_destination{}};
56-
cfg.logger.log_msg<logging::level::TRACE, cib_log_env_t>(
57-
format("Fixed ModuleID string with {} placeholder"_sc, 1));
56+
CIB_WITH_LOG_ENV(logging::get_level, logging::level::TRACE,
57+
logging::get_module, "fixed") {
58+
auto cfg = logging::mipi::config{test_log_args_destination{}};
59+
cfg.logger.log_msg<cib_log_env_t>(
60+
format("Fixed ModuleID string with {} placeholder"_sc, 1));
61+
}
5862
}

0 commit comments

Comments
 (0)