【问题标题】:Contextual logging (corelation id in headers ) with webflux使用 webflux 进行上下文日志记录(标头中的相关 id)
【发布时间】:2020-10-28 04:30:27
【问题描述】:

我需要控制器中协程内的标头中的一些参数,并将它们记录为我的请求的关联 ID。

是否可以在控制器中使用 webflux / kotlin 协程并使用标头中的参数进行上下文日志记录?

我知道 Webflux 可以使用 WebFilter 来拦截 headers 并记录或修改它们,但是可以将它发送到它将触发的协程吗?

@RestController
class ItemController(private val itemRepository: ItemRepository) {

    @GetMapping("/")
    suspend fun findAllItems(): List<Item> =
        // do stuff
        logger.log("Corelation id is : " + myCorelationIdHeaderParam) // that's the param i need
        return itemService.findAll()
}

【问题讨论】:

    标签: kotlin spring-webflux kotlin-coroutines


    【解决方案1】:

    您在网络过滤器中设置的任何上下文都可以通过在控制器/服务中使用subscriberContext 来访问。

    以下是使用 Java 的示例。您可以在您的 Kotlin 代码中使用类似的逻辑

    您的过滤器:(这里您在“myContext”中设置标题值“someHeaderval”)

    public class MyFilter implements WebFilter {
    
    
      @Override
      public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String someHeaderval = request.getHeaders().get("someHeader").get(0);
        return chain.filter(exchange).subscriberContext(context -> {
                      return context.put("myContext",someHeaderval);
                    });;
      }
    
    }
    
    

    现在您可以在任何地方使用此上下文:

    @GetMapping(value = "/myGetApi")
      public Mono<String> sampleGet() {
        return Mono.subscriberContext()
            .flatMap(context -> {
              String myHeaderVal = (String)context.get("myContext");
              //do logging with this header value
              return someService.doSomething(myHeaderVal);
            });
      }
    

    【讨论】:

    • 感谢过滤器部分。对于控制器方法,我将在下面发布 Kotlin 的答案
    【解决方案2】:

    原来你可以从 CoroutineContext 访问 ReactorContext

    coroutineContext[ReactorContext]
    

    这是我的代码:

    @Component
    class MyWebFilter : WebFilter {
        val headerKey = "correlation-token-key"
        val contextKey = "correlationId"
        override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
            val headers: HttpHeaders = exchange.request.headers
            return chain.filter(exchange)
                .subscriberContext(Context.of(contextKey, headers[headerKey] ?: "unidentified"))
    
        }
    }
    

    和控制器部分(对 Kotlin 用户最重要):

    @RestController
    class ItemController(private val itemRepository: ItemRepository) {
        @GetMapping("/")
        suspend fun findAllItems(): List<Item> =
            // do stuff
            logger.log("Correlation id of request is : " + coroutineContext[ReactorContext]?.context?.get<List<String>>("correlationId")?.firstOrNull()) 
            return itemService.findAll()
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-06
      • 2017-09-27
      • 2021-09-23
      • 2019-01-28
      • 2021-03-20
      • 1970-01-01
      • 2016-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多