12. 定制

12.1. 禁用默认日志记录模式

Spring Cloud Sleuth 设置默认日志记录模式。要禁用它,请将属性设置为 。spring.sleuth.default-logging-pattern-enabledfalsespring-doc.cn

12.2. 定制器

使用 Brave 5.7,您可以通过多种方式为您的项目提供定制器。Brave 搭载spring-doc.cn

  • TracingCustomizer- 允许配置插件协作构建 .Tracingspring-doc.cn

  • CurrentTraceContextCustomizer- 允许配置插件协作构建 .CurrentTraceContextspring-doc.cn

  • ExtraFieldCustomizer- 允许配置插件协作构建 .ExtraFieldPropagation.Factoryspring-doc.cn

Sleuth 将搜索这些类型的 bean 并自动应用自定义。spring-doc.cn

12.3. HTTP 协议

12.3.1. 数据政策

HTTP 请求的默认 span 数据策略在 Brave 中进行了描述:github.com/openzipkin/brave/tree/master/instrumentation/http#span-data-policyspring-doc.cn

要将不同的数据添加到 span 中,您需要注册一个 bean 类型或 数据被收集。brave.http.HttpRequestParserbrave.http.HttpResponseParserspring-doc.cn

Bean 名称对应于请求或响应端,以及它是否是 客户端或服务器。例如,更改 在将客户端请求发送到服务器之前收集。sleuthHttpClientRequestParserspring-doc.cn

为方便起见,可以使用相应的服务器注释来注入适当的 bean 或者通过其静态 String 字段引用 bean 名称。@HttpClientRequestParser@HttpClientResponseParserNAMEspring-doc.cn

下面是一个示例,除了 defaults 之外,还添加了 HTTP url:spring-doc.cn

@Configuration
class Config {
  @Bean(name = { HttpClientRequestParser.NAME, HttpServerRequestParser.NAME })
  HttpRequestParser sleuthHttpServerRequestParser() {
      return (req, context, span) -> {
          HttpRequestParser.DEFAULT.parse(req, context, span);
          String url = req.url();
          if (url != null) {
              span.tag("http.url", url);
          }
      };
  }
}

12.3.2. 采样

如果需要 Client 端/服务器采样,只需注册一个 Bean 类型,并为 Client 端采样器和服务器采样器命名该 Bean。brave.sampler.SamplerFunction<HttpRequest>sleuthHttpClientSamplersleuthHttpServerSamplerspring-doc.cn

为方便起见,可以使用 and 注释来注入适当的 bean 或引用 bean names 通过其静态 String 字段。@HttpClientSampler@HttpServerSamplerNAMEspring-doc.cn

查看 Brave 的代码,查看如何制作基于路径的采样器的示例 github.com/openzipkin/brave/tree/master/instrumentation/http#sampling-policyspring-doc.cn

如果要完全重写 Bean,可以使用该接口检索不应采样的 span 的 URL。下面你可以看到 在服务器端 .HttpTracingSkipPatternProviderPatternSkipPatternProviderSampler<HttpRequest>spring-doc.cn

@Configuration
class Config {
  @Bean(name = HttpServerSampler.NAME)
  SamplerFunction<HttpRequest> myHttpSampler(SkipPatternProvider provider) {
      Pattern pattern = provider.skipPattern();
      return request -> {
          String url = request.path();
          boolean shouldSkip = pattern.matcher(url).matches();
          if (shouldSkip) {
              return false;
          }
          return null;
      };
  }
}

12.4. TracingFilter

您还可以修改 的行为,该组件负责处理输入 HTTP 请求并根据 HTTP 响应添加标记。 您可以通过注册自己的 Bean 实例来自定义标记或修改响应标头。TracingFilterTracingFilterspring-doc.cn

在以下示例中,我们注册 Bean,添加包含当前 Span 的跟踪 ID 的响应标头,并向 span 添加带有 key 和 value 的标签。TracingFilterZIPKIN-TRACE-IDcustomtagspring-doc.cn

@Component
@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1)
class MyFilter extends GenericFilterBean {

    private final Tracer tracer;

    MyFilter(Tracer tracer) {
        this.tracer = tracer;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        Span currentSpan = this.tracer.currentSpan();
        if (currentSpan == null) {
            chain.doFilter(request, response);
            return;
        }
        // for readability we're returning trace id in a hex form
        ((HttpServletResponse) response).addHeader("ZIPKIN-TRACE-ID",
                currentSpan.context().traceIdString());
        // we can also add some custom tags
        currentSpan.tag("custom", "tag");
        chain.doFilter(request, response);
    }

}

12.5. 消息传递

Sleuth 会自动配置一个 bean,该 bean 充当 消息收发工具(如 Kafka 或 JMS)的基础。MessagingTracingspring-doc.cn

如果需要自定义消息收发跟踪的生产者/使用者采样, 只需注册一个 Bean 类型为 并且 为 Producer Sampler 和 Consumer Sampler 命名 Bean。brave.sampler.SamplerFunction<MessagingRequest>sleuthProducerSamplersleuthConsumerSamplerspring-doc.cn

为方便起见,可以使用 and 注释来注入适当的 bean 或引用 bean names 通过其静态 String 字段。@ProducerSampler@ConsumerSamplerNAMEspring-doc.cn

前任。下面是一个每秒跟踪 100 个使用者请求的采样器,除了 “alerts” 频道。其他请求将使用组件提供的全局速率。Tracingspring-doc.cn

@Configuration
class Config {
}

12.5.1. 自定义消息传递 span

为了更改默认的 span 名称和标签,只需注册一个 bean 类型的 .您还可以 override the existing 以扩展 existing 行为。MessageSpanCustomizerDefaultMessageSpanCustomizerspring-doc.cn

@Component
  class MyMessageSpanCustomizer extends DefaultMessageSpanCustomizer {
      @Override
      public SpanCustomizer customizeHandle(SpanCustomizer spanCustomizer,
              Message<?> message, MessageChannel messageChannel) {
          return super.customizeHandle(spanCustomizer, message, messageChannel)
                  .name("changedHandle")
                  .tag("handleKey", "handleValue")
                  .tag("channelName", channelName(messageChannel));
      }

      @Override
      public SpanCustomizer customizeSend(SpanCustomizer spanCustomizer,
              Message<?> message, MessageChannel messageChannel) {
          return super.customizeSend(spanCustomizer, message, messageChannel)
                  .name("changedSend")
                  .tag("sendKey", "sendValue")
                  .tag("channelName", channelName(messageChannel));
      }
  }

12.6. RPC

Sleuth 会自动配置一个 bean,该 bean 充当 为 gRPC 或 Dubbo 等 RPC 插桩奠定基础。RpcTracingspring-doc.cn

如果需要自定义 RPC 跟踪的客户端/服务器采样, 只需注册一个 Bean 类型为 并且 为 Client Sampler 和 Server Sampler 命名 Bean。brave.sampler.SamplerFunction<RpcRequest>sleuthRpcClientSamplersleuthRpcServerSamplerspring-doc.cn

为方便起见,可以使用 and 注释来注入适当的 bean 或引用 bean names 通过其静态 String 字段。@RpcClientSampler@RpcServerSamplerNAMEspring-doc.cn

前任。下面是一个每秒跟踪 100 个“GetUserToken”服务器请求的采样器。 这不会为运行状况检查服务的请求启动新的跟踪。其他 请求将使用全局采样配置。spring-doc.cn

@Configuration
class Config {
  @Bean(name = RpcServerSampler.NAME)
  SamplerFunction<RpcRequest> myRpcSampler() {
      Matcher<RpcRequest> userAuth = and(serviceEquals("users.UserService"),
              methodEquals("GetUserToken"));
      return RpcRuleSampler.newBuilder()
              .putRule(serviceEquals("grpc.health.v1.Health"), Sampler.NEVER_SAMPLE)
              .putRule(userAuth, RateLimitingSampler.create(100)).build();
  }
}

12.7. 自定义服务名称

默认情况下,Sleuth 假定当您将 span 发送到 Zipkin 时,您希望 span 的服务名称等于属性的值。 不过,情况并非总是如此。 在某些情况下,您希望为来自应用程序的所有 span 显式提供不同的服务名称。 为此,您可以将以下属性传递给应用程序以覆盖该值(该示例适用于名为 ):spring.application.namemyServicespring-doc.cn

spring.zipkin.service.name: myService

12.8. 自定义报告的 Span

在报告 span (例如,向 Zipkin) 报告之前,您可能希望以某种方式修改该 span。 您可以通过实施 .SpanHandlerspring-doc.cn

在 Sleuth 中,我们生成具有固定名称的 span。 一些用户希望根据标签的值修改名称。 您可以实现该接口来更改该名称。SpanHandlerspring-doc.cn

以下示例显示如何注册两个实现:SpanHandlerspring-doc.cn

@Bean
SpanHandler handlerOne() {
    return new SpanHandler() {
        @Override
        public boolean end(TraceContext traceContext, MutableSpan span,
                Cause cause) {
            span.name("foo");
            return true; // keep this span
        }
    };
}

@Bean
SpanHandler handlerTwo() {
    return new SpanHandler() {
        @Override
        public boolean end(TraceContext traceContext, MutableSpan span,
                Cause cause) {
            span.name(span.name() + " bar");
            return true; // keep this span
        }
    };
}

前面的示例导致在报告之前将报告的 span 的名称更改为 , (例如,更改为 Zipkin)。foo barspring-doc.cn

12.9. 主机定位器

本节介绍如何从服务发现定义主机。 它不是通过服务发现来查找 Zipkin。

要定义与特定 span 对应的主机,我们需要解析主机名和端口。 默认方法是从 server 属性中获取这些值。 如果未设置,我们将尝试从网络接口中检索主机名。spring-doc.cn

如果您启用了发现客户端,并且希望从服务注册表中注册的实例中检索主机地址,则必须设置该属性(它适用于基于 HTTP 和基于 Stream 的跨度报告),如下所示:spring.zipkin.locator.discovery.enabledspring-doc.cn

spring.zipkin.locator.discovery.enabled: true