diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index c24cc19e7b..cadd0a14ae 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -578,6 +578,8 @@ async def final_step(): if domain_data.get(KEY_LEVEL_LISTENERS, False): cg.add_define("USE_LOGGER_LEVEL_LISTENERS") - # Set exact count of log listeners - runtime will silently drop listeners if exceeded + # Only generate log listener code if any component needs it log_listener_count = domain_data.get(KEY_LOG_LISTENERS, 0) - cg.add_define("ESPHOME_LOG_MAX_LISTENERS", log_listener_count) + if log_listener_count > 0: + cg.add_define("USE_LOG_LISTENERS") + cg.add_define("ESPHOME_LOG_MAX_LISTENERS", log_listener_count) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 1b41bc3d47..fb9a33e612 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -156,8 +156,10 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas this->tx_buffer_at_ - msg_start; // Don't subtract 1 - tx_buffer_at_ is already at the null terminator position // Listeners get message first (before console write) +#ifdef USE_LOG_LISTENERS for (auto *listener : this->log_listeners_) listener->on_log(level, tag, this->tx_buffer_ + msg_start, msg_length); +#endif // Write to console starting at the msg_start this->write_tx_buffer_to_console_(msg_start, &msg_length); diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index ea63f9e07c..c8491c5967 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -212,8 +212,13 @@ class Logger : public Component { inline uint8_t level_for(const char *tag); +#ifdef USE_LOG_LISTENERS /// Register a log listener to receive log messages void add_log_listener(LogListener *listener) { this->log_listeners_.push_back(listener); } +#else + /// No-op when log listeners are disabled + void add_log_listener(LogListener *listener) {} +#endif #ifdef USE_LOGGER_LEVEL_LISTENERS /// Register a listener for log level changes @@ -293,8 +298,10 @@ class Logger : public Component { this->tx_buffer_size_); // Listeners get message WITHOUT newline (for API/MQTT/syslog) +#ifdef USE_LOG_LISTENERS for (auto *listener : this->log_listeners_) listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_); +#endif // Console gets message WITH newline (if platform needs it) this->write_tx_buffer_to_console_(); @@ -311,8 +318,10 @@ class Logger : public Component { this->write_body_to_buffer_(text, text_length, this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_); this->write_footer_to_buffer_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_); this->tx_buffer_[this->tx_buffer_at_] = '\0'; +#ifdef USE_LOG_LISTENERS for (auto *listener : this->log_listeners_) listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_); +#endif } #endif @@ -369,8 +378,10 @@ class Logger : public Component { #ifdef USE_LOGGER_RUNTIME_TAG_LEVELS std::map log_levels_{}; #endif +#ifdef USE_LOG_LISTENERS StaticVector log_listeners_; // Log message listeners (API, MQTT, syslog, etc.) +#endif #ifdef USE_LOGGER_LEVEL_LISTENERS std::vector level_listeners_; // Log level change listeners #endif diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index d7b9b244c0..f53df5564c 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -351,9 +351,6 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - # Request a log listener slot for MQTT log streaming - logger.request_log_listener() - # Add required libraries for ESP8266 and LibreTiny if CORE.is_esp8266 or CORE.is_libretiny: # https://github.com/heman/async-mqtt-client/blob/master/library.json @@ -436,6 +433,8 @@ async def to_code(config): cg.add(var.disable_log_message()) else: cg.add(var.set_log_message_template(exp_mqtt_message(log_topic))) + # Request a log listener slot only when log topic is enabled + logger.request_log_listener() if CONF_LEVEL in log_topic: cg.add(var.set_log_level(logger.LOG_LEVELS[log_topic[CONF_LEVEL]])) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 2df0552edf..3cc48c6008 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -20,6 +20,7 @@ // logger #define ESPHOME_LOG_LEVEL ESPHOME_LOG_LEVEL_VERY_VERBOSE +#define USE_LOG_LISTENERS #define ESPHOME_LOG_MAX_LISTENERS 8 // Feature flags