Skip to content

Commit 8cc712d

Browse files
committed
✨ Add unit to logging
Problem: - Multiple processes may emit the same log calls, and there is no way to tell them apart. The MIPI spec uses a unit field in the catalog message for this purpose. Solution: - Add support for `unit` in a catalog message. Note: - The value of unit is not known at compile time, but it is static for the program, so a function can obtain it.
1 parent 2eb221b commit 8cc712d

File tree

6 files changed

+101
-15
lines changed

6 files changed

+101
-15
lines changed

include/log/catalog/encoder.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <log/module.hpp>
99
#include <log/module_id.hpp>
1010
#include <log/string_id.hpp>
11+
#include <log/unit.hpp>
1112

1213
#include <stdx/ct_string.hpp>
1314
#include <stdx/span.hpp>
@@ -17,7 +18,6 @@
1718
#include <conc/concurrency.hpp>
1819

1920
#include <cstddef>
20-
#include <cstdint>
2121
#include <string_view>
2222
#include <type_traits>
2323
#include <utility>
@@ -81,9 +81,10 @@ template <writer_like Writer> struct log_handler {
8181
using Module =
8282
decltype(detail::to_module<get_module(Env{}),
8383
logging::get_module_id(Env{})>());
84+
auto const unit = get_unit(Env{})();
8485
auto const pkt =
8586
builder.template build<L>(catalog<Message>(), module<Module>(),
86-
std::forward<Args>(args)...);
87+
unit, std::forward<Args>(args)...);
8788
writer(pkt.as_const_view().data());
8889
});
8990
}

include/log/catalog/mipi_builder.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ concept packer = std::integral<typename T::template pack_as_t<int>> and
2424
template <typename, packer> struct builder;
2525

2626
template <packer P> struct builder<defn::short32_msg_t, P> {
27-
template <auto Level> static auto build(string_id id, module_id) {
27+
template <auto Level> static auto build(string_id id, module_id, unit_t) {
2828
using namespace msg;
2929
return owning<defn::short32_msg_t>{"payload"_field = id};
3030
}
3131
};
3232

3333
template <typename Storage, packer P> struct catalog_builder {
3434
template <auto Level, packable... Ts>
35-
static auto build(string_id id, module_id m, Ts... args) {
35+
static auto build(string_id id, module_id m, unit_t u, Ts... args) {
3636
using namespace msg;
37-
defn::catalog_msg_t::owner_t<Storage> message{"severity"_field = Level,
38-
"module_id"_field = m};
37+
defn::catalog_msg_t::owner_t<Storage> message{
38+
"severity"_field = Level, "module_id"_field = m, "unit"_field = u};
3939

4040
using V = typename Storage::value_type;
4141
constexpr auto header_size = defn::catalog_msg_t::size<V>::value;
@@ -115,13 +115,13 @@ template <packer P> struct builder<defn::normal_build_msg_t, P> {
115115

116116
template <packer P = logging::default_arg_packer> struct default_builder {
117117
template <auto Level, packable... Ts>
118-
static auto build(string_id id, module_id m, Ts... args) {
118+
static auto build(string_id id, module_id m, unit_t unit, Ts... args) {
119119
if constexpr (sizeof...(Ts) == 0u) {
120-
return builder<defn::short32_msg_t, P>{}.template build<Level>(id,
121-
m);
120+
return builder<defn::short32_msg_t, P>{}.template build<Level>(
121+
id, m, unit);
122122
} else {
123123
return builder<defn::catalog_msg_t, P>{}.template build<Level>(
124-
id, m, args...);
124+
id, m, unit, args...);
125125
}
126126
}
127127

include/log/catalog/mipi_messages.hpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
#include <msg/message.hpp>
44

5+
#include <cstdint>
6+
57
namespace logging::mipi {
8+
using unit_t = std::uint32_t;
9+
610
namespace defn {
711
using msg::at;
812
using msg::dword_index_t;
@@ -11,9 +15,13 @@ using msg::message;
1115
using msg::operator""_msb;
1216
using msg::operator""_lsb;
1317

14-
enum struct type : uint8_t { Build = 0, Short32 = 1, Catalog = 3 };
15-
enum struct build_subtype : uint8_t { Compact32 = 0, Compact64 = 1, Long = 2 };
16-
enum struct catalog_subtype : uint8_t { Id32_Pack32 = 1 };
18+
enum struct type : std::uint8_t { Build = 0, Short32 = 1, Catalog = 3 };
19+
enum struct build_subtype : std::uint8_t {
20+
Compact32 = 0,
21+
Compact64 = 1,
22+
Long = 2
23+
};
24+
enum struct catalog_subtype : std::uint8_t { Id32_Pack32 = 1 };
1725

1826
using type_f = field<"type", type>::located<at{dword_index_t{0}, 3_msb, 0_lsb}>;
1927
using opt_len_f =
@@ -58,9 +66,11 @@ using severity_f = field<"severity", std::uint8_t>::located<at{dword_index_t{0},
5866
using module_id_f =
5967
field<"module_id",
6068
std::uint8_t>::located<at{dword_index_t{0}, 22_msb, 16_lsb}>;
69+
using unit_f =
70+
field<"unit", std::uint16_t>::located<at{dword_index_t{0}, 15_msb, 12_lsb}>;
6171

6272
using catalog_msg_t =
63-
message<"catalog", type_f::with_required<type::Catalog>, severity_f,
73+
message<"catalog", type_f::with_required<type::Catalog>, severity_f, unit_f,
6474
module_id_f,
6575
catalog_subtype_f::with_required<catalog_subtype::Id32_Pack32>>;
6676
} // namespace defn

include/log/unit.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include <stdx/compiler.hpp>
4+
#include <stdx/utility.hpp>
5+
6+
#include <utility>
7+
8+
namespace logging {
9+
[[maybe_unused]] constexpr inline struct get_unit_t {
10+
template <typename T>
11+
requires true
12+
CONSTEVAL auto operator()(T &&t) const
13+
noexcept(noexcept(std::forward<T>(t).query(std::declval<get_unit_t>())))
14+
-> decltype(std::forward<T>(t).query(*this)) {
15+
return std::forward<T>(t).query(*this);
16+
}
17+
18+
CONSTEVAL auto operator()(auto &&) const {
19+
return [] { return 0; };
20+
}
21+
} get_unit;
22+
} // namespace logging

test/log/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
add_tests(
22
FILES
3+
env
34
level
45
log
56
module_id
6-
env
7+
unit
78
LIBRARIES
89
cib_log)
910
add_tests(FILES fmt_logger LIBRARIES cib_log_fmt)

test/log/unit.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <log/catalog/encoder.hpp>
2+
#include <log/level.hpp>
3+
#include <log/unit.hpp>
4+
5+
#include <stdx/ct_conversions.hpp>
6+
#include <stdx/ct_format.hpp>
7+
#include <stdx/ct_string.hpp>
8+
#include <stdx/span.hpp>
9+
10+
#include <catch2/catch_test_macros.hpp>
11+
12+
#include <cstddef>
13+
#include <cstdint>
14+
15+
template <typename> auto catalog() -> string_id { return 0xdeadbeef; }
16+
template <typename> auto module() -> module_id { return 0x5a; }
17+
18+
namespace {
19+
int log_calls{};
20+
logging::mipi::unit_t test_unit{};
21+
22+
struct test_destination {
23+
template <std::size_t N>
24+
auto operator()(stdx::span<std::uint32_t const, N> pkt) const {
25+
using namespace msg;
26+
auto const msg =
27+
msg::const_view<logging::mipi::defn::catalog_msg_t>{pkt};
28+
CHECK(msg.get("unit"_f) == test_unit);
29+
++log_calls;
30+
}
31+
};
32+
33+
} // namespace
34+
35+
TEST_CASE("mipi logger works with init-time unit", "[unit]") {
36+
log_calls = 0;
37+
test_unit = 5;
38+
CIB_LOG_ENV(logging::get_level, logging::level::TRACE, logging::get_unit,
39+
[] { return test_unit; });
40+
auto cfg = logging::binary::config{test_destination{}};
41+
cfg.logger.log_msg<cib_log_env_t>(stdx::ct_format<"Hello {} {}">(42, 17));
42+
CHECK(log_calls == 1);
43+
}
44+
45+
TEST_CASE("default unit is 0", "[unit]") {
46+
log_calls = 0;
47+
test_unit = 0;
48+
CIB_LOG_ENV(logging::get_level, logging::level::TRACE);
49+
auto cfg = logging::binary::config{test_destination{}};
50+
cfg.logger.log_msg<cib_log_env_t>(stdx::ct_format<"Hello {} {}">(42, 17));
51+
CHECK(log_calls == 1);
52+
}

0 commit comments

Comments
 (0)