【问题标题】:How to get request headers to be saved to MDC如何获取要保存到 MDC 的请求标头
【发布时间】:2020-10-04 18:25:56
【问题描述】:

我有一个带有 spring-cloud-sleuth (Hoxton.SR3) 的 spring boot (2.2.5.RELEASE) 项目。 我想向包含标头的控制器发送请求,并且此标头为:

  1. 填充在控制器的跨距行李中(即currentSpan.context().extra()
  2. 已保存到 MDC

我有一个自定义TracingConfiguration

@Bean
public Tracing tracing(@Value("${spring.application.name}") String serviceName, TracingProperties tracingProperties,
                       CurrentTraceContext currentTraceContext) {

    String profile = String.join(",", env.getActiveProfiles());

    log.info("Enable tracing for service {}", serviceName + ":" + profile);
    return Tracing.newBuilder()
            .localServiceName(serviceName + ":" + profile)
            .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
                    .addScopeDecorator(MDCScopeDecorator.create()) // puts trace IDs into logs
                    .build()
            )
            .sampler(Sampler.NEVER_SAMPLE)
            .propagationFactory(
                    ExtraFieldPropagation.newFactoryBuilder(B3Propagation.FACTORY)
                            .addPrefixedFields(TracingConstant.BAGGAGE_HEADER_PREFIX, tracingProperties.getAllBaggageKeys())
                            .build())
            .build();
}

tracingProperties.getAllBaggageKeys 返回从我的配置文件中读取的行李密钥列表时。

我也在application.yml中定义了:

spring:
  sleuth:
    log:
      slf4j:
        whitelisted-mdc-keys:
          - behalf-flow-id
          - behalf-requested-time
          - x-behalf-ach-file-name
          - behalf-principal-id
          - x-http-request-id
          - behalf-principal
          - requestid
    baggage-keys:
      - behalf-flow-id
      - behalf-requested-time
      - x-behalf-ach-file-name
      - behalf-principal-id
      - x-http-request-id
      - behalf-principal
      - requestid

当我(通过 POSTMAN)调用带有键 baggage-behalf-requested-time 和值 123456 的标头的服务控制器时,我得到 currentSpan.context().extra() 的值 baggage-behalf-requested-time(即 123456

问题

  1. 是否需要在标题前加上baggage- 前缀?框架不是应该自己处理吗?或者它只是在我使用 Spring 本身发送请求时才这样做(即RestTemplate)?
  2. 为什么 MDC 没有填充 baggage-behalf-requested-time 标头的值?

【问题讨论】:

    标签: java spring spring-boot spring-cloud spring-cloud-sleuth


    【解决方案1】:

    您拥有自定义跟踪机制,这就是为什么您需要处理所有 baggage- 前缀等。如果您查看 Sleuth 的 2.2.2.RELEASE,您会发现我们自己为这些字段添加前缀https://github.com/spring-cloud/spring-cloud-sleuth/blob/v2.2.2.RELEASE/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java#L168-L174 然后,它们也被填充到 MDC (https://github.com/spring-cloud/spring-cloud-sleuth/blob/v2.2.2.RELEASE/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jScopeDecorator.java) 但没有 baggage- 前缀。在最新版本 (2.2.3.RELEAE) 中,代码进行了重构,但在概念上是相似的。

    【讨论】:

    • 我删除了我的自定义跟踪机制(因为 Sleuth 给了我相同的功能),现在它似乎可以工作了。谢谢你!
    • 如果我有想要手动设置的 e bag-key(在 application.yml 中定义),我应该使用 ExtraFieldPropagation.set() 吗?因为这样做时,currentSpan.context().extra() 填充了 key+value 但没有 baggage- 前缀,并且 MDC 也没有填充 key+value...
    • 如果没有baggage,您需要将其添加到行李钥匙中。在新版本中,您必须将值与 baggage- 前缀一起显式传递。或者让我改写一下,baggage 前缀将不再需要。
    • 我不关注... 我想手动设置的值存在于行李键中(例如 requestid),但是在调用 ExtraFieldPropagation.set(context, "requestid", SomeValue) 时它没有添加到 MDC(问题) 并且它在currentSpan.context().extra() 中但没有baggage- 前缀(它应该是这样的吗?)并且如果它假设在上下文中没有baggage- 前缀,那么当代码通过 HTTP 或消息调用另一个服务?
    • 它将被添加到带有前缀的标题中,但如果没有它,它将在 mdc 中。有时它不会刷新到 mdc。您可以在新 sleuth 版本的文档中了解它。在那里你可以设置自动冲洗选项
    【解决方案2】:

    您可以编写customeFilter来拦截每个请求并将请求中的数据放入MDC。

    
    @Component
    public class CustomFilter implements Filter {
    
      @Override
      public void doFilter(ServletRequest req, ServletResponse res,
          FilterChain chain) throws IOException, ServletException {
          final String correlationId = getCorrelationIdFromHeader(req);
          MDC.put(HttpConstants.CORRELATION_ID_HEADER_NAME, correlationId);
          chain.doFilter(req, res);
      }
    }
    

    【讨论】:

    • 我在寻找框架自动提供的东西,而不是手动完成
    【解决方案3】:

    做事

        public String someMethod(HttpServletRequest request, HttpServletResponse httprespons)
    {
     MDC.put(request.getHeader("header_name"););
    }
    

    传递 HttpServletRequest,HttpServletResponse 作为参数。

    【讨论】:

    • 我正在寻找框架自动提供的东西,而不是手动完成
    猜你喜欢
    • 2018-02-27
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    相关资源
    最近更新 更多