Доступ проекта SpringCloud к Jaeger (ниже)

Spring Cloud

1. Последний обзор

В предыдущей статье, когда мы сдалисьspring-cloud-sleuthЭтот компонент сталкивается с двумя проблемами. Во-первых, информация о ссылке, такая как traceId и spanId, не может отображаться в журнале, а во-вторых, ее нельзя использовать.spring-cloud-sleuthПредоставленный метод выполняет передачу значения ссылки. Теперь давайте решим эти две задачи.Предыдущий отзыв

2. В журнале отображается traceId

spring-cloud-sleuthзаключается в хранении информации о ссылке, такой как traceId, вslf4jВ MDC (сопоставленные диагностические контексты), а затем извлеките traceId с помощью %X{traceId}, например, формат по умолчанию, выводимый на консоль, следующий:

%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(%5p [${spring.application.name:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}

opentracingпредоставлено вThreadLocalScopeManagerЭтот класс управляет Span в контексте вызова, и мы можем наследовать от этого класса, чтобы установить traceId в MDC.

public class MDCScopeManager extends ThreadLocalScopeManager {

    @Override
    public Scope activate(Span span, boolean finishOnClose) {
        return new ScopeWrapper(super.activate(span, finishOnClose));
    }

    @Override
    public Scope activate(Span span) {
        return new ScopeWrapper(super.activate(span));
    }

    private static class ScopeWrapper implements Scope {

        private final Scope scope;
        private final String previousTraceId;
        private final String previousSpanId;
        private final String previousParentSpanId;
        private final String previousSampled;

        ScopeWrapper(Scope scope) {
            this.scope = scope;
            this.previousTraceId = lookup("traceId");
            this.previousSpanId = lookup("spanId");
            this.previousParentSpanId = lookup("parentSpanId");
            this.previousSampled = lookup("traceSampled");

            JaegerSpanContext ctx = (JaegerSpanContext) scope.span().context();
            String traceId = ctx.getTraceId();
            String spanId = Long.toHexString(ctx.getSpanId());
            String sampled = String.valueOf(ctx.isSampled());
            String parentSpanId = Long.toHexString(ctx.getParentId());

            replace("traceId", traceId);
            replace("spanId", spanId);
            replace("parentSpanId", parentSpanId);
            replace("traceSampled", sampled);
        }

        @Override
        public void close() {
            this.scope.close();
            replace("traceId", previousTraceId);
            replace("spanId", previousSpanId);
            replace("parentSpanId", previousParentSpanId);
            replace("traceSampled", previousSampled);
        }

        @Override
        public Span span() {
            return this.scope.span();
        }
    }

    private static String lookup(String key) {
        return MDC.get(key);
    }

    private static void replace(String key, String value) {
        if (value == null) {
            MDC.remove(key);
        } else {
            MDC.put(key, value);
        }
    }
}

Тогда этот класс определяется как bean, поэтому вы можете связать его с текущим трассером, чтобы пойти:

@Bean
public TracerBuilderCustomizer mdcBuilderCustomizer() {
		return builder -> builder.withScopeManager(new MDCScopeManager());
}

затем используйте%X{traceId}Таким образом задается формат печати, а вывод можно увидеть в консоли после запуска программы:

image-20190620104412638

Это иspring-cloud-sleuthПредоставляется таким же образом

3. Передача ценности между сервисами

opentracingЭлемент багажа предусмотрен для сквозной передачи кв, мы можем использовать багаж для передачи значения, которое нам нужно передать. (Примечание: в то же время он также будет генерировать огромные накладные расходы, пожалуйста, используйте эту функцию осторожно)

public class TraceContext {

    public static void setField(String key, String value) {
        if (GlobalTracer.isRegistered() && StringUtils.isNotBlank(key) && StringUtils.isNotBlank(value)) {
            Tracer tracer = GlobalTracer.get();
            tracer.activeSpan().setBaggageItem(key, value);
        }
    }

    public static String getFiled(String key, String defaultValue) {
        if (GlobalTracer.isRegistered() && StringUtils.isNotBlank(key)) {
            Tracer tracer = GlobalTracer.get();
            return tracer.activeSpan().getBaggageItem(key);
        }
        return defaultValue;
    }

}

4. Трассировка в многопоточности

Требуются зависимости в проектеopentracing-concurrent:

<dependency>
    <groupId>io.opentracing.contrib</groupId>
    <artifactId>opentracing-concurrent</artifactId>
    <version>0.4.0</version>
</dependency>

Тогда вы можете пройтиTraceRunnableсоздать поток с трассировкой

new Thread(new TracedRunnable(() -> {
	//线程中干活....
	
}, GlobalTracer.get()));

Его также можно использовать в среде Spring.@Autowiredполучить трассировщик

@Autowired
private Tracer tracer;

image-20190620112043513