Skip to content
Bluetape4k docs1.11

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.

Lifecycle of outer, inner, and restored MDC state

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.

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.

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.

  • 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.

Use Coroutine MDC when suspend code can switch threads.