ESPHome 2025.12.5
Loading...
Searching...
No Matches
logger.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdarg>
4#include <map>
5#ifdef USE_ESP32
6#include <pthread.h>
7#endif
12#include "esphome/core/log.h"
13
14#ifdef USE_ESPHOME_TASK_LOG_BUFFER
15#include "task_log_buffer.h"
16#endif
17
18#ifdef USE_ARDUINO
19#if defined(USE_ESP8266)
20#include <HardwareSerial.h>
21#endif // USE_ESP8266
22#ifdef USE_RP2040
23#include <HardwareSerial.h>
24#include <SerialUSB.h>
25#endif // USE_RP2040
26#endif // USE_ARDUINO
27
28#ifdef USE_ESP32
29#include <driver/uart.h>
30#endif // USE_ESP32
31
32#ifdef USE_ZEPHYR
33#include <zephyr/kernel.h>
34struct device;
35#endif
36
37namespace esphome::logger {
38
57 public:
58 virtual void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) = 0;
59};
60
61#ifdef USE_LOGGER_LEVEL_LISTENERS
80 public:
81 virtual void on_log_level_change(uint8_t level) = 0;
82};
83#endif
84
85#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
86// Comparison function for const char* keys in log_levels_ map
88 bool operator()(const char *a, const char *b) const { return strcmp(a, b) < 0; }
89};
90#endif
91
92// ANSI color code last digit (30-38 range, store only last digit to save RAM)
93static constexpr char LOG_LEVEL_COLOR_DIGIT[] = {
94 '\0', // NONE
95 '1', // ERROR (31 = red)
96 '3', // WARNING (33 = yellow)
97 '2', // INFO (32 = green)
98 '5', // CONFIG (35 = magenta)
99 '6', // DEBUG (36 = cyan)
100 '7', // VERBOSE (37 = gray)
101 '8', // VERY_VERBOSE (38 = white)
102};
103
104static constexpr char LOG_LEVEL_LETTER_CHARS[] = {
105 '\0', // NONE
106 'E', // ERROR
107 'W', // WARNING
108 'I', // INFO
109 'C', // CONFIG
110 'D', // DEBUG
111 'V', // VERBOSE (VERY_VERBOSE uses two 'V's)
112};
113
114// Maximum header size: 35 bytes fixed + 32 bytes tag + 16 bytes thread name = 83 bytes (45 byte safety margin)
115static constexpr uint16_t MAX_HEADER_SIZE = 128;
116
117// "0x" + 2 hex digits per byte + '\0'
118static constexpr size_t MAX_POINTER_REPRESENTATION = 2 + sizeof(void *) * 2 + 1;
119
120// Platform-specific: does write_msg_ add its own newline?
121// false: Caller must add newline to buffer before calling write_msg_ (ESP32, ESP8266, LibreTiny)
122// Allows single write call with newline included for efficiency
123// true: write_msg_ adds newline itself via puts()/println() (other platforms)
124// Newline should NOT be added to buffer
125#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_LIBRETINY)
126static constexpr bool WRITE_MSG_ADDS_NEWLINE = false;
127#else
128static constexpr bool WRITE_MSG_ADDS_NEWLINE = true;
129#endif
130
131#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
136enum UARTSelection : uint8_t {
137#ifdef USE_LIBRETINY
140#else
142#endif
144#if defined(USE_LIBRETINY) || defined(USE_ESP32_VARIANT_ESP32)
146#endif
147#ifdef USE_LOGGER_USB_CDC
149#endif
150#ifdef USE_LOGGER_USB_SERIAL_JTAG
152#endif
153#ifdef USE_ESP8266
155#endif // USE_ESP8266
156};
157#endif // USE_ESP32 || USE_ESP8266 || USE_RP2040 || USE_LIBRETINY || USE_ZEPHYR
158
176class Logger : public Component {
177 public:
178 explicit Logger(uint32_t baud_rate, size_t tx_buffer_size);
179#ifdef USE_ESPHOME_TASK_LOG_BUFFER
180 void init_log_buffer(size_t total_buffer_size);
181#endif
182#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC))
183 void loop() override;
184#endif
186 void set_baud_rate(uint32_t baud_rate);
187 uint32_t get_baud_rate() const { return baud_rate_; }
188#if defined(USE_ARDUINO) && !defined(USE_ESP32)
189 Stream *get_hw_serial() const { return hw_serial_; }
190#endif
191#ifdef USE_ESP32
192 uart_port_t get_uart_num() const { return uart_num_; }
193 void create_pthread_key() { pthread_key_create(&log_recursion_key_, nullptr); }
194#endif
195#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
196 void set_uart_selection(UARTSelection uart_selection) { uart_ = uart_selection; }
198 UARTSelection get_uart() const;
199#endif
200
202 void set_log_level(uint8_t level);
203#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
205 void set_log_level(const char *tag, uint8_t log_level);
206#endif
207 uint8_t get_log_level() { return this->current_level_; }
208
209 // ========== INTERNAL METHODS ==========
210 // (In most use cases you won't need these)
212 void pre_setup();
213 void dump_config() override;
214
215 inline uint8_t level_for(const char *tag);
216
218 void add_log_listener(LogListener *listener) { this->log_listeners_.push_back(listener); }
219
220#ifdef USE_LOGGER_LEVEL_LISTENERS
222 void add_level_listener(LoggerLevelListener *listener) { this->level_listeners_.push_back(listener); }
223#endif
224
225 float get_setup_priority() const override;
226
227 void log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args); // NOLINT
228#ifdef USE_STORE_LOG_STR_IN_FLASH
229 void log_vprintf_(uint8_t level, const char *tag, int line, const __FlashStringHelper *format,
230 va_list args); // NOLINT
231#endif
232
233 protected:
234 void process_messages_();
235 void write_msg_(const char *msg, size_t len);
236
237 // Format a log message with printf-style arguments and write it to a buffer with header, footer, and null terminator
238 // It's the caller's responsibility to initialize buffer_at (typically to 0)
239 inline void HOT format_log_to_buffer_with_terminator_(uint8_t level, const char *tag, int line, const char *format,
240 va_list args, char *buffer, uint16_t *buffer_at,
241 uint16_t buffer_size) {
242#if defined(USE_ESP32) || defined(USE_LIBRETINY)
243 this->write_header_to_buffer_(level, tag, line, this->get_thread_name_(), buffer, buffer_at, buffer_size);
244#elif defined(USE_ZEPHYR)
245 char buff[MAX_POINTER_REPRESENTATION];
246 this->write_header_to_buffer_(level, tag, line, this->get_thread_name_(buff), buffer, buffer_at, buffer_size);
247#else
248 this->write_header_to_buffer_(level, tag, line, nullptr, buffer, buffer_at, buffer_size);
249#endif
250 this->format_body_to_buffer_(buffer, buffer_at, buffer_size, format, args);
251 this->write_footer_to_buffer_(buffer, buffer_at, buffer_size);
252
253 // Always ensure the buffer has a null terminator, even if we need to
254 // overwrite the last character of the actual content
255 if (*buffer_at >= buffer_size) {
256 buffer[buffer_size - 1] = '\0'; // Truncate and ensure null termination
257 } else {
258 buffer[*buffer_at] = '\0'; // Normal case, append null terminator
259 }
260 }
261
262 // Helper to add newline to buffer for platforms that need it
263 // Modifies buffer_at to include the newline
264 inline void HOT add_newline_to_buffer_if_needed_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size) {
265 if constexpr (!WRITE_MSG_ADDS_NEWLINE) {
266 // Add newline - don't need to maintain null termination
267 // write_msg_ now always receives explicit length, so we can safely overwrite the null terminator
268 // This is safe because:
269 // 1. Callbacks already received the message (before we add newline)
270 // 2. write_msg_ receives the length explicitly (doesn't need null terminator)
271 if (*buffer_at < buffer_size) {
272 buffer[(*buffer_at)++] = '\n';
273 } else if (buffer_size > 0) {
274 // Buffer was full - replace last char with newline to ensure it's visible
275 buffer[buffer_size - 1] = '\n';
276 *buffer_at = buffer_size;
277 }
278 }
279 }
280
281 // Helper to write tx_buffer_ to console if logging is enabled
282 // INTERNAL USE ONLY - offset > 0 requires length parameter to be non-null
283 inline void HOT write_tx_buffer_to_console_(uint16_t offset = 0, uint16_t *length = nullptr) {
284 if (this->baud_rate_ > 0) {
285 uint16_t *len_ptr = length ? length : &this->tx_buffer_at_;
286 this->add_newline_to_buffer_if_needed_(this->tx_buffer_ + offset, len_ptr, this->tx_buffer_size_ - offset);
287 this->write_msg_(this->tx_buffer_ + offset, *len_ptr);
288 }
289 }
290
291 // Helper to format and send a log message to both console and listeners
292 inline void HOT log_message_to_buffer_and_send_(uint8_t level, const char *tag, int line, const char *format,
293 va_list args) {
294 // Format to tx_buffer and prepare for output
295 this->tx_buffer_at_ = 0; // Initialize buffer position
296 this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, this->tx_buffer_, &this->tx_buffer_at_,
297 this->tx_buffer_size_);
298
299 // Listeners get message WITHOUT newline (for API/MQTT/syslog)
300 for (auto *listener : this->log_listeners_)
301 listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_);
302
303 // Console gets message WITH newline (if platform needs it)
305 }
306
307 // Write the body of the log message to the buffer
308 inline void write_body_to_buffer_(const char *value, size_t length, char *buffer, uint16_t *buffer_at,
309 uint16_t buffer_size) {
310 // Calculate available space
311 if (*buffer_at >= buffer_size)
312 return;
313 const uint16_t available = buffer_size - *buffer_at;
314
315 // Determine copy length (minimum of remaining capacity and string length)
316 const size_t copy_len = (length < static_cast<size_t>(available)) ? length : available;
317
318 // Copy the data
319 if (copy_len > 0) {
320 memcpy(buffer + *buffer_at, value, copy_len);
321 *buffer_at += copy_len;
322 }
323 }
324
325#ifndef USE_HOST
326 const LogString *get_uart_selection_();
327#endif
328
329 // Group 4-byte aligned members first
330 uint32_t baud_rate_;
331 char *tx_buffer_{nullptr};
332#if defined(USE_ARDUINO) && !defined(USE_ESP32)
333 Stream *hw_serial_{nullptr};
334#endif
335#if defined(USE_ZEPHYR)
336 const device *uart_dev_{nullptr};
337#endif
338#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
339 void *main_task_ = nullptr; // Only used for thread name identification
340#endif
341#ifdef USE_ESP32
342 // Task-specific recursion guards:
343 // - Main task uses a dedicated member variable for efficiency
344 // - Other tasks use pthread TLS with a dynamically created key via pthread_key_create
345 pthread_key_t log_recursion_key_; // 4 bytes
346 uart_port_t uart_num_; // 4 bytes (enum defaults to int size)
347#endif
348
349 // Large objects (internally aligned)
350#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
351 std::map<const char *, uint8_t, CStrCompare> log_levels_{};
352#endif
353 std::vector<LogListener *> log_listeners_; // Log message listeners (API, MQTT, syslog, etc.)
354#ifdef USE_LOGGER_LEVEL_LISTENERS
355 std::vector<LoggerLevelListener *> level_listeners_; // Log level change listeners
356#endif
357#ifdef USE_ESPHOME_TASK_LOG_BUFFER
358 std::unique_ptr<logger::TaskLogBuffer> log_buffer_; // Will be initialized with init_log_buffer
359#endif
360
361 // Group smaller types together at the end
362 uint16_t tx_buffer_at_{0};
363 uint16_t tx_buffer_size_{0};
364 uint8_t current_level_{ESPHOME_LOG_LEVEL_VERY_VERBOSE};
365#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_ZEPHYR)
367#endif
368#ifdef USE_LIBRETINY
370#endif
371#ifdef USE_ESP32
373#else
374 bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms
375#endif
376
377#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
378 const char *HOT get_thread_name_(
379#ifdef USE_ZEPHYR
380 char *buff
381#endif
382 ) {
383#ifdef USE_ZEPHYR
384 k_tid_t current_task = k_current_get();
385#else
386 TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
387#endif
388 if (current_task == main_task_) {
389 return nullptr; // Main task
390 } else {
391#if defined(USE_ESP32)
392 return pcTaskGetName(current_task);
393#elif defined(USE_LIBRETINY)
394 return pcTaskGetTaskName(current_task);
395#elif defined(USE_ZEPHYR)
396 const char *name = k_thread_name_get(current_task);
397 if (name) {
398 // zephyr print task names only if debug component is present
399 return name;
400 }
401 std::snprintf(buff, MAX_POINTER_REPRESENTATION, "%p", current_task);
402 return buff;
403#endif
404 }
405 }
406#endif
407
408#ifdef USE_ESP32
409 inline bool HOT check_and_set_task_log_recursion_(bool is_main_task) {
410 if (is_main_task) {
411 const bool was_recursive = main_task_recursion_guard_;
413 return was_recursive;
414 }
415
416 intptr_t current = (intptr_t) pthread_getspecific(log_recursion_key_);
417 if (current != 0)
418 return true;
419
420 pthread_setspecific(log_recursion_key_, (void *) 1);
421 return false;
422 }
423
424 inline void HOT reset_task_log_recursion_(bool is_main_task) {
425 if (is_main_task) {
427 return;
428 }
429
430 pthread_setspecific(log_recursion_key_, (void *) 0);
431 }
432#endif
433
434 static inline void copy_string(char *buffer, uint16_t &pos, const char *str) {
435 const size_t len = strlen(str);
436 // Intentionally no null terminator, building larger string
437 memcpy(buffer + pos, str, len); // NOLINT(bugprone-not-null-terminated-result)
438 pos += len;
439 }
440
441 static inline void write_ansi_color_for_level(char *buffer, uint16_t &pos, uint8_t level) {
442 if (level == 0)
443 return;
444 // Construct ANSI escape sequence: "\033[{bold};3{color}m"
445 // Example: "\033[1;31m" for ERROR (bold red)
446 buffer[pos++] = '\033';
447 buffer[pos++] = '[';
448 buffer[pos++] = (level == 1) ? '1' : '0'; // Only ERROR is bold
449 buffer[pos++] = ';';
450 buffer[pos++] = '3';
451 buffer[pos++] = LOG_LEVEL_COLOR_DIGIT[level];
452 buffer[pos++] = 'm';
453 }
454
455 inline void HOT write_header_to_buffer_(uint8_t level, const char *tag, int line, const char *thread_name,
456 char *buffer, uint16_t *buffer_at, uint16_t buffer_size) {
457 uint16_t pos = *buffer_at;
458 // Early return if insufficient space - intentionally don't update buffer_at to prevent partial writes
459 if (pos + MAX_HEADER_SIZE > buffer_size)
460 return;
461
462 // Construct: <color>[LEVEL][tag:line]:
463 write_ansi_color_for_level(buffer, pos, level);
464 buffer[pos++] = '[';
465 if (level != 0) {
466 if (level >= 7) {
467 buffer[pos++] = 'V'; // VERY_VERBOSE = "VV"
468 buffer[pos++] = 'V';
469 } else {
470 buffer[pos++] = LOG_LEVEL_LETTER_CHARS[level];
471 }
472 }
473 buffer[pos++] = ']';
474 buffer[pos++] = '[';
475 copy_string(buffer, pos, tag);
476 buffer[pos++] = ':';
477 // Format line number without modulo operations (passed by value, safe to mutate)
478 if (line > 999) [[unlikely]] {
479 int thousands = line / 1000;
480 buffer[pos++] = '0' + thousands;
481 line -= thousands * 1000;
482 }
483 int hundreds = line / 100;
484 int remainder = line - hundreds * 100;
485 int tens = remainder / 10;
486 buffer[pos++] = '0' + hundreds;
487 buffer[pos++] = '0' + tens;
488 buffer[pos++] = '0' + (remainder - tens * 10);
489 buffer[pos++] = ']';
490
491#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
492 if (thread_name != nullptr) {
493 write_ansi_color_for_level(buffer, pos, 1); // Always use bold red for thread name
494 buffer[pos++] = '[';
495 copy_string(buffer, pos, thread_name);
496 buffer[pos++] = ']';
497 write_ansi_color_for_level(buffer, pos, level); // Restore original color
498 }
499#endif
500
501 buffer[pos++] = ':';
502 buffer[pos++] = ' ';
503 *buffer_at = pos;
504 }
505
506 inline void HOT format_body_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size, const char *format,
507 va_list args) {
508 // Get remaining capacity in the buffer
509 if (*buffer_at >= buffer_size)
510 return;
511 const uint16_t remaining = buffer_size - *buffer_at;
512
513 const int ret = vsnprintf(buffer + *buffer_at, remaining, format, args);
514
515 if (ret < 0) {
516 return; // Encoding error, do not increment buffer_at
517 }
518
519 // Update buffer_at with the formatted length (handle truncation)
520 // When vsnprintf truncates (ret >= remaining), it writes (remaining - 1) chars + null terminator
521 // When it doesn't truncate (ret < remaining), it writes ret chars + null terminator
522 uint16_t formatted_len = (ret >= remaining) ? (remaining - 1) : ret;
523 *buffer_at += formatted_len;
524
525 // Remove all trailing newlines right after formatting
526 while (*buffer_at > 0 && buffer[*buffer_at - 1] == '\n') {
527 (*buffer_at)--;
528 }
529 }
530
531 inline void HOT write_footer_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size) {
532 static constexpr uint16_t RESET_COLOR_LEN = sizeof(ESPHOME_LOG_RESET_COLOR) - 1;
533 this->write_body_to_buffer_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN, buffer, buffer_at, buffer_size);
534 }
535
536#ifdef USE_ESP32
537 // Disable loop when task buffer is empty (with USB CDC check)
539 // Thread safety note: This is safe even if another task calls enable_loop_soon_any_context()
540 // concurrently. If that happens between our check and disable_loop(), the enable request
541 // will be processed on the next main loop iteration since:
542 // - disable_loop() takes effect immediately
543 // - enable_loop_soon_any_context() sets a pending flag that's checked at loop start
544 this->disable_loop();
545 }
546#endif
547};
548extern Logger *global_logger; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
549
550class LoggerMessageTrigger : public Trigger<uint8_t, const char *, const char *>, public LogListener {
551 public:
552 explicit LoggerMessageTrigger(Logger *parent, uint8_t level) : level_(level) { parent->add_log_listener(this); }
553
554 void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override {
555 (void) message_len;
556 if (level <= this->level_) {
557 this->trigger(level, tag, message);
558 }
559 }
560
561 protected:
562 uint8_t level_;
563};
564
565} // namespace esphome::logger
void disable_loop()
Disable this component's loop.
Interface for receiving log messages without std::function overhead.
Definition logger.h:56
virtual void on_log(uint8_t level, const char *tag, const char *message, size_t message_len)=0
Logger component for all ESPHome logging.
Definition logger.h:176
std::vector< LogListener * > log_listeners_
Definition logger.h:353
void add_level_listener(LoggerLevelListener *listener)
Register a listener for log level changes.
Definition logger.h:222
UARTSelection uart_
Definition logger.h:366
void add_log_listener(LogListener *listener)
Register a log listener to receive log messages.
Definition logger.h:218
void HOT format_log_to_buffer_with_terminator_(uint8_t level, const char *tag, int line, const char *format, va_list args, char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
Definition logger.h:239
void HOT log_message_to_buffer_and_send_(uint8_t level, const char *tag, int line, const char *format, va_list args)
Definition logger.h:292
void dump_config() override
Definition logger.cpp:260
void HOT format_body_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size, const char *format, va_list args)
Definition logger.h:506
uint32_t get_baud_rate() const
Definition logger.h:187
const LogString * get_uart_selection_()
uint8_t level_for(const char *tag)
Definition logger.cpp:154
bool HOT check_and_set_task_log_recursion_(bool is_main_task)
Definition logger.h:409
void loop() override
Definition logger.cpp:183
uint8_t get_log_level()
Definition logger.h:207
Stream * get_hw_serial() const
Definition logger.h:189
void log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args)
Definition logger.cpp:26
void pre_setup()
Set up this component.
const char *HOT get_thread_name_(#ifdef USE_ZEPHYR char *buff #endif)
Definition logger.h:378
void HOT write_footer_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
Definition logger.h:531
float get_setup_priority() const override
Definition logger.cpp:236
std::map< const char *, uint8_t, CStrCompare > log_levels_
Definition logger.h:351
UARTSelection get_uart() const
Get the UART used by the logger.
Definition logger.cpp:233
std::vector< LoggerLevelListener * > level_listeners_
Definition logger.h:355
void write_msg_(const char *msg, size_t len)
void disable_loop_when_buffer_empty_()
Definition logger.h:538
uart_port_t uart_num_
Definition logger.h:346
std::unique_ptr< logger::TaskLogBuffer > log_buffer_
Definition logger.h:358
static void copy_string(char *buffer, uint16_t &pos, const char *str)
Definition logger.h:434
pthread_key_t log_recursion_key_
Definition logger.h:345
uart_port_t get_uart_num() const
Definition logger.h:192
void init_log_buffer(size_t total_buffer_size)
Definition logger.cpp:173
void HOT write_tx_buffer_to_console_(uint16_t offset=0, uint16_t *length=nullptr)
Definition logger.h:283
void set_log_level(uint8_t level)
Set the default log level for this logger.
Definition logger.cpp:285
void set_baud_rate(uint32_t baud_rate)
Manually set the baud rate for serial, set to 0 to disable.
Definition logger.cpp:227
void set_uart_selection(UARTSelection uart_selection)
Definition logger.h:196
static void write_ansi_color_for_level(char *buffer, uint16_t &pos, uint8_t level)
Definition logger.h:441
Logger(uint32_t baud_rate, size_t tx_buffer_size)
Definition logger.cpp:163
void HOT reset_task_log_recursion_(bool is_main_task)
Definition logger.h:424
void write_body_to_buffer_(const char *value, size_t length, char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
Definition logger.h:308
void HOT write_header_to_buffer_(uint8_t level, const char *tag, int line, const char *thread_name, char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
Definition logger.h:455
bool main_task_recursion_guard_
Definition logger.h:372
const device * uart_dev_
Definition logger.h:336
uint16_t tx_buffer_size_
Definition logger.h:363
void HOT add_newline_to_buffer_if_needed_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
Definition logger.h:264
Interface for receiving log level changes without std::function overhead.
Definition logger.h:79
virtual void on_log_level_change(uint8_t level)=0
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override
Definition logger.h:554
LoggerMessageTrigger(Logger *parent, uint8_t level)
Definition logger.h:552
const char * message
Definition component.cpp:38
UARTSelection
Enum for logging UART selection.
Definition logger.h:136
@ UART_SELECTION_UART0_SWAP
Definition logger.h:154
@ UART_SELECTION_UART2
Definition logger.h:145
@ UART_SELECTION_USB_SERIAL_JTAG
Definition logger.h:151
@ UART_SELECTION_DEFAULT
Definition logger.h:138
@ UART_SELECTION_USB_CDC
Definition logger.h:148
@ UART_SELECTION_UART0
Definition logger.h:139
@ UART_SELECTION_UART1
Definition logger.h:143
Logger * global_logger
Definition logger.cpp:297
std::string size_t len
Definition helpers.h:503
bool operator()(const char *a, const char *b) const
Definition logger.h:88
uint16_t length
Definition tt21100.cpp:0