-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Description
Summary
When building spdlog as a compiled library (SPDLOG_COMPILED_LIB
) and using the mdc_formatter
(%&
), MDC values inserted via spdlog::mdc::put(...)
are not visible in the formatter. This only happens in optimized builds (-O2
, -O3
); in debug builds (-O0
), everything works as expected.
This is caused by static thread_local
usage in mdc::get_context()
in the header file mdc.h
. Under optimization, the compiler generates separate instances of the thread_local context
per translation unit, which causes put(...)
and the formatter to operate on different contexts — even within the same thread.
Minimal reproduction
- Build spdlog with
-O2
,-DSPDLOG_BUILD_SHARED=ON
andSPDLOG_BUILD_TESTS=ON
. - Run the test:
mdc formatter test-1
intest_pattern_formatter.cpp
.
Expected log output:
[logger-name] [info] [mdc_key_1:mdc_value_1 mdc_key_2:mdc_value_2] some message
Actual output:
[logger-name] [info] [] some message
If you insert this line before the formatter call:
REQUIRE(spdlog::mdc::get("mdc_key_1") == "mdc_value_1");
…then the value is found — confirming that put()
worked, but mdc_formatter
sees a different thread_local context
.
Cause
mdc::get_context()
is currently defined as:
static thread_local mdc_map_t context;
in a header-only context. This causes multiple copies of the variable to be instantiated across different TUs when optimization is enabled, due to inlining and aggressive code elimination. In particular:
mdc::put()
is compiled into the test TU,mdc_formatter::format()
is compiled into the spdlog library TU,- and they each operate on a different
thread_local
instance.
This does not occur at -O0 because inlining is disabled, and symbol resolution happens normally.
Suggested fix
Move the definition of get_context()
to a .cpp
file to guarantee a single instance of the thread_local
variable per program (per thread)
This avoids duplication across TUs and ensures that all MDC-aware components share the same storage.
Notes
- Tested on macOS (Clang 14, Apple Silicon).