committed by
GitHub
parent
c5e043af71
commit
5b6a4f2767
@@ -23,11 +23,11 @@ import brave.CurrentSpanCustomizer;
|
||||
import brave.ErrorParser;
|
||||
import brave.Tracer;
|
||||
import brave.Tracing;
|
||||
import brave.context.log4j2.ThreadContextCurrentTraceContext;
|
||||
import brave.propagation.B3Propagation;
|
||||
import brave.propagation.CurrentTraceContext;
|
||||
import brave.propagation.ExtraFieldPropagation;
|
||||
import brave.propagation.Propagation;
|
||||
import brave.propagation.ThreadLocalCurrentTraceContext;
|
||||
import brave.sampler.Sampler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -58,6 +58,7 @@ public class TraceAutoConfiguration {
|
||||
public static final String TRACER_BEAN_NAME = "tracer";
|
||||
|
||||
@Autowired(required = false) List<SpanAdjuster> spanAdjusters = new ArrayList<>();
|
||||
@Autowired(required = false) List<CurrentTraceContext.ScopeDecorator> scopeDecorators = new ArrayList<>();
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@@ -132,10 +133,18 @@ public class TraceAutoConfiguration {
|
||||
return factoryBuilder.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
CurrentTraceContext currentTraceContext(CurrentTraceContext.Builder builder) {
|
||||
for (CurrentTraceContext.ScopeDecorator scopeDecorator : this.scopeDecorators) {
|
||||
builder.addScopeDecorator(scopeDecorator);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
CurrentTraceContext sleuthCurrentTraceContext() {
|
||||
return ThreadContextCurrentTraceContext.create();
|
||||
CurrentTraceContext.Builder sleuthCurrentTraceContextBuilder() {
|
||||
return ThreadLocalCurrentTraceContext.newBuilder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -18,12 +18,8 @@ package org.springframework.cloud.sleuth.log;
|
||||
|
||||
import brave.propagation.CurrentTraceContext;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
|
||||
@@ -51,32 +47,8 @@ public class SleuthLogAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "spring.sleuth.log.slf4j.enabled", matchIfMissing = true)
|
||||
@ConditionalOnMissingBean
|
||||
public CurrentTraceContext slf4jSpanLogger() {
|
||||
return Slf4jCurrentTraceContext.create();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "spring.sleuth.log.slf4j.enabled", matchIfMissing = true)
|
||||
@ConditionalOnBean(CurrentTraceContext.class)
|
||||
public static BeanPostProcessor slf4jSpanLoggerBPP() {
|
||||
return new Slf4jBeanPostProcessor();
|
||||
}
|
||||
|
||||
static class Slf4jBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
@Override public Object postProcessBeforeInitialization(Object bean,
|
||||
String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override public Object postProcessAfterInitialization(Object bean,
|
||||
String beanName) throws BeansException {
|
||||
if (bean instanceof CurrentTraceContext && !(bean instanceof Slf4jCurrentTraceContext)) {
|
||||
return Slf4jCurrentTraceContext.create((CurrentTraceContext) bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
public CurrentTraceContext.ScopeDecorator slf4jSpanDecorator() {
|
||||
return new Slf4jScopeDecorator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,16 @@ import org.slf4j.MDC;
|
||||
* Supports backward compatibility of MDC entries by adding legacy "X-B3" entries to MDC context
|
||||
* "X-B3-TraceId", "X-B3-ParentSpanId", "X-B3-SpanId" and "X-B3-Sampled"
|
||||
*
|
||||
* Due to the migration to {@link brave.propagation.CurrentTraceContext.ScopeDecorator} approach,
|
||||
* we are making the default implementation package scope since you can register your
|
||||
* own implementation of the Scope Decorator.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @deprecated {@link Slf4jScopeDecorator} will be used
|
||||
*/
|
||||
@Deprecated
|
||||
public final class Slf4jCurrentTraceContext extends CurrentTraceContext {
|
||||
|
||||
// Backward compatibility for all logging patterns
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.log;
|
||||
|
||||
import brave.internal.HexCodec;
|
||||
import brave.internal.Nullable;
|
||||
import brave.propagation.CurrentTraceContext;
|
||||
import brave.propagation.TraceContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
/**
|
||||
* Adds {@linkplain MDC} properties "traceId", "parentId", "spanId" and "spanExportable" when a {@link
|
||||
* brave.Tracer#currentSpan() span is current}. These can be used in log correlation.
|
||||
* Supports backward compatibility of MDC entries by adding legacy "X-B3" entries to MDC context
|
||||
* "X-B3-TraceId", "X-B3-ParentSpanId", "X-B3-SpanId" and "X-B3-Sampled"
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 2.1.0
|
||||
*/
|
||||
final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator {
|
||||
|
||||
// Backward compatibility for all logging patterns
|
||||
private static final String LEGACY_EXPORTABLE_NAME = "X-Span-Export";
|
||||
private static final String LEGACY_PARENT_ID_NAME = "X-B3-ParentSpanId";
|
||||
private static final String LEGACY_TRACE_ID_NAME = "X-B3-TraceId";
|
||||
private static final String LEGACY_SPAN_ID_NAME = "X-B3-SpanId";
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Slf4jScopeDecorator.class);
|
||||
|
||||
@Override public CurrentTraceContext.Scope decorateScope(TraceContext currentSpan,
|
||||
CurrentTraceContext.Scope scope) {
|
||||
final String previousTraceId = MDC.get("traceId");
|
||||
final String previousParentId = MDC.get("parentId");
|
||||
final String previousSpanId = MDC.get("spanId");
|
||||
final String spanExportable = MDC.get("spanExportable");
|
||||
final String legacyPreviousTraceId = MDC.get(LEGACY_TRACE_ID_NAME);
|
||||
final String legacyPreviousParentId = MDC.get(LEGACY_PARENT_ID_NAME);
|
||||
final String legacyPreviousSpanId = MDC.get(LEGACY_SPAN_ID_NAME);
|
||||
final String legacySpanExportable = MDC.get(LEGACY_EXPORTABLE_NAME);
|
||||
|
||||
if (currentSpan != null) {
|
||||
String traceIdString = currentSpan.traceIdString();
|
||||
MDC.put("traceId", traceIdString);
|
||||
MDC.put(LEGACY_TRACE_ID_NAME, traceIdString);
|
||||
String parentId = currentSpan.parentId() != null ?
|
||||
HexCodec.toLowerHex(currentSpan.parentId()) :
|
||||
null;
|
||||
replace("parentId", parentId);
|
||||
replace(LEGACY_PARENT_ID_NAME, parentId);
|
||||
String spanId = HexCodec.toLowerHex(currentSpan.spanId());
|
||||
MDC.put("spanId", spanId);
|
||||
MDC.put(LEGACY_SPAN_ID_NAME, spanId);
|
||||
String sampled = String.valueOf(currentSpan.sampled());
|
||||
MDC.put("spanExportable", sampled);
|
||||
MDC.put(LEGACY_EXPORTABLE_NAME, sampled);
|
||||
log("Starting scope for span: {}", currentSpan);
|
||||
if (currentSpan.parentId() != null) {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("With parent: {}", currentSpan.parentId());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
MDC.remove("traceId");
|
||||
MDC.remove("parentId");
|
||||
MDC.remove("spanId");
|
||||
MDC.remove("spanExportable");
|
||||
MDC.remove(LEGACY_TRACE_ID_NAME);
|
||||
MDC.remove(LEGACY_PARENT_ID_NAME);
|
||||
MDC.remove(LEGACY_SPAN_ID_NAME);
|
||||
MDC.remove(LEGACY_EXPORTABLE_NAME);
|
||||
}
|
||||
|
||||
class ThreadContextCurrentTraceContextScope implements CurrentTraceContext.Scope {
|
||||
@Override public void close() {
|
||||
log("Closing scope for span: {}", currentSpan);
|
||||
scope.close();
|
||||
replace("traceId", previousTraceId);
|
||||
replace("parentId", previousParentId);
|
||||
replace("spanId", previousSpanId);
|
||||
replace("spanExportable", spanExportable);
|
||||
replace(LEGACY_TRACE_ID_NAME, legacyPreviousTraceId);
|
||||
replace(LEGACY_PARENT_ID_NAME, legacyPreviousParentId);
|
||||
replace(LEGACY_SPAN_ID_NAME, legacyPreviousSpanId);
|
||||
replace(LEGACY_EXPORTABLE_NAME, legacySpanExportable);
|
||||
}
|
||||
}
|
||||
return new ThreadContextCurrentTraceContextScope();
|
||||
}
|
||||
|
||||
private void log(String text, TraceContext span) {
|
||||
if (span == null) {
|
||||
return;
|
||||
}
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace(text, span);
|
||||
}
|
||||
}
|
||||
|
||||
static void replace(String key, @Nullable String value) {
|
||||
if (value != null) {
|
||||
MDC.put(key, value);
|
||||
}
|
||||
else {
|
||||
MDC.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,8 +40,7 @@ public class Slf4JSpanLoggerTest {
|
||||
.build();
|
||||
|
||||
Span span = this.tracing.tracer().nextSpan().name("span").start();
|
||||
Slf4jCurrentTraceContext slf4jCurrentTraceContext =
|
||||
new Slf4jCurrentTraceContext(new StrictCurrentTraceContext());
|
||||
Slf4jScopeDecorator slf4jScopeDecorator = new Slf4jScopeDecorator();
|
||||
|
||||
@Before
|
||||
@After
|
||||
@@ -51,7 +50,7 @@ public class Slf4JSpanLoggerTest {
|
||||
|
||||
@Test
|
||||
public void should_set_entries_to_mdc_from_span() throws Exception {
|
||||
Scope scope = this.slf4jCurrentTraceContext.newScope(this.span.context());
|
||||
Scope scope = this.slf4jScopeDecorator.decorateScope(this.span.context(), () -> { });
|
||||
|
||||
assertThat(MDC.get("X-B3-TraceId")).isEqualTo(span.context().traceIdString());
|
||||
assertThat(MDC.get("traceId")).isEqualTo(span.context().traceIdString());
|
||||
@@ -67,8 +66,7 @@ public class Slf4JSpanLoggerTest {
|
||||
MDC.put("X-B3-TraceId", "A");
|
||||
MDC.put("traceId", "A");
|
||||
|
||||
Scope scope = this.slf4jCurrentTraceContext
|
||||
.newScope(null);
|
||||
Scope scope = this.slf4jScopeDecorator.decorateScope(null, () -> { });
|
||||
|
||||
assertThat(MDC.get("X-B3-TraceId")).isNullOrEmpty();
|
||||
assertThat(MDC.get("traceId")).isNullOrEmpty();
|
||||
|
||||
Reference in New Issue
Block a user