Scoped MDC and nested restoration
Latest stable Based on Bluetape4k release 1.11.0
MDC adds correlation fields to log lines, but its underlying state is thread-local and mutable. Separating put and cleanup responsibility easily leaks one request into the next.
What the scope owns
Section titled “What the scope owns”withLoggingContext( "traceId" to "trace-100", "tenantId" to tenantId,) { log.info { "Load account" }}restorePrevious=true is the default. The helper remembers each prior value and restores it in finally after success or failure. Keys without a previous value are removed.
Nesting and policy
Section titled “Nesting and policy”MDC.put("traceId", "outer")withLoggingContext("traceId" to "inner") { check(MDC.get("traceId") == "inner")}check(MDC.get("traceId") == "outer")With restorePrevious=false, the scope removes installed keys on exit. Keep the default for a nested operation that must return to outer values. A null map or vararg value is not installed.
Exceptions and cleanup
Section titled “Exceptions and cleanup”Cleanup runs after a business exception. A map cleanup callback exception is swallowed so it cannot replace the primary failure. This preserves the main exception; it does not make cleanup defects harmless.
Values appropriate for MDC
Section titled “Values appropriate for MDC”- small, stable request, trace, span, or tenant correlation keys
- identifiers already sanitized
- fields actually emitted by the log pattern or structured encoder
Do not store passwords, tokens, raw payloads, or unbounded collections. Setting a field is insufficient: Logback needs %X{traceId} or a corresponding structured mapping to emit it.
Source and tests
Section titled “Source and tests”Use Coroutine MDC when suspend code can switch threads.