diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/SleuthProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/SleuthProperties.java new file mode 100644 index 0000000000..57036095a4 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/SleuthProperties.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2015 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.autoconfig; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Sleuth settings + * + * @since 1.0.11 + */ +@ConfigurationProperties("spring.sleuth") +public class SleuthProperties { + /** When true, generate 128-bit trace IDs instead of 64-bit ones. */ + private boolean traceId128 = false; + + public boolean isTraceId128() { + return this.traceId128; + } + + public void setTraceId128(boolean traceId128) { + this.traceId128 = traceId128; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java index 579f81f5b8..e4a5fcf545 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java @@ -18,6 +18,7 @@ import java.util.Random; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -44,8 +45,10 @@ */ @Configuration @ConditionalOnProperty(value="spring.sleuth.enabled", matchIfMissing=true) -@EnableConfigurationProperties(TraceKeys.class) +@EnableConfigurationProperties({TraceKeys.class, SleuthProperties.class}) public class TraceAutoConfiguration { + @Autowired + SleuthProperties properties; @Bean @ConditionalOnMissingBean @@ -65,7 +68,7 @@ public DefaultTracer sleuthTracer(Sampler sampler, Random random, SpanNamer spanNamer, SpanLogger spanLogger, SpanReporter spanReporter) { return new DefaultTracer(sampler, random, spanNamer, spanLogger, - spanReporter); + spanReporter, this.properties.isTraceId128()); } @Bean diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTracer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTracer.java index 56bb4cefe1..c7337e4aaf 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTracer.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTracer.java @@ -18,7 +18,6 @@ import java.util.Random; import java.util.concurrent.Callable; - import org.springframework.cloud.sleuth.Sampler; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.SpanNamer; @@ -47,13 +46,21 @@ public class DefaultTracer implements Tracer { private final SpanReporter spanReporter; + private final boolean traceId128; + public DefaultTracer(Sampler defaultSampler, Random random, SpanNamer spanNamer, SpanLogger spanLogger, SpanReporter spanReporter) { + this(defaultSampler, random, spanNamer, spanLogger, spanReporter, false); + } + + public DefaultTracer(Sampler defaultSampler, Random random, SpanNamer spanNamer, + SpanLogger spanLogger, SpanReporter spanReporter, boolean traceId128) { this.defaultSampler = defaultSampler; this.random = random; this.spanNamer = spanNamer; this.spanLogger = spanLogger; this.spanReporter = spanReporter; + this.traceId128 = traceId128; } @Override @@ -77,12 +84,14 @@ public Span createSpan(String name, Sampler sampler) { } else { long id = createId(); - span = Span.builder().name(name).traceId(id) + span = Span.builder().name(name) + .traceIdHigh(this.traceId128 ? createId() : 0L) + .traceId(id) .spanId(id).build(); - if (sampler==null) { + if (sampler == null) { sampler = this.defaultSampler; } - span = sampledSpan(name, id, span, sampler); + span = sampledSpan(span, sampler); this.spanLogger.logStartedSpan(null, span); } return continueSpan(span); @@ -142,8 +151,10 @@ Span createChild(Span parent, String name) { long id = createId(); if (parent == null) { Span span = Span.builder().name(name) - .traceId(id).spanId(id).build(); - span = sampledSpan(name, id, span, this.defaultSampler); + .traceIdHigh(this.traceId128 ? createId() : 0L) + .traceId(id) + .spanId(id).build(); + span = sampledSpan(span, this.defaultSampler); this.spanLogger.logStartedSpan(null, span); return span; } @@ -152,6 +163,7 @@ Span createChild(Span parent, String name) { SpanContextHolder.push(parent, true); } Span span = Span.builder().name(name) + .traceIdHigh(parent.getTraceIdHigh()) .traceId(parent.getTraceId()).parent(parent.getSpanId()).spanId(id) .processId(parent.getProcessId()).savedSpan(parent) .exportable(parent.isExportable()) @@ -162,11 +174,16 @@ Span createChild(Span parent, String name) { } } - private Span sampledSpan(String name, long id, Span span, Sampler sampler) { + private Span sampledSpan(Span span, Sampler sampler) { if (!sampler.isSampled(span)) { - // Non-exportable so we keep the trace but not other data - return Span.builder().begin(span.getBegin()).name(name).traceId(id) - .spanId(id).exportable(false).build(); + // Copy everything, except set exportable to false + return Span.builder() + .begin(span.getBegin()) + .traceIdHigh(span.getTraceIdHigh()) + .traceId(span.getTraceId()) + .spanId(span.getSpanId()) + .name(span.getName()) + .exportable(false).build(); } return span; } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationTest.java new file mode 100644 index 0000000000..b0dfe97d20 --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationTest.java @@ -0,0 +1,82 @@ +/** + * Copyright 2015-2016 The OpenZipkin 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.autoconfig; + +import org.junit.After; +import org.junit.Test; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.Tracer; +import org.springframework.cloud.sleuth.log.SleuthLogAutoConfiguration; +import org.springframework.cloud.sleuth.sampler.NeverSampler; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.boot.test.util.EnvironmentTestUtils.addEnvironment; + +public class TraceAutoConfigurationTest { + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + + @After + public void close() { + context.close(); + } + + @Test + public void defaultsTo64BitTraceId() { + context = new AnnotationConfigApplicationContext(); + context.register( + PropertyPlaceholderAutoConfiguration.class, + SleuthLogAutoConfiguration.class, + TraceAutoConfiguration.class + ); + context.refresh(); + Tracer tracer = context.getBean(Tracer.class); + + Span span = null; + try { + span = tracer.createSpan("foo", NeverSampler.INSTANCE); + assertThat(span.getTraceIdHigh()).isEqualTo(0L); + assertThat(span.getTraceId()).isNotEqualTo(0L); + } finally { + if (span != null){ + tracer.close(span); + } + } + } + + @Test + public void optInto128BitTraceId() { + addEnvironment(context, "spring.sleuth.traceId128:true"); + context.register( + PropertyPlaceholderAutoConfiguration.class, + SleuthLogAutoConfiguration.class, + TraceAutoConfiguration.class + ); + context.refresh(); + Tracer tracer = context.getBean(Tracer.class); + + Span span = null; + try { + span = tracer.createSpan("foo", NeverSampler.INSTANCE); + assertThat(span.getTraceIdHigh()).isNotEqualTo(0L); + assertThat(span.getTraceId()).isNotEqualTo(0L); + } finally { + if (span != null){ + tracer.close(span); + } + } + } +}