首页 > 解决方案 > Spring Sleuth 升级并添加自定义跟踪 ID

问题描述

我一直在尝试将我的 Spring Cloud Sleuth 从版本 1.3.3-Release 升级到 2.2.0-Release。我们使用的 HTTPSpanInjector 和 HTTPSpanExtractor 已被弃用。我已经粘贴了需要升级的当前代码

我有一个名为 Tracing Handler 的类

/**
 * 
 */

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanTextMap;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.web.HttpSpanExtractor;
import org.springframework.cloud.sleuth.instrument.web.HttpSpanInjector;
import org.springframework.cloud.sleuth.instrument.web.ZipkinHttpSpanInjector;
import org.springframework.cloud.sleuth.util.TextMapUtil;
import org.springframework.web.filter.GenericFilterBean;

/**
 * 
 *
 */
public final class TracingHandler {

    public static final String TRACE_HEADER_NAME = "X-Pep-TraceId";
    public static final String SPAN_HEADER_NAME = "X-Pep-SpanId";

    public static class CustomHttpSpanExtractor implements HttpSpanExtractor {

        @Override
        public Span joinTrace(SpanTextMap carrier) {
            Map<String, String> map = TextMapUtil.asMap(carrier);
            String traceIdStr = map.get(TRACE_HEADER_NAME);
            String spanIdStr = map.get(SPAN_HEADER_NAME);

            Long traceId = null;
            Long spanId = null;
            if (!StringUtils.isBlank(traceIdStr)) {
                traceId = Span.hexToId(traceIdStr);
            }
            if (!StringUtils.isBlank(spanIdStr)) {
                spanId = Span.hexToId(spanIdStr);
            }

            Span.SpanBuilder builder = Span.builder();
            if (traceId != null) {
                builder.traceId(traceId);
            }
            if (spanId != null) {
                builder.spanId(spanId);
            }

            return builder.build();
        }
    }

    public static class CustomHttpSpanInjector implements HttpSpanInjector {

        @Override
        public void inject(Span span, SpanTextMap carrier) {
            carrier.put(TRACE_HEADER_NAME, span.traceIdString());
            carrier.put(SPAN_HEADER_NAME, Span.idToHex(span.getSpanId()));
        }
    }

    static class CustomHttpServletResponseSpanInjector extends ZipkinHttpSpanInjector {

        @Override
        public void inject(Span span, SpanTextMap carrier) {
            super.inject(span, carrier);
            carrier.put(Span.TRACE_ID_NAME, span.traceIdString());
            carrier.put(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
        }
    }

    public static class HttpResponseInjectingTraceFilter extends GenericFilterBean {

        private final Tracer tracer;
        private final HttpSpanInjector spanInjector;

        public HttpResponseInjectingTraceFilter(Tracer tracer, HttpSpanInjector spanInjector) {
            this.tracer = tracer;
            this.spanInjector = spanInjector;
        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            Span currentSpan = this.tracer.getCurrentSpan();
            this.spanInjector.inject(currentSpan, new HttpServletResponseTextMap(response));
            filterChain.doFilter(request, response);
        }

        class HttpServletResponseTextMap implements SpanTextMap {

            private final HttpServletResponse delegate;

            HttpServletResponseTextMap(HttpServletResponse delegate) {
                this.delegate = delegate;
            }

            @Override
            public Iterator<Map.Entry<String, String>> iterator() {
                Map<String, String> map = new HashMap<>();
                for (String header : this.delegate.getHeaderNames()) {
                    map.put(header, this.delegate.getHeader(header));
                }
                return map.entrySet().iterator();
            }

            @Override
            public void put(String key, String value) {
                this.delegate.addHeader(key, value);
            }
        }
    }

    /* As this class is supposed to be a config. class, there's no need to allow consumers to create an object for this class */
    private TracingHandler() {}
}

我们在网关微服务中添加跨度,其他微服务只有这样的 bean 定义

@Bean
public HttpSpanInjector customHttpSpanInjector() {
    return new TracingHandler.CustomHttpSpanInjector();
}

@Bean
public HttpSpanExtractor customHttpSpanExtractor() {
    return new TracingHandler.CustomHttpSpanExtractor();
}

@Bean
public HttpResponseInjectingTraceFilter responseInjectingTraceFilter(Tracer tracer) {
    return new HttpResponseInjectingTraceFilter(tracer, customHttpSpanInjector());
}

如何升级到 Spring-Cloud-Sleuth 2.2-Release 并实现相同的功能

标签: spring-cloudspring-cloud-sleuthzipkin

解决方案


推荐阅读