mirror of
https://github.com/esphome/esphome.git
synced 2026-02-18 15:35:59 -07:00
[logger] Conditionally compile log level change listener
This commit is contained in:
@@ -406,6 +406,8 @@ async def to_code(config):
|
||||
conf,
|
||||
)
|
||||
|
||||
CORE.add_job(final_step)
|
||||
|
||||
|
||||
def validate_printf(value):
|
||||
# https://stackoverflow.com/questions/30011379/how-can-i-parse-a-c-format-string-in-python
|
||||
@@ -506,3 +508,23 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform(
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# Key for CORE.data to track if level listeners are requested
|
||||
LOGGER_LEVEL_LISTENERS_KEY = "logger_level_listeners"
|
||||
|
||||
|
||||
def request_logger_level_listeners() -> None:
|
||||
"""Request that logger level listeners be compiled in.
|
||||
|
||||
Components that need to be notified about log level changes should call this
|
||||
function during their code generation. This enables the add_level_listener()
|
||||
method and compiles in the listener vector.
|
||||
"""
|
||||
CORE.data[LOGGER_LEVEL_LISTENERS_KEY] = True
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def final_step():
|
||||
"""Final code generation step to configure optional logger features."""
|
||||
if CORE.data.get(LOGGER_LEVEL_LISTENERS_KEY, False):
|
||||
cg.add_define("USE_LOGGER_LEVEL_LISTENERS")
|
||||
|
||||
@@ -288,7 +288,10 @@ void Logger::set_log_level(uint8_t level) {
|
||||
ESP_LOGW(TAG, "Cannot set log level higher than pre-compiled %s", LOG_STR_ARG(LOG_LEVELS[ESPHOME_LOG_LEVEL]));
|
||||
}
|
||||
this->current_level_ = level;
|
||||
this->level_callback_.call(level);
|
||||
#ifdef USE_LOGGER_LEVEL_LISTENERS
|
||||
for (auto *listener : this->level_listeners_)
|
||||
listener->on_log_level_change(level);
|
||||
#endif
|
||||
}
|
||||
|
||||
Logger *global_logger = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
@@ -58,6 +58,18 @@ class LogListener {
|
||||
virtual void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) = 0;
|
||||
};
|
||||
|
||||
#ifdef USE_LOGGER_LEVEL_LISTENERS
|
||||
/** Interface for receiving log level changes without std::function overhead.
|
||||
*
|
||||
* Components can implement this interface instead of using lambdas with std::function
|
||||
* to reduce flash usage from std::function type erasure machinery.
|
||||
*/
|
||||
class LoggerLevelListener {
|
||||
public:
|
||||
virtual void on_log_level_change(uint8_t level) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
// Comparison function for const char* keys in log_levels_ map
|
||||
struct CStrCompare {
|
||||
@@ -193,8 +205,10 @@ class Logger : public Component {
|
||||
/// Register a log listener to receive log messages
|
||||
void add_log_listener(LogListener *listener) { this->log_listeners_.push_back(listener); }
|
||||
|
||||
// add a listener for log level changes
|
||||
void add_listener(std::function<void(uint8_t)> &&callback) { this->level_callback_.add(std::move(callback)); }
|
||||
#ifdef USE_LOGGER_LEVEL_LISTENERS
|
||||
/// Register a listener for log level changes
|
||||
void add_level_listener(LoggerLevelListener *listener) { this->level_listeners_.push_back(listener); }
|
||||
#endif
|
||||
|
||||
float get_setup_priority() const override;
|
||||
|
||||
@@ -325,7 +339,9 @@ class Logger : public Component {
|
||||
std::map<const char *, uint8_t, CStrCompare> log_levels_{};
|
||||
#endif
|
||||
std::vector<LogListener *> log_listeners_; // Log message listeners (API, MQTT, syslog, etc.)
|
||||
CallbackManager<void(uint8_t)> level_callback_{};
|
||||
#ifdef USE_LOGGER_LEVEL_LISTENERS
|
||||
std::vector<LoggerLevelListener *> level_listeners_; // Log level change listeners
|
||||
#endif
|
||||
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
||||
std::unique_ptr<logger::TaskLogBuffer> log_buffer_; // Will be initialized with init_log_buffer
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,13 @@ from esphome.const import CONF_LEVEL, CONF_LOGGER, ENTITY_CATEGORY_CONFIG, ICON_
|
||||
from esphome.core import CORE
|
||||
from esphome.cpp_helpers import register_component, register_parented
|
||||
|
||||
from .. import CONF_LOGGER_ID, LOG_LEVELS, Logger, logger_ns
|
||||
from .. import (
|
||||
CONF_LOGGER_ID,
|
||||
LOG_LEVELS,
|
||||
Logger,
|
||||
logger_ns,
|
||||
request_logger_level_listeners,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@clydebarrow"]
|
||||
|
||||
@@ -21,6 +27,7 @@ CONFIG_SCHEMA = select.select_schema(
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
request_logger_level_listeners()
|
||||
parent = await cg.get_variable(config[CONF_LOGGER_ID])
|
||||
levels = list(LOG_LEVELS)
|
||||
index = levels.index(CORE.data[CONF_LOGGER][CONF_LEVEL])
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace esphome::logger {
|
||||
|
||||
void LoggerLevelSelect::publish_state(int level) {
|
||||
void LoggerLevelSelect::on_log_level_change(uint8_t level) {
|
||||
auto index = level_to_index(level);
|
||||
if (!this->has_index(index))
|
||||
return;
|
||||
@@ -10,8 +10,8 @@ void LoggerLevelSelect::publish_state(int level) {
|
||||
}
|
||||
|
||||
void LoggerLevelSelect::setup() {
|
||||
this->parent_->add_listener([this](int level) { this->publish_state(level); });
|
||||
this->publish_state(this->parent_->get_log_level());
|
||||
this->parent_->add_level_listener(this);
|
||||
this->on_log_level_change(this->parent_->get_log_level());
|
||||
}
|
||||
|
||||
void LoggerLevelSelect::control(size_t index) { this->parent_->set_log_level(index_to_level(index)); }
|
||||
|
||||
@@ -5,12 +5,17 @@
|
||||
#include "esphome/components/logger/logger.h"
|
||||
|
||||
namespace esphome::logger {
|
||||
class LoggerLevelSelect : public Component, public select::Select, public Parented<Logger> {
|
||||
class LoggerLevelSelect final : public Component,
|
||||
public select::Select,
|
||||
public Parented<Logger>,
|
||||
public LoggerLevelListener {
|
||||
public:
|
||||
void publish_state(int level);
|
||||
void setup() override;
|
||||
void control(size_t index) override;
|
||||
|
||||
// LoggerLevelListener interface
|
||||
void on_log_level_change(uint8_t level) override;
|
||||
|
||||
protected:
|
||||
// Convert log level to option index (skip CONFIG at level 4)
|
||||
static uint8_t level_to_index(uint8_t level) { return (level > ESPHOME_LOG_LEVEL_CONFIG) ? level - 1 : level; }
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#define USE_LIGHT
|
||||
#define USE_LOCK
|
||||
#define USE_LOGGER
|
||||
#define USE_LOGGER_LEVEL_LISTENERS
|
||||
#define USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
#define USE_LVGL
|
||||
#define USE_LVGL_ANIMIMG
|
||||
|
||||
Reference in New Issue
Block a user