@@ -44,6 +44,13 @@ struct log_channel_config {
4444 bool should_print_context = false ;
4545};
4646
47+ // / Strong type to wrap a constant log label that is prepended to each log message.
48+ struct log_label_t {
49+ // / Optional log label. If set, will get printed in front of each log message.
50+ // / Disabled by default.
51+ std::string log_label;
52+ };
53+
4754// / A log channel is the entity used for logging messages.
4855// /
4956// / It can deliver a log entry to one or more different sinks, for example a
@@ -136,6 +143,38 @@ class log_channel
136143 backend.push (std::move (entry));
137144 }
138145
146+ // / Builds the provided log entry and passes it to the backend. When the
147+ // / channel is disabled the log entry will be discarded.
148+ template <typename ... Args>
149+ void operator ()(const log_label_t & label, const char * fmtstr, Args&&... args)
150+ {
151+ if (!enabled ()) {
152+ return ;
153+ }
154+
155+ // Populate the store with all incoming arguments.
156+ auto * store = backend.alloc_arg_store ();
157+ if (!store) {
158+ return ;
159+ }
160+ (void )std::initializer_list<int >{(push_back (store, std::forward<Args>(args)), 0 )...};
161+
162+ // Send the log entry to the backend.
163+ log_formatter& formatter = log_sink.get_formatter ();
164+ detail::log_entry entry = {&log_sink,
165+ [&formatter](detail::log_entry_metadata&& metadata, fmt::memory_buffer& buffer) {
166+ formatter.format (std::move (metadata), buffer);
167+ },
168+ {std::chrono::high_resolution_clock::now (),
169+ {ctx_value64, should_print_context},
170+ fmtstr,
171+ store,
172+ log_name,
173+ log_tag,
174+ label.log_label }};
175+ backend.push (std::move (entry));
176+ }
177+
139178 // / Builds the provided log entry and passes it to the backend. When the
140179 // / channel is disabled the log entry will be discarded.
141180 template <typename ... Args>
@@ -200,6 +239,45 @@ class log_channel
200239 store,
201240 log_name,
202241 log_tag,
242+ {},
243+ std::vector<uint8_t >(buffer, buffer + len)}};
244+ backend.push (std::move (entry));
245+ }
246+
247+ // / Builds the provided log entry and passes it to the backend. When the
248+ // / channel is disabled the log entry will be discarded.
249+ template <typename ... Args>
250+ void operator ()(const log_label_t & label, const uint8_t * buffer, size_t len, const char * fmtstr, Args&&... args)
251+ {
252+ if (!enabled ()) {
253+ return ;
254+ }
255+
256+ // Populate the store with all incoming arguments.
257+ auto * store = backend.alloc_arg_store ();
258+ if (!store) {
259+ return ;
260+ }
261+ (void )std::initializer_list<int >{(push_back (store, std::forward<Args>(args)), 0 )...};
262+
263+ // Calculate the length to capture in the buffer.
264+ if (hex_max_size >= 0 ) {
265+ len = std::min<size_t >(len, hex_max_size);
266+ }
267+
268+ // Send the log entry to the backend.
269+ log_formatter& formatter = log_sink.get_formatter ();
270+ detail::log_entry entry = {&log_sink,
271+ [&formatter](detail::log_entry_metadata&& metadata, fmt::memory_buffer& buffer_) {
272+ formatter.format (std::move (metadata), buffer_);
273+ },
274+ {std::chrono::high_resolution_clock::now (),
275+ {ctx_value64, should_print_context},
276+ fmtstr,
277+ store,
278+ log_name,
279+ log_tag,
280+ label.log_label ,
203281 std::vector<uint8_t >(buffer, buffer + len)}};
204282 backend.push (std::move (entry));
205283 }
@@ -237,6 +315,7 @@ class log_channel
237315 store,
238316 log_name,
239317 log_tag,
318+ {},
240319 std::vector<uint8_t >(buffer, buffer + len)}};
241320 backend.push (std::move (entry));
242321 }
@@ -274,6 +353,45 @@ class log_channel
274353 store,
275354 log_name,
276355 log_tag,
356+ {},
357+ std::vector<uint8_t >(it_begin, it_end)}};
358+ backend.push (std::move (entry));
359+ }
360+
361+ // / Builds the provided log entry and passes it to the backend. When the
362+ // / channel is disabled the log entry will be discarded.
363+ template <typename It, typename ... Args, typename std::enable_if<detail::is_byte_iterable<It>::value, int >::type = 0 >
364+ void operator ()(const log_label_t & label, It it_begin, It it_end, const char * fmtstr, Args&&... args)
365+ {
366+ if (!enabled ()) {
367+ return ;
368+ }
369+
370+ // Populate the store with all incoming arguments.
371+ auto * store = backend.alloc_arg_store ();
372+ if (!store) {
373+ return ;
374+ }
375+ (void )std::initializer_list<int >{(push_back (store, std::forward<Args>(args)), 0 )...};
376+
377+ // Calculate the length to capture in the buffer.
378+ if (hex_max_size >= 0 && hex_max_size < std::distance (it_begin, it_end)) {
379+ it_end = it_begin + hex_max_size;
380+ }
381+
382+ // Send the log entry to the backend.
383+ log_formatter& formatter = log_sink.get_formatter ();
384+ detail::log_entry entry = {&log_sink,
385+ [&formatter](detail::log_entry_metadata&& metadata, fmt::memory_buffer& buffer) {
386+ formatter.format (std::move (metadata), buffer);
387+ },
388+ {std::chrono::high_resolution_clock::now (),
389+ {ctx_value64, should_print_context},
390+ fmtstr,
391+ store,
392+ log_name,
393+ log_tag,
394+ label.log_label ,
277395 std::vector<uint8_t >(it_begin, it_end)}};
278396 backend.push (std::move (entry));
279397 }
0 commit comments