Skip to main content

Contextual event items

Klogging includes the LogContext class to hold a map of contextual information in a coroutine context. For example:

suspend fun complexLogic(input: EssentialStuff) {
withLogContext("runId" to input.runId) {
logger.info { "Starting logic" }

// Do stuff: log events, call functions, etc.

logger.info { "Finished logic" }
}
}

The log events sent by any suspend functions within the scope of the launched coroutine will contain a field called runId with the value of input.runId for that particular run.

Example of two log events with the same value of runId in Seq

Coroutine context information is kept for the duration of the current coroutine scope and is automatically removed at the end of that scope. Context information is also automatically copied into child scopes as required.

This is easier to use and more flexible than Mapped Diagnostic Context (MDC) in Logback and ThreadContext in Log4J. Those contexts require callers to remove items when finished and to ensure items are moved between threads.

Log context functions

Klogging provides functions for creating and managing LogContext instances.

logContext()

Create a LogContext instance with items to include in log events, for example:

    launch(logContext("runId" to request.runId, "userId" to request.userId)) {
logger.info("Start processing")
// etc.
}

logContext() returns a new CoroutineContext instance. It also includes any LogContext information in the current coroutine scope:

    withContext(logContext("runId" to request.runId) {
// Item `runId` is in scope.
withContext(logContext("mode" to calculateMode()) {
// Both `runId` and `mode` items are in scope.
}
// Only `runId` is in scope.
}

withLogContext()

Create a LogContext within the current coroutine scope with items to include in log events, for example:

    withLogContext("runId" to request.runId, "userId" to request.userId) {
logger.info("Start processing")
// etc.
}

withLogContext() is the same as withContext(logContext()).

addToContext()

Add items to a LogContext in the current coroutine scope, for example:

    // Within a coroutine scope …
addToContext("mode" to calculateMode())
// Item `mode` is now in coroutine scope `LogContext`

removeFromContext()

Remove items from a LogContext in the current coroutine scope, for example:

    // Within a coroutine scope …
removeFromContext("mode")
// Item `mode` is no longer in coroutine scope `LogContext`