在上面代码中我们首先获取当前上下文的 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 关联起来 。
同样的方式我们还可以在 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();
推荐阅读
- 通过诗经楚辞取的公司名字
- 动量定理的应用 动量定理的应用视频讲解
- 深入浅出、玩转Java多线程
- 揭秘十个必知的 JavaScript 3D 库,打造顶级3D炫酷效果!
- 图灵测试已死!ChatGPT通过人类考试也不算,超强AI评估新秀「逻辑谜题」
- 王者荣耀的段位排行榜是通过Redis实现的?
- 我不再写Javascript了
- Java 单元测试及常用语句
- 构建高效的Java网络应用,体验秒级响应
- 谷歌推出 AlloyDB AI,帮助开发者创建生成式 AI 应用