From 24e52c690d982622944a9ba520f9a6e243b5bf1e Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Fri, 18 Nov 2016 22:58:34 +0800 Subject: [PATCH] Starts 128-bit traces when spring.sleuth.traceId128=true (#455) (#456) This adds autoconfiguration to create 128-bit traces when `spring.sleuth.traceId128=true`. --- .../sleuth/autoconfig/SleuthProperties.java | 38 +++++++++ .../autoconfig/TraceAutoConfiguration.java | 7 +- .../cloud/sleuth/trace/DefaultTracer.java | 47 ++++++++--- .../TraceAutoConfigurationTest.java | 82 +++++++++++++++++++ 4 files changed, 160 insertions(+), 14 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/SleuthProperties.java create mode 100644 spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationTest.java 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 000000000..57036095a --- /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 579f81f5b..e4a5fcf54 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 @@ package org.springframework.cloud.sleuth.autoconfig; 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 @@ import org.springframework.context.annotation.Configuration; */ @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 class TraceAutoConfiguration { 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 360bde3f0..a1cb5edd0 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 @@ package org.springframework.cloud.sleuth.trace; 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; - public DefaultTracer(Sampler defaultSampler, Random random, SpanNamer spanNamer, SpanLogger spanLogger, - 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,11 +84,14 @@ public class DefaultTracer implements Tracer { } else { long id = createId(); - span = Span.builder().name(name).traceId(id).spanId(id).build(); + span = Span.builder().name(name) + .traceIdHigh(this.traceId128 ? createId() : 0L) + .traceId(id) + .spanId(id).build(); if (sampler == null) { sampler = this.defaultSampler; } - span = sampledSpan(name, id, span, sampler); + span = sampledSpan(span, sampler); this.spanLogger.logStartedSpan(null, span); } return continueSpan(span); @@ -139,8 +149,11 @@ public class DefaultTracer implements Tracer { protected 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); + Span span = Span.builder().name(name) + .traceIdHigh(this.traceId128 ? createId() : 0L) + .traceId(id) + .spanId(id).build(); + span = sampledSpan(span, this.defaultSampler); this.spanLogger.logStartedSpan(null, span); return span; } @@ -148,17 +161,27 @@ public class DefaultTracer implements Tracer { if (!isTracing()) { SpanContextHolder.push(parent, true); } - Span span = Span.builder().name(name).traceId(parent.getTraceId()).parent(parent.getSpanId()).spanId(id) - .processId(parent.getProcessId()).savedSpan(parent).exportable(parent.isExportable()).build(); + 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()) + .build(); this.spanLogger.logStartedSpan(parent, span); return span; } } - 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 000000000..389760318 --- /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.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); + } + } + } +}