diff --git a/README.md b/README.md index 2cf388d..d21aad4 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,16 @@ Stairway is designed to provide atomic operations for one instance of one servic global or cross-service state. Therefore, it is up to the application or service to implement concurrency control on its objects. +### Context Awareness and Logs +Stairway leverages the underlying logging system's mapped diagnostic context (MDC) if available. + +MDC manages contextual information on a per-thread basis: as Stairway submits a Flight for processing, +it **passes along the MDC of the calling thread** so that context isn't lost. It also further populates +the MDC with **flight-specific context** for the duration of the flight's execution on the thread, +and **step-specific context** for the duration of each step's execution. + +For more information on MDC, please see [Logback's MDC manual](https://logback.qos.ch/manual/mdc.html). + # TODOs * Add a section on clusters, queuing, failure, and recovery * Add a section - perhaps in DEVELOPMENT.md describing the schema diff --git a/stairway/src/main/java/bio/terra/stairway/impl/MdcHelper.java b/stairway/src/main/java/bio/terra/stairway/impl/MdcHelper.java index bafcbb3..f3143a5 100644 --- a/stairway/src/main/java/bio/terra/stairway/impl/MdcHelper.java +++ b/stairway/src/main/java/bio/terra/stairway/impl/MdcHelper.java @@ -5,6 +5,9 @@ import java.util.Optional; import org.slf4j.MDC; +/** + * Utility methods to make Stairway flight runnables context-aware, using mapped diagnostic context (MDC). + */ public class MdcHelper { /** ID of the flight */ @@ -34,8 +37,7 @@ public static Runnable withMdcAndFlightContext( // Any leftover context on the thread will be fully overwritten: MDC.setContextMap(Optional.ofNullable(contextMap).orElse(Map.of())); // If the calling thread's context contains flight and step context from a parent flight, this - // will - // be overwritten below: + // will be overwritten below: addFlightContextToMdc(flightContext); removeStepContextFromMdc(flightContext); try { diff --git a/stairway/src/test/java/bio/terra/stairway/impl/MdcHelperTest.java b/stairway/src/test/java/bio/terra/stairway/impl/MdcHelperTest.java index 4ec14a7..c017513 100644 --- a/stairway/src/test/java/bio/terra/stairway/impl/MdcHelperTest.java +++ b/stairway/src/test/java/bio/terra/stairway/impl/MdcHelperTest.java @@ -97,9 +97,8 @@ void withMdcAndFlightContext_subflight(Map initialContext) { MDC.getCopyOfContextMap(), equalTo(expectedParentFlightMdc)); // If a child flight is launched within a step in a parent flight, the calling thread's - // context would also - // contain step-specific context that should be cleared for logs emitted by the child - // flight. + // context would also contain step-specific context that should be cleared for logs + // emitted by the child flight. MdcHelper.addStepContextToMdc(flightContext); Runnable childFlight = () ->