3#ifdef USE_ESPHOME_TASK_LOG_BUFFER
13static const char *
const TAG =
"logger";
15#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_LIBRETINY)
28void HOT
Logger::log_vprintf_(uint8_t level,
const char *tag,
int line,
const char *format, va_list args) {
32#if defined(USE_ESP32) || defined(USE_LIBRETINY)
34 TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
35 const bool is_main_task = (current_task == this->
main_task_);
37 const bool is_main_task = pthread_equal(pthread_self(), this->
main_thread_);
54#if defined(USE_ESP32) || defined(USE_LIBRETINY)
63#if defined(USE_ESP32) || defined(USE_LIBRETINY)
65 TaskHandle_t current_task) {
77 bool message_sent =
false;
78#ifdef USE_ESPHOME_TASK_LOG_BUFFER
80#if defined(USE_ESP32) || defined(USE_LIBRETINY)
82 this->
log_buffer_->send_message_thread_safe(level, tag,
static_cast<uint16_t
>(line), current_task, format, args);
84 message_sent = this->
log_buffer_->send_message_thread_safe(level, tag,
static_cast<uint16_t
>(line), format, args);
100 static const size_t MAX_CONSOLE_LOG_MSG_SIZE = 512;
104 static const size_t MAX_CONSOLE_LOG_MSG_SIZE = 144;
106 char console_buffer[MAX_CONSOLE_LOG_MSG_SIZE];
107 uint16_t buffer_at = 0;
109 MAX_CONSOLE_LOG_MSG_SIZE);
119void HOT
Logger::log_vprintf_(uint8_t level,
const char *tag,
int line,
const char *format, va_list args) {
129#ifdef USE_STORE_LOG_STR_IN_FLASH
151void Logger::log_vprintf_(uint8_t level,
const char *tag,
int line,
const __FlashStringHelper *format,
160 auto *format_pgm_p =
reinterpret_cast<const uint8_t *
>(format);
177 uint16_t msg_length =
181#ifdef USE_LOG_LISTENERS
183 listener->on_log(level, tag, this->
tx_buffer_ + msg_start, msg_length);
192#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
202 this->tx_buffer_ =
new char[this->tx_buffer_size_ + 1];
203#if defined(USE_ESP32) || defined(USE_LIBRETINY)
204 this->main_task_ = xTaskGetCurrentTaskHandle();
205#elif defined(USE_ZEPHYR)
206 this->main_task_ = k_current_get();
207#elif defined(USE_HOST)
208 this->main_thread_ = pthread_self();
211#ifdef USE_ESPHOME_TASK_LOG_BUFFER
212void Logger::init_log_buffer(
size_t total_buffer_size) {
215 this->log_buffer_ = esphome::make_unique<logger::TaskLogBufferHost>(total_buffer_size);
216#elif defined(USE_ESP32)
217 this->log_buffer_ = esphome::make_unique<logger::TaskLogBuffer>(total_buffer_size);
218#elif defined(USE_LIBRETINY)
219 this->log_buffer_ = esphome::make_unique<logger::TaskLogBufferLibreTiny>(total_buffer_size);
222#if defined(USE_ESP32) || defined(USE_LIBRETINY)
225 this->disable_loop_when_buffer_empty_();
230#ifdef USE_ESPHOME_TASK_LOG_BUFFER
231void Logger::loop() { this->process_messages_(); }
234void Logger::process_messages_() {
235#ifdef USE_ESPHOME_TASK_LOG_BUFFER
237 if (this->log_buffer_->has_messages()) {
239 logger::TaskLogBufferHost::LogMessage *
message;
240 while (this->log_buffer_->get_message_main_loop(&
message)) {
241 const char *thread_name =
message->thread_name[0] !=
'\0' ?
message->thread_name :
nullptr;
244 this->log_buffer_->release_message_main_loop();
245 this->write_tx_buffer_to_console_();
247#elif defined(USE_ESP32)
248 logger::TaskLogBuffer::LogMessage *
message;
250 void *received_token;
251 while (this->log_buffer_->borrow_message_main_loop(&
message, &text, &received_token)) {
252 const char *thread_name =
message->thread_name[0] !=
'\0' ?
message->thread_name :
nullptr;
253 this->format_buffered_message_and_notify_(
message->level,
message->tag,
message->line, thread_name, text,
256 this->log_buffer_->release_message_main_loop(received_token);
257 this->write_tx_buffer_to_console_();
259#elif defined(USE_LIBRETINY)
260 logger::TaskLogBufferLibreTiny::LogMessage *
message;
262 while (this->log_buffer_->borrow_message_main_loop(&
message, &text)) {
263 const char *thread_name =
message->thread_name[0] !=
'\0' ?
message->thread_name :
nullptr;
264 this->format_buffered_message_and_notify_(
message->level,
message->tag,
message->line, thread_name, text,
267 this->log_buffer_->release_message_main_loop();
268 this->write_tx_buffer_to_console_();
272#if defined(USE_ESP32) || defined(USE_LIBRETINY)
276 this->disable_loop_when_buffer_empty_();
282void Logger::set_baud_rate(uint32_t baud_rate) { this->baud_rate_ = baud_rate; }
283#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
284void Logger::set_log_level(
const char *tag, uint8_t log_level) { this->log_levels_[tag] = log_level; }
287#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
288UARTSelection Logger::get_uart()
const {
return this->uart_; }
291float Logger::get_setup_priority()
const {
return setup_priority::BUS + 500.0f; }
293#ifdef USE_STORE_LOG_STR_IN_FLASH
305static const LogString *
const LOG_LEVELS[] = {
306 reinterpret_cast<const LogString *
>(
LOG_LEVEL_NONE),
reinterpret_cast<const LogString *
>(LOG_LEVEL_ERROR),
307 reinterpret_cast<const LogString *
>(
LOG_LEVEL_WARN),
reinterpret_cast<const LogString *
>(LOG_LEVEL_INFO),
308 reinterpret_cast<const LogString *
>(
LOG_LEVEL_CONFIG),
reinterpret_cast<const LogString *
>(LOG_LEVEL_DEBUG),
309 reinterpret_cast<const LogString *
>(
LOG_LEVEL_VERBOSE),
reinterpret_cast<const LogString *
>(LOG_LEVEL_VERY_VERBOSE),
312static const char *
const LOG_LEVELS[] = {
"NONE",
"ERROR",
"WARN",
"INFO",
"CONFIG",
"DEBUG",
"VERBOSE",
"VERY_VERBOSE"};
315void Logger::dump_config() {
319 " Initial Level: %s",
320 LOG_STR_ARG(LOG_LEVELS[ESPHOME_LOG_LEVEL]), LOG_STR_ARG(LOG_LEVELS[this->current_level_]));
323 " Log Baud Rate: %" PRIu32
"\n"
324 " Hardware UART: %s",
325 this->baud_rate_, LOG_STR_ARG(get_uart_selection_()));
327#ifdef USE_ESPHOME_TASK_LOG_BUFFER
328 if (this->log_buffer_) {
330 ESP_LOGCONFIG(TAG,
" Task Log Buffer Slots: %u",
static_cast<unsigned int>(this->log_buffer_->size()));
332 ESP_LOGCONFIG(TAG,
" Task Log Buffer Size: %u bytes",
static_cast<unsigned int>(this->log_buffer_->size()));
337#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
338 for (
auto &it : this->log_levels_) {
339 ESP_LOGCONFIG(TAG,
" Level for '%s': %s", it.first, LOG_STR_ARG(LOG_LEVELS[it.second]));
344void Logger::set_log_level(uint8_t level) {
345 if (level > ESPHOME_LOG_LEVEL) {
346 level = ESPHOME_LOG_LEVEL;
347 ESP_LOGW(TAG,
"Cannot set log level higher than pre-compiled %s", LOG_STR_ARG(LOG_LEVELS[ESPHOME_LOG_LEVEL]));
349 this->current_level_ = level;
350#ifdef USE_LOGGER_LEVEL_LISTENERS
351 for (
auto *listener : this->level_listeners_)
352 listener->on_log_level_change(level);
void enable_loop_soon_any_context()
Thread and ISR-safe version of enable_loop() that can be called from any context.
void log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args)
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)
void HOT log_message_to_buffer_and_send_(uint8_t level, const char *tag, int line, const char *format, va_list args)
bool HOT is_non_main_task_recursive_() const
NonMainTaskRecursionGuard make_non_main_task_guard_()
uint8_t level_for(const char *tag)
StaticVector< LogListener *, ESPHOME_LOG_MAX_LISTENERS > log_listeners_
void HOT add_newline_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
std::map< const char *, uint8_t, CStrCompare > log_levels_
void write_msg_(const char *msg, size_t len)
void HOT write_tx_buffer_to_console_(uint16_t offset=0, uint16_t *length=nullptr)
void log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args, TaskHandle_t current_task)
bool global_recursion_guard_
Logger(uint32_t baud_rate, size_t tx_buffer_size)
std::unique_ptr< logger::TaskLogBufferHost > log_buffer_
bool main_task_recursion_guard_
UARTSelection
Enum for logging UART selection.
uint8_t progmem_read_byte(const uint8_t *addr)
const uint8_t ESPHOME_WEBSERVER_INDEX_HTML[] PROGMEM