Skip to content

Commit 6f952f1

Browse files
authored
Merge pull request #706 from elbeno/mipi-writer-config
🎨 Separate log writer from logger
2 parents d40c4de + 989bd11 commit 6f952f1

17 files changed

+247
-193
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

include/log/catalog/encoder.hpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#pragma once
2+
3+
#include <log/catalog/builder.hpp>
4+
#include <log/catalog/catalog.hpp>
5+
#include <log/log.hpp>
6+
#include <log/module.hpp>
7+
8+
#include <stdx/ct_string.hpp>
9+
#include <stdx/span.hpp>
10+
#include <stdx/tuple.hpp>
11+
#include <stdx/utility.hpp>
12+
13+
#include <conc/concurrency.hpp>
14+
15+
#include <cstddef>
16+
#include <cstdint>
17+
#include <string_view>
18+
#include <type_traits>
19+
#include <utility>
20+
21+
namespace logging::binary {
22+
namespace detail {
23+
template <typename S, typename... Args> constexpr static auto to_message() {
24+
constexpr auto s = S::value;
25+
using char_t = typename std::remove_cv_t<decltype(s)>::value_type;
26+
return [&]<std::size_t... Is>(std::integer_sequence<std::size_t, Is...>) {
27+
return sc::message<
28+
sc::undefined<sc::args<Args...>, char_t, s[Is]...>>{};
29+
}(std::make_integer_sequence<std::size_t, std::size(s)>{});
30+
}
31+
32+
template <stdx::ct_string S> constexpr static auto to_module() {
33+
constexpr auto s = std::string_view{S};
34+
return [&]<std::size_t... Is>(std::integer_sequence<std::size_t, Is...>) {
35+
return sc::module_string<sc::undefined<void, char, s[Is]...>>{};
36+
}(std::make_integer_sequence<std::size_t, std::size(s)>{});
37+
}
38+
39+
template <typename S> struct to_message_t {
40+
template <typename... Args> using fn = decltype(to_message<S, Args...>());
41+
};
42+
} // namespace detail
43+
44+
template <typename Destinations> struct log_writer {
45+
template <std::size_t N>
46+
auto operator()(stdx::span<std::uint8_t const, N> msg) -> void {
47+
stdx::for_each(
48+
[&]<typename Dest>(Dest &dest) {
49+
conc::call_in_critical_section<Dest>(
50+
[&] { dest.log_by_buf(msg); });
51+
},
52+
dests);
53+
}
54+
55+
template <std::size_t N>
56+
auto operator()(stdx::span<std::uint32_t const, N> msg) -> void {
57+
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
58+
stdx::for_each(
59+
[&]<typename Dest>(Dest &dest) {
60+
conc::call_in_critical_section<Dest>(
61+
[&] { dest.log_by_args(msg[Is]...); });
62+
},
63+
dests);
64+
}(std::make_index_sequence<N>{});
65+
}
66+
67+
auto operator()(auto const &msg) -> void {
68+
this->operator()(msg.as_const_view().data());
69+
}
70+
71+
Destinations dests;
72+
};
73+
template <typename T> log_writer(T) -> log_writer<T>;
74+
75+
template <typename Writer> struct log_handler {
76+
template <typename Env, typename FilenameStringType,
77+
typename LineNumberType, typename MsgType>
78+
auto log(FilenameStringType, LineNumberType, MsgType const &msg) -> void {
79+
log_msg<Env>(msg);
80+
}
81+
82+
template <typename Env, typename Msg> auto log_msg(Msg msg) -> void {
83+
msg.apply([&]<typename S, typename... Args>(S, Args... args) {
84+
auto builder = get_builder(Env{});
85+
constexpr auto L = stdx::to_underlying(get_level(Env{}));
86+
using Message = typename decltype(builder)::template convert_args<
87+
detail::to_message_t<S>::template fn, Args...>;
88+
using Module = decltype(detail::to_module<get_module(Env{})>());
89+
w(builder.template build<L>(catalog<Message>(), module<Module>(),
90+
args...));
91+
});
92+
}
93+
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>());
98+
}
99+
100+
Writer w;
101+
};
102+
103+
template <typename... TDestinations> struct config {
104+
using destinations_tuple_t = stdx::tuple<TDestinations...>;
105+
constexpr explicit config(TDestinations... dests)
106+
: logger{log_writer{stdx::tuple{std::move(dests)...}}} {}
107+
108+
log_handler<log_writer<destinations_tuple_t>> logger;
109+
};
110+
template <typename... Ts> config(Ts...) -> config<Ts...>;
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

0 commit comments

Comments
 (0)