• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines.slf4j
6 
7 import kotlinx.coroutines.*
8 import org.slf4j.MDC
9 import kotlin.coroutines.AbstractCoroutineContextElement
10 import kotlin.coroutines.CoroutineContext
11 
12 /**
13  * The value of [MDC] context map.
14  * See [MDC.getCopyOfContextMap].
15  */
16 public typealias MDCContextMap = Map<String, String>?
17 
18 /**
19  * [MDC] context element for [CoroutineContext].
20  *
21  * Example:
22  *
23  * ```
24  * MDC.put("kotlin", "rocks") // Put a value into the MDC context
25  *
26  * launch(MDCContext()) {
27  *     logger.info { "..." }   // The MDC context contains the mapping here
28  * }
29  * ```
30  *
31  * Note that you cannot update MDC context from inside the coroutine simply
32  * using [MDC.put]. These updates are going to be lost on the next suspension and
33  * reinstalled to the MDC context that was captured or explicitly specified in
34  * [contextMap] when this object was created on the next resumption.
35  * Use `withContext(MDCContext()) { ... }` to capture updated map of MDC keys and values
36  * for the specified block of code.
37  *
38  * @param contextMap the value of [MDC] context map.
39  * Default value is the copy of the current thread's context map that is acquired via
40  * [MDC.getCopyOfContextMap].
41  */
42 public class MDCContext(
43     /**
44      * The value of [MDC] context map.
45      */
46     @Suppress("MemberVisibilityCanBePrivate")
47     public val contextMap: MDCContextMap = MDC.getCopyOfContextMap()
48 ) : ThreadContextElement<MDCContextMap>, AbstractCoroutineContextElement(Key) {
49     /**
50      * Key of [MDCContext] in [CoroutineContext].
51      */
52     public companion object Key : CoroutineContext.Key<MDCContext>
53 
54     /** @suppress */
updateThreadContextnull55     override fun updateThreadContext(context: CoroutineContext): MDCContextMap {
56         val oldState = MDC.getCopyOfContextMap()
57         setCurrent(contextMap)
58         return oldState
59     }
60 
61     /** @suppress */
restoreThreadContextnull62     override fun restoreThreadContext(context: CoroutineContext, oldState: MDCContextMap) {
63         setCurrent(oldState)
64     }
65 
setCurrentnull66     private fun setCurrent(contextMap: MDCContextMap) {
67         if (contextMap == null) {
68             MDC.clear()
69         } else {
70             MDC.setContextMap(contextMap)
71         }
72     }
73 }
74