Repository navigation
feat(logger): make the tag's mutability a compile-time option (off on ESP-IDF) - #882
Conversation
… ESP-IDF) Changing a Logger's tag after construction needs a mutex, and on ESP-IDF every std::mutex allocates its FreeRTOS semaphore: about 116 B of internal RAM for every Logger, which every espp component has. Almost nothing changes the tag after construction, so: - New Kconfig option CONFIG_ESPP_LOGGER_MUTABLE_TAG (default n). With it off the Logger has no mutex, and Logger::set_tag() / BaseComponent::set_log_tag() fail to compile with a message naming the option, so existing users can turn it on and keep building. - Host / python builds keep the mutable tag (the python bindings expose set_log_tag()); define ESPP_LOGGER_MUTABLE_TAG to 0 / 1 to choose. - RtspSession and PersistentData set their tags in the constructor instead of with set_tag() / set_log_tag(). M5Stack Tab5 example: about 2.9 KB more internal RAM free after initialize_audio(). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
|
✅Static analysis result - no issues found! ✅ |
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
No open issues 🎉
What changed in this PR
This PR makes Logger tag mutability a compile-time option (off by default on ESP-IDF) to eliminate per-Logger mutex RAM overhead, and updates components that previously changed tags post-construction to set tags during construction instead.
Changes:
- Add
CONFIG_ESPP_LOGGER_MUTABLE_TAGKconfig option to control whether tags can change after construction. - Update
Logger/BaseComponentto compile-time enable/disableset_tag()/set_log_tag()(withstatic_assertwhen disabled), and remove tag mutex usage when disabled. - Update
RtspSessionandPersistentDatato include additional context in the constructor tag rather than callingset_tag()later.
| File | Description |
|---|---|
| components/rtsp/src/rtsp_session.cpp | Set RTSP session logger tag during base construction via a delegating constructor. |
| components/rtsp/include/rtsp_session.hpp | Add protected ctor for injected session id; make generate_session_id() static. |
| components/persistent_data/include/persistent_data.hpp | Bake file name into the logger tag at construction time (no runtime tag mutation). |
| components/logger/include/logger.hpp | Add compile-time mutable-tag switch and remove tag mutex/locking when disabled. |
| components/logger/Kconfig | Add ESPP_LOGGER_MUTABLE_TAG Kconfig option (default off). |
| components/base_component/include/base_component.hpp | Gate set_log_tag() behind the mutable-tag option with a clear compile-time failure when disabled. |
Review effort: Lite
- iperf_menu example: add base_component to EXTRA_COMPONENT_DIRS. Without
it the component manager pulls the published espp/base_component, whose
set_log_tag() calls Logger::set_tag(), which the local logger now rejects
when CONFIG_ESPP_LOGGER_MUTABLE_TAG is off.
- motorgo-mini: default_motor{1,2}_config copied motor{1,2}_driver_ and
encoder{1,2}_, members declared (so constructed) after it - copying
shared_ptrs that do not exist yet. init_motor_channel_{1,2}() always set
both, so the defaults now hold nullptr. GCC 15 reports it
(-Werror=uninitialized) since the Logger change alters inlining of the
MotorGoMini constructor, failing the bldc_motor, bldc_haptics and
motorgo-mini examples.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
2 open issues
Review effort: Lite
…ds guard It sat inside #if !defined(ESPP_LOGGER_CURSOR_COMMANDS_ENABLED), so a build that defines ESPP_LOGGER_CURSOR_COMMANDS_ENABLED itself left it undefined - which the #if checks read as 0, silently making the tag immutable. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
2 open issues
2 resolved since last review
Review effort: Lite
…hat it is defined Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY


Description
On ESP-IDF every
std::mutexallocates its FreeRTOS semaphore when it is constructed. That is about 116 B of internal RAM (anew std::mutexmeasured 140 B with heap overhead). Everyespp::Loggerhas one, to guard its tag againstset_tag(), and every espp component has a Logger. Almost nothing changes a tag after construction: in this repo onlyRtspSessionandPersistentDatadid, both from their constructors.This PR makes the tag's mutability a compile-time option:
CONFIG_ESPP_LOGGER_MUTABLE_TAG(menuconfig: ESPP Logger → Mutable tag), default n.Logger::set_tag()andBaseComponent::set_log_tag()become templates that fail to compile with astatic_assertnaming the option, so existing users see what to turn on to keep building.set_log_tag(). DefiningESPP_LOGGER_MUTABLE_TAGto 0 or 1 overrides that.RtspSessionandPersistentDatanow set their tags in the constructor.RtspSessiondelegates to a new constructor that takes the session ID, because the tag is set before the members are.generate_session_id()is nowstatic, since it uses no members.Loggerstill replace the tag. They are not thread-safe against another thread logging through the same Logger, just like assigning any other object.Measured
M5Stack Tab5 example on ESP-IDF 6.1, internal RAM free at the same point, with main's Logger vs this branch's:
initialize_audio()initialize_audio()Possible follow-up
A seqlock-guarded fixed-size tag would allow a mutable tag without a mutex. It would have compile-time options for the tag length, and perhaps
std::arrayvsstd::stringstorage.Testing
set_tag()with the option off: fails withstatic assertion failed: Logger::set_tag() needs CONFIG_ESPP_LOGGER_MUTABLE_TAG (menuconfig: ESPP Logger -> Mutable tag); or set the tag in the Logger's Config.set_tag()withCONFIG_ESPP_LOGGER_MUTABLE_TAG=y: builds.🤖 Generated with Claude Code
https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY