Java 应用通过 OpenTelemetry API 实现手动埋点( 八 )

在上面代码中我们首先获取当前上下文的 Span,然后创建一个名为 GET /api/userinfo 的 span,将其设置为当前上下文的子 span,并将上下文切换到当前子 span,然后执行我们的业务逻辑,最后结束子 span 。
【Java 应用通过 OpenTelemetry API 实现手动埋点】然后我们可以统一在 WebClient 中来注入 span context,这样当我们 Java 服务请求其他服务的时候就可以形成链路 。
// src/main/java/com/youdianzhishi/orderservice/config/WebClientConfig.javapackage com.youdianzhishi.orderservice.config;// ......@Configuration@Order(3)public class WebClientConfig {    @Autowired    private OpenTelemetry openTelemetry;    @Bean    public WebClient webClient() {        return WebClient.builder().filter(traceExchangeFilterFunction()).build();    }    @Bean    public ExchangeFilterFunction traceExchangeFilterFunction() {        return (clientRequest, next) -> {            // 获取当前上下文的 Span            Span currentSpan = Span.current();            Context context = Context.current().with(currentSpan);            // 创建新的请求头并添加跟踪信息            HttpHeaders newHeaders = new HttpHeaders();            newHeaders.putAll(clientRequest.headers());            TextMapSetter<HttpHeaders> setter = new TextMapSetter<HttpHeaders>() {                @Override                public void set(HttpHeaders carrier, String key, String value) {                    carrier.add(key, value);                }            };            // 将当前上下文的 Span 注入到请求头中            openTelemetry.getPropagators().getTextMapPropagator().inject(context, newHeaders, setter);            // 创建一个新的 ClientRequest 对象            ClientRequest newRequest = ClientRequest.from(clientRequest)                    .headers(headers -> headers.addAll(newHeaders))                    .build();            return next.exchange(newRequest);        };    }}在上面代码中我们为 WebClient 添加了一个名为 traceExchangeFilterFunction 的过滤器函数,在该函数中我们首先获取当前上下文的 Span,然后创建一个新的请求头并添加跟踪信息,最后将当前上下文的 Span 通过 Propagator 接口注入到请求头中,这样当我们请求其他服务的时候就可以形成链路了 。
现在我们重新启动容器,当我们访问订单列表后就可以看到 Jaeger UI 中多了一个 GET /api/userinfo 的 span 了,并且该 span 和还会和 user-service 服务的 span 关联起来 。


Java 应用通过 OpenTelemetry API 实现手动埋点

文章插图
同样的方式我们还可以在 getAllOrders 处理器中添加数据库查询的 span,代码如下所示:
// 新建一个 DB 查询的 spanSpan dbSpan = tracer.spanBuilder("DB findByUserIdOrderByOrderDateDesc").setParent(context).startSpan();// 要根据 orderDate 倒序排列List<Order> orders = orderRepository.findByUserIdOrderByOrderDateDesc(user.getId());dbSpan.addEvent("OrderRepository findByUserIdOrderByOrderDateDesc From DB");dbSpan.setAttribute("order_count", orders.size());dbSpan.end();


推荐阅读