with Logging Context
Adds the given log fields to every log made by a Logger in the context of the given block. Use the field/rawJsonField functions to construct log fields.
An example of when this is useful is when processing an event, and you want the event to be attached to every log while processing it. Instead of manually attaching the event to each log, you can wrap the event processing in withLoggingContext
with the event as a log field, and then all logs inside that context will include the event.
Field value encoding with SLF4J
The JVM implementation uses MDC
from SLF4J, which only supports String values by default. To encode object values as actual JSON (not escaped strings), you can add dev.hermannm.devlog.LoggingContextJsonFieldWriter
as an mdcEntryWriter
for logstash-logback-encoder
, like this:
<!-- Example Logback config (in src/main/resources/logback.xml) -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<!-- Writes object values from logging context as actual JSON (not escaped) -->
<mdcEntryWriter class="dev.hermannm.devlog.LoggingContextJsonFieldWriter"/>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration
This requires that you have added ch.qos.logback:logback-classic
and net.logstash.logback:logstash-logback-encoder
as dependencies.
Note on coroutines
SLF4J's MDC
uses a thread-local, so it won't work by default with Kotlin coroutines and suspend
functions. If you use coroutines, you can solve this with MDCContext
from kotlinx-coroutines-slf4j
.
Example
import dev.hermannm.devlog.field
import dev.hermannm.devlog.getLogger
import dev.hermannm.devlog.withLoggingContext
private val log = getLogger()
fun example(event: Event) {
withLoggingContext(field("event", event)) {
log.debug { "Started processing event" }
// ...
log.debug { "Finished processing event" }
}
}
If you have configured dev.hermannm.devlog.LoggingContextJsonFieldWriter
, the field from withLoggingContext
will then be attached to every log as follows:
{ "message": "Started processing event", "event": { ... } }
{ "message": "Finished processing event", "event": { ... } }