mirror of
https://github.com/esphome/esphome.git
synced 2026-02-26 05:53:12 -07:00
[logger] Use StaticVector for log listeners with compile-time sizing
This commit is contained in:
@@ -4,6 +4,7 @@ import logging
|
||||
from esphome import automation
|
||||
from esphome.automation import Condition
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.logger import request_log_listener
|
||||
from esphome.config_helpers import get_logger_level
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
@@ -326,6 +327,9 @@ async def to_code(config: ConfigType) -> None:
|
||||
# Track controller registration for StaticVector sizing
|
||||
CORE.register_controller()
|
||||
|
||||
# Request a log listener slot for API log streaming
|
||||
request_log_listener()
|
||||
|
||||
cg.add(var.set_port(config[CONF_PORT]))
|
||||
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
|
||||
cg.add(var.set_batch_delay(config[CONF_BATCH_DELAY]))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.logger import request_log_listener
|
||||
from esphome.components.zephyr import zephyr_add_prj_conf
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_LOGS, CONF_TYPE
|
||||
@@ -25,5 +26,8 @@ CONFIG_SCHEMA = cv.All(
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
zephyr_add_prj_conf("BT_NUS", True)
|
||||
cg.add(var.set_expose_log(config[CONF_TYPE] == CONF_LOGS))
|
||||
expose_log = config[CONF_TYPE] == CONF_LOGS
|
||||
cg.add(var.set_expose_log(expose_log))
|
||||
if expose_log:
|
||||
request_log_listener() # Request a log listener slot for BLE NUS log streaming
|
||||
await cg.register_component(var, config)
|
||||
|
||||
@@ -421,6 +421,7 @@ async def to_code(config):
|
||||
await cg.register_component(log, config)
|
||||
|
||||
for conf in config.get(CONF_ON_MESSAGE, []):
|
||||
request_log_listener() # Each on_message trigger needs a listener slot
|
||||
trigger = cg.new_Pvariable(
|
||||
conf[CONF_TRIGGER_ID], log, LOG_LEVEL_SEVERITY.index(conf[CONF_LEVEL])
|
||||
)
|
||||
@@ -546,6 +547,7 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform(
|
||||
# Keys for CORE.data storage
|
||||
DOMAIN = "logger"
|
||||
KEY_LEVEL_LISTENERS = "level_listeners"
|
||||
KEY_LOG_LISTENERS = "log_listeners"
|
||||
|
||||
|
||||
def request_logger_level_listeners() -> None:
|
||||
@@ -558,8 +560,24 @@ def request_logger_level_listeners() -> None:
|
||||
CORE.data.setdefault(DOMAIN, {})[KEY_LEVEL_LISTENERS] = True
|
||||
|
||||
|
||||
def request_log_listener() -> None:
|
||||
"""Request a log listener slot.
|
||||
|
||||
Components that need to receive log messages should call this function
|
||||
during their code generation. This increments the listener count used
|
||||
to size the StaticVector.
|
||||
"""
|
||||
data = CORE.data.setdefault(DOMAIN, {})
|
||||
data[KEY_LOG_LISTENERS] = data.get(KEY_LOG_LISTENERS, 0) + 1
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def final_step():
|
||||
"""Final code generation step to configure optional logger features."""
|
||||
if CORE.data.get(DOMAIN, {}).get(KEY_LEVEL_LISTENERS, False):
|
||||
domain_data = CORE.data.get(DOMAIN, {})
|
||||
if domain_data.get(KEY_LEVEL_LISTENERS, False):
|
||||
cg.add_define("USE_LOGGER_LEVEL_LISTENERS")
|
||||
|
||||
# Set exact count of log listeners - runtime will error if exceeded
|
||||
log_listener_count = domain_data.get(KEY_LOG_LISTENERS, 0)
|
||||
cg.add_define("ESPHOME_LOG_MAX_LISTENERS", log_listener_count)
|
||||
|
||||
@@ -369,7 +369,8 @@ class Logger : public Component {
|
||||
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
std::map<const char *, uint8_t, CStrCompare> log_levels_{};
|
||||
#endif
|
||||
std::vector<LogListener *> log_listeners_; // Log message listeners (API, MQTT, syslog, etc.)
|
||||
StaticVector<LogListener *, ESPHOME_LOG_MAX_LISTENERS>
|
||||
log_listeners_; // Log message listeners (API, MQTT, syslog, etc.)
|
||||
#ifdef USE_LOGGER_LEVEL_LISTENERS
|
||||
std::vector<LoggerLevelListener *> level_listeners_; // Log level change listeners
|
||||
#endif
|
||||
|
||||
@@ -350,6 +350,10 @@ def exp_mqtt_message(config):
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import udp
|
||||
from esphome.components.logger import LOG_LEVELS, is_log_level
|
||||
from esphome.components.logger import LOG_LEVELS, is_log_level, request_log_listener
|
||||
from esphome.components.time import RealTimeClock
|
||||
from esphome.components.udp import CONF_UDP_ID
|
||||
import esphome.config_validation as cv
|
||||
@@ -36,6 +36,7 @@ async def to_code(config):
|
||||
level = LOG_LEVELS[config[CONF_LEVEL]]
|
||||
var = cg.new_Pvariable(config[CONF_ID], level, time)
|
||||
await cg.register_component(var, config)
|
||||
request_log_listener() # Request a log listener slot for syslog
|
||||
await cg.register_parented(var, parent)
|
||||
cg.add(var.set_strip(config[CONF_STRIP]))
|
||||
cg.add(var.set_facility(config[CONF_FACILITY]))
|
||||
|
||||
@@ -4,6 +4,7 @@ import gzip
|
||||
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import web_server_base
|
||||
from esphome.components.logger import request_log_listener
|
||||
from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
@@ -313,6 +314,8 @@ async def to_code(config):
|
||||
if config.get(CONF_OTA) is False:
|
||||
cg.add_define("USE_WEBSERVER_OTA_DISABLED")
|
||||
cg.add(var.set_expose_log(config[CONF_LOG]))
|
||||
if config[CONF_LOG]:
|
||||
request_log_listener() # Request a log listener slot for web server log streaming
|
||||
if config[CONF_ENABLE_PRIVATE_NETWORK_ACCESS]:
|
||||
cg.add_define("USE_WEBSERVER_PRIVATE_NETWORK_ACCESS")
|
||||
if CONF_AUTH in config:
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
// logger
|
||||
#define ESPHOME_LOG_LEVEL ESPHOME_LOG_LEVEL_VERY_VERBOSE
|
||||
#define ESPHOME_LOG_MAX_LISTENERS 8
|
||||
|
||||
// Feature flags
|
||||
#define USE_ALARM_CONTROL_PANEL
|
||||
|
||||
Reference in New Issue
Block a user