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

,然后通过 extract 方法来解析 span context,然后将解析出来的 span context 设置为子 span 的父级 span,最后将 span context 存储在请求属性中,以便后续使用 。
这里的关键是在初始化 OpenTelemetry 的时候需要配置 ContextPropagators,代码如下所示:
// 初始化 ContextPropagators,这里我们配置包含 W3C Trace Context 和 W3C BaggageContextPropagators propagators = ContextPropagators.create(        TextMapPropagator.composite(                W3CTraceContextPropagator.getInstance(),                W3CBaggagePropagator.getInstance()));这样我们才能去解析 TraceContext 和 Baggage 两种上下文传播机制 。而其中的 getter 就是用来从 HTTP 请求头中获取 span context 的方式 。
当然最后我们还需要在 WebMvcConfig 中注册该拦截器,代码如下所示:
// src/main/java/com/youdianzhishi/orderservice/config/WebMvcConfig.javapackage com.youdianzhishi.orderservice.config;// ......@Configuration@Order(4)public class WebMvcConfig implements WebMvcConfigurer {    @Autowired    private TokenInterceptor tokenInterceptor;    @Autowired    private OpenTelemetryInterceptor otelCtxInterceptor;    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(otelCtxInterceptor)            .addPathPatterns("/api/orders/**");        registry.addInterceptor(tokenInterceptor)            .addPathPatterns("/api/orders/**") // 指定拦截器应该应用的路径模式            .excludePathPatterns("/api/login", "/api/register"); // 指定应该排除的路径模式    }}这样当我们在请求 /api/orders/** 下面的接口时,就可以从请求属性中获取父级的 span context 了 。
现在我们重新修改 getAllOrders 处理器,代码如下所示:
@GetMappingpublic ResponseEntity<List<OrderDto>> getAllOrders(HttpServletRequest request) {    // 从请求属性中获取 Span    Span span = (Span) request.getAttribute("currentSpan");    try {        // 从拦截器中获取用户信息        User user = (User) request.getAttribute("user");        // 要根据 orderDate 倒序排列        List<Order> orders = orderRepository.findByUserIdOrderByOrderDateDesc(user.getId());        // 将Order转换为OrderDto        List<OrderDto> orderDtos = orders.stream().map(order -> {            try {                return order.toOrderDto(webClient);            } catch (Exception e) {                throw new RuntimeException(e);            }        }).collect(Collectors.toList());        span.setAttribute("user_id", user.getId());        span.setAttribute("order_count", orders.size());        return new ResponseEntity<>(orderDtos, HttpStatus.OK);    } catch (Exception e) {        // 记录 Span 错误        span.recordException(e).setStatus(StatusCode.ERROR, e.getMessage());        return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);    } finally {        // 记录 Span 结束时间        span.end();    }}


推荐阅读