簡體   English   中英

如何在 kotlin 中的多模塊項目中的線程之間共享 MDC 上下文 - kotlinx.coroutines.slf4j

[英]How to share MDC context between threads in multimodule project in kotlin - kotlinx.coroutines.slf4j

我有一個多模塊項目,我希望有一個上下文可以通過不同的模塊共享。

在我的核心模塊(它們都依賴於此)中,我創建了一個 class 來使用 org.slf4j.MDC 管理上下文,它有兩個函數,一個用於在上下文 (logContext) 中存儲屬性,另一個用於獲取上下文(get上下文)

import jakarta.inject.Singleton
import kotlinx.coroutines.slf4j.MDCContextMap
import mu.KotlinLogging
import org.slf4j.MDC

private val logger = KotlinLogging.logger {}

@Singleton
class LoggingContext {
    companion object {
        fun logContext(name: String, id: String) {
            MDC.put("name", name)
            MDC.put("id", id)
            logger.info { "Companion object - logContext: ${MDC.getCopyOfContextMap()}" }
        }

        fun getContext(): MDCContextMap {
            logger.info { "Companion object - getContext: ${MDC.getCopyOfContextMap()}" }
            return MDC.getCopyOfContextMap()
        }
    }
}

問題如下:

我有一個完整的模塊,其中有一個 controller,我想在上下文中存儲來自請求的nameid 為此,我只需在我的 controller 代碼中添加以下行:

logContext("request_name", "request_id")

在 controller 代碼中(在 controller 模塊中),如果我調用getContext() function,我將獲得剛剛從請求中保存的屬性。 直到這里一切都很好✅

❌ 但是,如果我嘗試這樣做,從另一個模塊獲取上下文,例如,從存儲庫模塊(它是項目中的一個全新模塊)調用getContext() function,我得到一個 null。那里根本沒有上下文。

我假設是因為,當我試圖從另一個模塊獲取上下文時,它是另一個線程,並且上下文不在整個項目中共享。

更新:為了提供更多上下文,流程如下:

  1. 這是接收請求的端點,我想在上下文中存儲 name 和 id 屬性。
@Get(PATH_GLOBAL)
    suspend fun getGlobal(
        @PathVariable name: String,
        @PathVariable id: String,
        httpRequest: HttpRequest<*>,
    ): HttpResponse<Resource> {
        LoggingContext.logContext(name, id)
        ...
    // invoke repository
        return readOperation.execute(trigger).fold(...)
    }
  1. 以前的端點調用存儲在另一個模塊中的以下 function。
override suspend fun readConfiguration(...): {
        logger.trace { "Reading configuration from repository" }
        val entity = configurationDataRepository.findBy(...)
        
        logger.info { "ConfigurationDataRepositoryImpl - readConfiguration4: ${MDC.getCopyOfContextMap()}" }

        withContext(MDCContext()) {
            logger.info { "ConfigurationDataRepositoryImpl - readConfiguration1: ${MDC.getCopyOfContextMap()}" }
        }

        return ...
    }

我嘗試添加withContext(MDCContext()){...}但在使用和不使用 withContext 調用getContext() function 時我得到了withContext...

那么,如何將上下文設置為在所有模塊內共享?

非常感謝您的幫助:)

顯然,解決方案就像在設置 MDC 上下文后立即添加withContext(MDCContext())一樣簡單,以保留 MDC 上下文。

所以,就我而言,我必須像這樣用之前的 function 包裝我的 controller:

@Get(PATH_GLOBAL)
    suspend fun getGlobal(
        @PathVariable name: String,
        @PathVariable id: String,
        httpRequest: HttpRequest<*>,
    ): HttpResponse<Resource> {

        LoggingContext.logContext(name, id)
    
        // Add withContext(MDCContext()) right after setting the Context
        return withContext(MDCContext()) {
            ...
            // invoke repository
            readOperation.execute(trigger).fold(...)
        }
    }

這對我行得通!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM