关于 sleuth 是什么,以及它的 traceId、spanId、parentId 这3个字段的作用,这里就不做赘述了,本文是为了解决一个需求场景:
在 logback 中输出 parentId。因为官方默认只讲 traceId 和 spanId 包装进了 Scope 中,所以在 MDC 中获取不到 parentId,好在官方为我们留了很多后门,让我们可以巧妙的通过接口的方式来添加和自定义其他属性(本文虽然只是添加了 parentId,但是更重要的是给大家提供一个思路,以便于可以添加其他自定义属性)。
官方关键代码片段:
BraveBaggageConfiguration.java
@Bean
@ConditionalOnMissingBean(CorrelationScopeDecorator.class)
@ConditionalOnBean(CorrelationScopeDecorator.Builder.class)
@ConditionalOnProperty(value = "spring.sleuth.baggage.correlation-enabled", matchIfMissing = true)
ScopeDecorator correlationScopeDecorator(@Qualifier(WHITELISTED_MDC_KEYS) List<String> whiteListedMDCKeys,
SleuthBaggageProperties sleuthBaggageProperties,
@Nullable List<CorrelationScopeCustomizer> correlationScopeCustomizers) {
Set<String> correlationFields = redirectOldPropertyToNew(WHITELISTED_MDC_KEYS, whiteListedMDCKeys,
"spring.sleuth.baggage.correlation-fields", sleuthBaggageProperties.getCorrelationFields());
// Add fields from properties
CorrelationScopeDecorator.Builder builder = MDCScopeDecorator.newBuilder();
for (String field : correlationFields) {
builder.add(SingleCorrelationField.newBuilder(BaggageField.create(field)).build());
}
// handle user overrides // 这里,这里,这里,看这里
if (correlationScopeCustomizers != null) {
for (CorrelationScopeCustomizer customizer : correlationScopeCustomizers) {
customizer.customize(builder);
}
}
return builder.build();
}
CorrelationScopeDecorator.java
public static abstract class Builder {
final CorrelationContext context;
// Don't allow mixed case of the same name!
final Set<String> allNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
final Set<SingleCorrelationField> fields = new LinkedHashSet<>();
/** Internal constructor used by subtypes. */
protected Builder(CorrelationContext context) {
if (context == null) throw new NullPointerException("context == null");
this.context = context;
// 这里,这里,这里,默认只添加了这2个
add(SingleCorrelationField.create(BaggageFields.TRACE_ID));
add(SingleCorrelationField.create(BaggageFields.SPAN_ID));
}
解决本文需求,只需要将如下配置类拷贝到你的项目中即可,so easy(分析源码的还是花了一个午休时间的)
SleuthConfiguration.java
/**
* 为 Sleuth 配置类
*
* @author shanhy
* @date 2021/4/7 13:37
*/
@Configuration
public class SleuthConfiguration {
/**
* Sleuth 默认只将 traceId 和 spanId 添加进入了 MDC {@link brave.baggage.CorrelationScopeDecorator.Builder }
* 我们需要将 parentId 输出到 logback 中,所以在这里自定义添加 parent 到MDC中
* Sleuth 为我们提供了自定义扩展接口 CorrelationScopeCustomizer,实现它即可对 builder 进行操作
*
* @return
*/
@Bean
public CorrelationScopeCustomizer createCorrelationScopeCustomizer(){
return builder -> builder.add(CorrelationScopeConfig.SingleCorrelationField.create(BaggageFields.PARENT_ID));
}
}
下面是我自己的 logback 中对应的输出示例(片段):
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}) - %clr([%5level]) %clr([${APP_NAME},%X{traceId:-},%X{spanId:-},%X{parentId:-}]) %clr(${PID:- }) --- %clr([%20.20t]) %-50.50logger{49}: %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
注意:sleuth 3.x 版本开始,logback 中的变量名称有变(不是X-B3开头了),同理如果你在代码中从MDC读取对应的 traceId 和 spanId ,也要注意新的变量名称。
官方文档:https://docs.spring.io/spring-cloud-sleuth/docs/current-SNAPSHOT/reference/html/project-features.html
(END)