From 62819d8bd5e255fd3dc42cab8b0306b7fc933463 Mon Sep 17 00:00:00 2001 From: Ben Deane Date: Tue, 20 May 2025 09:31:44 -0600 Subject: [PATCH] :sparkles: Add fixed module ID query to logging Problem: - String IDs can be fixed in code, but module IDs cannot. It's only a matter of time before someone asks for that. Solution: - Allow module IDs to be fixed in code with a `get_module_id` query. Note: - If a module ID is fixed in an environment, it is advisable also to provide the module string. Otherwise it will be fixing the ID of the "default" module. --- include/log/catalog/encoder.hpp | 9 ++++++--- include/log/module_id.hpp | 19 +++++++++++++++++++ test/log/catalog1_lib.cpp | 19 +++++++++++++++---- test/log/catalog_app.cpp | 21 ++++++++++++++++----- tools/gen_str_catalog.py | 2 ++ 5 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 include/log/module_id.hpp diff --git a/include/log/catalog/encoder.hpp b/include/log/catalog/encoder.hpp index eeac89ee..853bea23 100644 --- a/include/log/catalog/encoder.hpp +++ b/include/log/catalog/encoder.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -31,10 +32,10 @@ constexpr static auto to_message() { }(std::make_integer_sequence{}); } -template constexpr static auto to_module() { +template constexpr static auto to_module() { constexpr auto s = std::string_view{S}; return [&](std::integer_sequence) { - return sc::module_string>{}; + return sc::module_string>{}; }(std::make_integer_sequence{}); } @@ -91,7 +92,9 @@ template struct log_handler { detail::to_message_t::template fn, std::remove_cvref_t...>; - using Module = decltype(detail::to_module()); + using Module = + decltype(detail::to_module()); w(builder.template build(catalog(), module(), std::forward(args)...)); }); diff --git a/include/log/module_id.hpp b/include/log/module_id.hpp new file mode 100644 index 00000000..81a78b81 --- /dev/null +++ b/include/log/module_id.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include + +namespace logging { +[[maybe_unused]] constexpr inline struct get_module_id_t { + template + requires true // more constrained + CONSTEVAL auto operator()(T &&t) const noexcept( + noexcept(std::forward(t).query(std::declval()))) + -> decltype(std::forward(t).query(*this)) { + return std::forward(t).query(*this); + } + + CONSTEVAL auto operator()(auto &&) const -> int { return -1; } +} get_module_id; +} // namespace logging diff --git a/test/log/catalog1_lib.cpp b/test/log/catalog1_lib.cpp index 8048a68d..6ace3933 100644 --- a/test/log/catalog1_lib.cpp +++ b/test/log/catalog1_lib.cpp @@ -30,9 +30,10 @@ auto log_one_ct_arg() -> void; auto log_one_32bit_rt_arg() -> void; auto log_one_64bit_rt_arg() -> void; auto log_one_formatted_rt_arg() -> void; -auto log_with_non_default_module_id() -> void; -auto log_with_fixed_module_id() -> void; +auto log_with_non_default_module() -> void; +auto log_with_fixed_module() -> void; auto log_with_fixed_string_id() -> void; +auto log_with_fixed_module_id() -> void; auto log_zero_args() -> void { auto cfg = logging::binary::config{test_log_args_destination{}}; @@ -65,7 +66,7 @@ auto log_one_formatted_rt_arg() -> void { stdx::ct_format<"C3 string with {:08x} placeholder">(std::int32_t{1})); } -auto log_with_non_default_module_id() -> void { +auto log_with_non_default_module() -> void { CIB_WITH_LOG_ENV(logging::get_level, logging::level::TRACE, logging::get_module, "not default") { auto cfg = logging::binary::config{test_log_args_destination{}}; @@ -74,7 +75,7 @@ auto log_with_non_default_module_id() -> void { } } -auto log_with_fixed_module_id() -> void { +auto log_with_fixed_module() -> void { CIB_WITH_LOG_ENV(logging::get_level, logging::level::TRACE, logging::get_module, "fixed") { auto cfg = logging::binary::config{test_log_args_destination{}}; @@ -91,3 +92,13 @@ auto log_with_fixed_string_id() -> void { stdx::ct_format<"Fixed StringID string">()); } } + +auto log_with_fixed_module_id() -> void { + CIB_WITH_LOG_ENV(logging::get_level, logging::level::TRACE, + logging::get_module_id, 7, logging::get_module, + "fixed_id") { + auto cfg = logging::binary::config{test_log_args_destination{}}; + cfg.logger.log_msg( + stdx::ct_format<"Fixed ModuleID string with {} placeholder">(1)); + } +} diff --git a/test/log/catalog_app.cpp b/test/log/catalog_app.cpp index 2ec740b1..5dcc1901 100644 --- a/test/log/catalog_app.cpp +++ b/test/log/catalog_app.cpp @@ -17,9 +17,10 @@ extern auto log_one_64bit_rt_arg() -> void; extern auto log_one_formatted_rt_arg() -> void; extern auto log_two_rt_args() -> void; extern auto log_rt_enum_arg() -> void; -extern auto log_with_non_default_module_id() -> void; -extern auto log_with_fixed_module_id() -> void; +extern auto log_with_non_default_module() -> void; +extern auto log_with_fixed_module() -> void; extern auto log_with_fixed_string_id() -> void; +extern auto log_with_fixed_module_id() -> void; TEST_CASE("log zero arguments", "[catalog]") { test_critical_section::count = 0; @@ -88,16 +89,17 @@ TEST_CASE("log module ids change", "[catalog]") { CHECK((last_header & expected_static) == expected_static); auto default_header = last_header; - log_with_non_default_module_id(); + log_with_non_default_module(); CHECK((last_header & expected_static) == expected_static); CHECK((last_header ^ default_header) == (1u << 16u)); } -TEST_CASE("log with fixed module id", "[catalog]") { +TEST_CASE("log with stable module id", "[catalog]") { std::uint32_t expected_static = (1u << 24u) | (7u << 4u) | 3u; - log_with_fixed_module_id(); + log_with_fixed_module(); CHECK((last_header & expected_static) == expected_static); + // module ID 17 is fixed by stable_strings.json CHECK((last_header & ~expected_static) == (17u << 16u)); } @@ -110,3 +112,12 @@ TEST_CASE("log with fixed string id", "[catalog]") { // string ID 1337 is fixed by environment CHECK(last_header == ((1337u << 4u) | 1u)); } + +TEST_CASE("log with fixed module id", "[catalog]") { + std::uint32_t expected_static = (1u << 24u) | (7u << 4u) | 3u; + + log_with_fixed_module_id(); + CHECK((last_header & expected_static) == expected_static); + // module ID 7 is fixed by environment + CHECK((last_header & ~expected_static) == (7u << 16u)); +} diff --git a/tools/gen_str_catalog.py b/tools/gen_str_catalog.py index f4bb8316..a6445a09 100755 --- a/tools/gen_str_catalog.py +++ b/tools/gen_str_catalog.py @@ -163,6 +163,8 @@ def get_id(stables, gen, obj): stable_msgs, stable_modules = stable_data for msg in filter(lambda m: m.id != -1, messages): stable_msgs[msg.key()] = msg + for module in filter(lambda m: m.id != -1, modules): + stable_modules[module.key()] = module old_msg_ids = set(m.id for m in stable_msgs.values()) msg_id_gen = itertools.filterfalse(old_msg_ids.__contains__, itertools.count(0))