Skip to content

Commit 2c6ad02

Browse files
committed
🎨 Separate MIPI support from binary logger machinery
Problem: - It is useful to have a binary message logger for any format, not just for MIPI-SyS-T. Solution: - Separate the MIPI message building entirely from the binary catalog-based logger.
1 parent cb81efb commit 2c6ad02

16 files changed

+162
-110
lines changed

CMakeLists.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,13 @@ target_sources(
193193
FILES
194194
include/log/fmt/logger.hpp)
195195

196-
add_library(cib_log_mipi INTERFACE)
197-
target_compile_features(cib_log_mipi INTERFACE cxx_std_20)
198-
target_link_libraries_system(cib_log_mipi INTERFACE cib_log cib_msg concurrency
199-
stdx)
196+
add_library(cib_log_binary INTERFACE)
197+
target_compile_features(cib_log_binary INTERFACE cxx_std_20)
198+
target_link_libraries_system(cib_log_binary INTERFACE cib_log cib_msg
199+
concurrency stdx)
200200

201201
target_sources(
202-
cib_log_mipi
202+
cib_log_binary
203203
INTERFACE FILE_SET
204204
log
205205
TYPE
@@ -208,8 +208,8 @@ target_sources(
208208
include
209209
FILES
210210
include/log/catalog/catalog.hpp
211+
include/log/catalog/encoder.hpp
211212
include/log/catalog/mipi_builder.hpp
212-
include/log/catalog/mipi_encoder.hpp
213213
include/log/catalog/mipi_messages.hpp)
214214

215215
add_library(cib_nexus INTERFACE)
@@ -298,8 +298,8 @@ target_link_libraries_system(
298298
cib_flow
299299
cib_interrupt
300300
cib_log
301+
cib_log_binary
301302
cib_log_fmt
302-
cib_log_mipi
303303
cib_lookup
304304
cib_match
305305
cib_msg
@@ -329,8 +329,8 @@ if(PROJECT_IS_TOP_LEVEL)
329329
clang_tidy_interface(cib_interrupt)
330330
clang_tidy_interface(cib_lookup)
331331
clang_tidy_interface(cib_log)
332+
clang_tidy_interface(cib_log_binary)
332333
clang_tidy_interface(cib_log_fmt)
333-
clang_tidy_interface(cib_log_mipi)
334334
clang_tidy_interface(cib_match)
335335
clang_tidy_interface(cib_msg)
336336
clang_tidy_interface(cib_nexus)

docs/intro.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ flowchart BT
7373
msg(cib_msg) --> log & match
7474
msg --> lookup
7575
76-
log_mipi(cib_log_mipi) --> msg
76+
log_binary(cib_log_binary) --> msg
7777
seq(cib_seq) --> flow
7878
79-
cib --> interrupt & seq & log_fmt & log_mipi
79+
cib --> interrupt & seq & log_fmt & log_binary
8080
----

docs/logging.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Logging in _cib_ is in two parts:
1414
Three possible logger implementations are provided:
1515

1616
- one using fmt in https://github.com/intel/compile-time-init-build/tree/main/include/log/fmt/logger.hpp[fmt/logger.hpp]
17-
- one using the https://www.mipi.org/specifications/sys-t[MIPI Sys-T spec] in https://github.com/intel/compile-time-init-build/tree/main/include/log/catalog/mipi_encoder.hpp[catalog/mipi_encoder.hpp]
17+
- one using binary encoding in https://github.com/intel/compile-time-init-build/tree/main/include/log/catalog/encoder.hpp[catalog/encoder.hpp], using the https://www.mipi.org/specifications/sys-t[MIPI Sys-T spec] by default
1818
- the default implementation: the null logger which accepts everything, but never produces output
1919

2020
=== Log levels
@@ -208,22 +208,22 @@ template <> inline auto version::config<> = my_version_config{};
208208
----
209209

210210
Then use `CIB_LOG_VERSION()` to log the version. If the logging config provides
211-
a `log_build` function, that will be used. Otherwise a text string will be
211+
a `log_version` function, that will be used. Otherwise a text string will be
212212
logged.
213213

214214
[source,cpp]
215215
----
216216
struct my_logger_config {
217217
struct {
218-
template <auto Version, stdx::ct_string S = ""> auto log_build() -> void {
218+
template <auto Version, stdx::ct_string S = ""> auto log_version() -> void {
219219
// log the build version according to my mechanism
220220
}
221221
} logger;
222222
};
223223
template <>
224224
inline auto logging::config<> = my_logger_config{};
225225
226-
CIB_LOG_VERSION(); // calls my_logger_config::log_build
226+
CIB_LOG_VERSION(); // calls my_logger_config::log_version
227227
----
228228

229229
The easiest way to flavor the version logging is to define a macro in terms of

docs/sc.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static_assert("Hello,"_sc + " World!"_sc == "Hello, World!"_sc);
4343
The reason `string_constant` exists is for efficient logging. On a constrained
4444
system, space for text can be limited-to-nonexistent. `string_constant`
4545
interacts with the
46-
https://github.com/intel/compile-time-init-build/tree/main/include/log/catalog/mipi_encoder.hpp[MIPI
46+
https://github.com/intel/compile-time-init-build/tree/main/include/log/catalog/encoder.hpp[MIPI
4747
Sys-T logging config] to solve this problem.
4848

4949
- First, each `string_constant` contains string character data in its type.

include/log/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Logging in *cib* is in two parts:
66

77
Three possible logger implementations are provided:
88
- one using libfmt in [fmt/logger.hpp](fmt/logger.hpp)
9-
- one using the [MIPI SyS-T spec](https://www.mipi.org/specifications/sys-t), in [catalog/mipi_encoder.hpp](catalog/mipi_encoder.hpp)
9+
- a binary logger in [catalog/encoder.hpp](catalog/encoder.hpp), by default using the [MIPI SyS-T spec](https://www.mipi.org/specifications/sys-t)
1010
- the null logger (accepts everything, never produces output)
1111

1212
## log levels

include/log/catalog/builder.hpp

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

3+
#include <log/catalog/builder.hpp>
34
#include <log/catalog/catalog.hpp>
4-
#include <log/catalog/mipi_builder.hpp>
5-
#include <log/catalog/mipi_messages.hpp>
65
#include <log/log.hpp>
76
#include <log/module.hpp>
87

9-
#include <stdx/bit.hpp>
10-
#include <stdx/compiler.hpp>
118
#include <stdx/ct_string.hpp>
9+
#include <stdx/span.hpp>
1210
#include <stdx/tuple.hpp>
1311
#include <stdx/utility.hpp>
1412

1513
#include <conc/concurrency.hpp>
1614

17-
#include <algorithm>
18-
#include <concepts>
15+
#include <cstddef>
1916
#include <cstdint>
2017
#include <string_view>
18+
#include <type_traits>
2119
#include <utility>
2220

23-
namespace logging::mipi {
21+
namespace logging::binary {
2422
namespace detail {
25-
template <typename S, typename... Args> constexpr auto to_message() {
23+
template <typename S, typename... Args> constexpr static auto to_message() {
2624
constexpr auto s = S::value;
2725
using char_t = typename std::remove_cv_t<decltype(s)>::value_type;
2826
return [&]<std::size_t... Is>(std::integer_sequence<std::size_t, Is...>) {
2927
return sc::message<
30-
sc::undefined<sc::args<encode_as_t<Args>...>, char_t, s[Is]...>>{};
28+
sc::undefined<sc::args<Args...>, char_t, s[Is]...>>{};
3129
}(std::make_integer_sequence<std::size_t, std::size(s)>{});
3230
}
3331

34-
template <stdx::ct_string S> constexpr auto to_module() {
32+
template <stdx::ct_string S> constexpr static auto to_module() {
3533
constexpr auto s = std::string_view{S};
3634
return [&]<std::size_t... Is>(std::integer_sequence<std::size_t, Is...>) {
3735
return sc::module_string<sc::undefined<void, char, s[Is]...>>{};
3836
}(std::make_integer_sequence<std::size_t, std::size(s)>{});
3937
}
38+
39+
template <typename S> struct to_message_t {
40+
template <typename... Args> using fn = decltype(to_message<S, Args...>());
41+
};
4042
} // namespace detail
4143

4244
template <typename Destinations> struct log_writer {
@@ -62,6 +64,10 @@ template <typename Destinations> struct log_writer {
6264
}(std::make_index_sequence<N>{});
6365
}
6466

67+
auto operator()(auto const &msg) -> void {
68+
this->operator()(msg.as_const_view().data());
69+
}
70+
6571
Destinations dests;
6672
};
6773
template <typename T> log_writer(T) -> log_writer<T>;
@@ -75,46 +81,22 @@ template <typename Writer> struct log_handler {
7581

7682
template <typename Env, typename Msg> auto log_msg(Msg msg) -> void {
7783
msg.apply([&]<typename S, typename... Args>(S, Args... args) {
84+
auto builder = get_builder(Env{});
7885
constexpr auto L = stdx::to_underlying(get_level(Env{}));
79-
using Message = decltype(detail::to_message<S, Args...>());
86+
using Message = decltype(builder)::template convert_args<
87+
detail::to_message_t<S>::template fn, Args...>;
8088
using Module = decltype(detail::to_module<get_module(Env{})>());
81-
auto builder = get_builder(Env{});
82-
write(builder.template build<L>(catalog<Message>(),
83-
module<Module>(), args...));
89+
w(builder.template build<L>(catalog<Message>(), module<Module>(),
90+
args...));
8491
});
8592
}
8693

87-
template <auto Version, stdx::ct_string S = ""> auto log_build() -> void {
88-
using namespace msg;
89-
if constexpr (S.empty() and stdx::bit_width(Version) <= 22) {
90-
owning<defn::compact32_build_msg_t> message{"build_id"_field =
91-
Version};
92-
write(message);
93-
} else if constexpr (S.empty() and stdx::bit_width(Version) <= 54) {
94-
owning<defn::compact64_build_msg_t> message{"build_id"_field =
95-
Version};
96-
write(message);
97-
} else {
98-
constexpr auto header_size =
99-
defn::normal_build_msg_t::size<std::uint8_t>::value;
100-
constexpr auto payload_len = S.size() + sizeof(std::uint64_t);
101-
using storage_t =
102-
std::array<std::uint8_t, header_size + payload_len>;
103-
104-
defn::normal_build_msg_t::owner_t<storage_t> message{
105-
"payload_len"_field = payload_len};
106-
auto dest = &message.data()[header_size];
107-
108-
auto const ver = stdx::to_le(static_cast<std::uint64_t>(Version));
109-
dest = std::copy_n(stdx::bit_cast<std::uint8_t const *>(&ver),
110-
sizeof(std::uint64_t), dest);
111-
std::copy_n(std::cbegin(S.value), S.size(), dest);
112-
write(message);
113-
}
94+
template <typename Env, auto Version, stdx::ct_string S = "">
95+
auto log_version() -> void {
96+
auto builder = get_builder(Env{});
97+
w(builder.template build_version<Version, S>());
11498
}
11599

116-
auto write(auto const &msg) -> void { w(msg.as_const_view().data()); }
117-
118100
Writer w;
119101
};
120102

@@ -126,4 +108,4 @@ template <typename... TDestinations> struct config {
126108
log_handler<log_writer<destinations_tuple_t>> logger;
127109
};
128110
template <typename... Ts> config(Ts...) -> config<Ts...>;
129-
} // namespace logging::mipi
111+
} // namespace logging::binary

include/log/catalog/mipi_builder.hpp

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <array>
1111
#include <concepts>
12+
#include <cstddef>
1213
#include <cstdint>
1314
#include <cstring>
1415
#include <utility>
@@ -111,6 +112,40 @@ template <> struct builder<defn::catalog_msg_t> {
111112
}
112113
};
113114

115+
template <> struct builder<defn::compact32_build_msg_t> {
116+
template <auto Version> static auto build() {
117+
using namespace msg;
118+
return owning<defn::compact32_build_msg_t>{"build_id"_field = Version};
119+
}
120+
};
121+
122+
template <> struct builder<defn::compact64_build_msg_t> {
123+
template <auto Version> static auto build() {
124+
using namespace msg;
125+
return owning<defn::compact64_build_msg_t>{"build_id"_field = Version};
126+
}
127+
};
128+
129+
template <> struct builder<defn::normal_build_msg_t> {
130+
template <auto Version, stdx::ct_string S> static auto build() {
131+
using namespace msg;
132+
constexpr auto header_size =
133+
defn::normal_build_msg_t::size<std::uint8_t>::value;
134+
constexpr auto payload_len = S.size() + sizeof(std::uint64_t);
135+
using storage_t = std::array<std::uint8_t, header_size + payload_len>;
136+
137+
defn::normal_build_msg_t::owner_t<storage_t> message{
138+
"payload_len"_field = payload_len};
139+
auto dest = &message.data()[header_size];
140+
141+
auto const ver = stdx::to_le(static_cast<std::uint64_t>(Version));
142+
dest = std::copy_n(stdx::bit_cast<std::uint8_t const *>(&ver),
143+
sizeof(std::uint64_t), dest);
144+
std::copy_n(std::cbegin(S.value), S.size(), dest);
145+
return message;
146+
}
147+
};
148+
114149
struct default_builder {
115150
template <auto Level, packable... Ts>
116151
static auto build(string_id id, module_id m, Ts... args) {
@@ -121,17 +156,22 @@ struct default_builder {
121156
id, m, args...);
122157
}
123158
}
124-
};
125159

126-
[[maybe_unused]] constexpr inline struct get_builder_t {
127-
template <typename T>
128-
requires true
129-
CONSTEVAL auto operator()(T &&t) const noexcept(
130-
noexcept(std::forward<T>(t).query(std::declval<get_builder_t>())))
131-
-> decltype(std::forward<T>(t).query(*this)) {
132-
return std::forward<T>(t).query(*this);
160+
template <auto Version, stdx::ct_string S = ""> auto build_version() {
161+
using namespace msg;
162+
if constexpr (S.empty() and stdx::bit_width(Version) <= 22) {
163+
return builder<defn::compact32_build_msg_t>{}
164+
.template build<Version>();
165+
} else if constexpr (S.empty() and stdx::bit_width(Version) <= 54) {
166+
return builder<defn::compact64_build_msg_t>{}
167+
.template build<Version>();
168+
} else {
169+
return builder<defn::normal_build_msg_t>{}
170+
.template build<Version, S>();
171+
}
133172
}
134173

135-
CONSTEVAL auto operator()(auto &&) const { return default_builder{}; }
136-
} get_builder;
174+
template <template <typename...> typename F, typename... Args>
175+
using convert_args = F<encode_as_t<Args>...>;
176+
};
137177
} // namespace logging::mipi

include/log/log.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@ template <typename Env, typename... Ts> static auto log_version() -> void {
9393
auto &l_cfg = get_config<Env, Ts...>();
9494
auto &v_cfg = ::version::config<Ts...>;
9595
if constexpr (requires {
96-
l_cfg.logger.template log_build<v_cfg.build_id,
97-
v_cfg.version_string>();
96+
l_cfg.logger.template log_version<Env, v_cfg.build_id,
97+
v_cfg.version_string>();
9898
}) {
99-
l_cfg.logger.template log_build<v_cfg.build_id, v_cfg.version_string>();
99+
l_cfg.logger
100+
.template log_version<Env, v_cfg.build_id, v_cfg.version_string>();
100101
} else {
101102
CIB_LOG_ENV(logging::get_level, logging::level::MAX);
102103
l_cfg.logger.template log<cib_log_env_t>(

test/log/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ add_tests(
77
LIBRARIES
88
cib_log)
99
add_tests(FILES fmt_logger LIBRARIES cib_log_fmt)
10-
add_tests(FILES mipi_encoder mipi_logger LIBRARIES cib_log_mipi)
10+
add_tests(FILES encoder mipi_logger LIBRARIES cib_log_binary)
1111

1212
add_library(catalog1_lib STATIC catalog1_lib.cpp)
1313
add_library(catalog2_lib OBJECT catalog2a_lib.cpp catalog2b_lib.cpp)
@@ -50,7 +50,7 @@ add_unit_test(
5050
catalog_app.cpp
5151
LIBRARIES
5252
warnings
53-
cib_log_mipi
53+
cib_log_binary
5454
catalog1_lib
5555
catalog2_lib
5656
catalog_strings)

0 commit comments

Comments
 (0)