Skip to content

Commit 62adab8

Browse files
Detect the presence of autoconfig for Brave, fail the context initialization if it present and let the user know that they need to pics one tracer. (#38)
1 parent 037fab7 commit 62adab8

File tree

24 files changed

+220
-14
lines changed

24 files changed

+220
-14
lines changed

docs/src/main/asciidoc/_configprops.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
|spring.sleuth.otel.exporter.sleuth-span-filter.enabled | `true` | Enables Sleuth span filter.
1818
|spring.sleuth.otel.log.exporter.enabled | `false` | Enable log exporter for OTel.
1919
|spring.sleuth.otel.log.slf4j.enabled | `false` | Enable slf4j support for OTel.
20+
|spring.sleuth.otel.multiple-tracer-configs-detector-enabled | `true` | Enable detection of autoconfiguration for multiple tracers (i.e.: Brave and OTel); only one of them should be used.
2021
|spring.sleuth.otel.propagation.composite-text-map-propagator.enabled | `true` | Enable a composite text map propagator that can combine multiple propagation types into a single text map propagator.
2122
|spring.sleuth.otel.propagation.sleuth-baggage.enabled | `true` | Enable propagating baggage in a Sleuth compatible way (baggage key & value pair means e.g. a key & value HTTP pair).
2223
|spring.sleuth.otel.resource.enabled | `true` | Enables default {@link Resource} implementations.

spring-cloud-sleuth-otel-autoconfigure/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,12 @@
321321
<version>${grpc-netty-shaded.version}</version>
322322
<scope>test</scope>
323323
</dependency>
324+
<dependency>
325+
<groupId>org.springframework.cloud</groupId>
326+
<artifactId>spring-cloud-sleuth-tests-otel-common</artifactId>
327+
<version>${project.version}</version>
328+
<scope>test</scope>
329+
</dependency>
324330
</dependencies>
325331

326332
<profiles>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2021-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.sleuth.autoconfig.otel;
18+
19+
import javax.annotation.PostConstruct;
20+
21+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
22+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
23+
import org.springframework.context.annotation.Configuration;
24+
25+
/**
26+
* Detects if both OTel (this project) and autoconfiguration for Brave are both on the
27+
* classpath.
28+
*
29+
* @author Jonatan Ivanov
30+
* @since 1.0.0
31+
*/
32+
@Configuration
33+
@ConditionalOnClass(name = "org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration")
34+
@ConditionalOnProperty(
35+
value = { "spring.sleuth.enabled", "spring.sleuth.otel.multiple-tracer-configs-detector-enabled" },
36+
matchIfMissing = true)
37+
class MultipleTracerAutoConfigurationsDetector {
38+
39+
@PostConstruct
40+
void signalMultipleTracerAutoConfigurationsPresent() {
41+
throw new MultipleTracersFoundException();
42+
}
43+
44+
static final class MultipleTracersFoundException extends RuntimeException {
45+
46+
MultipleTracersFoundException() {
47+
super("You have both Spring Cloud Sleuth OpenTelemetry (OTel) and Spring Cloud Sleuth Brave tracers on the "
48+
+ "classpath. Please exclude <org.springframework.cloud:spring-cloud-sleuth-brave> dependency from "
49+
+ "<org.springframework.cloud:spring-cloud-starter-sleuth>.");
50+
}
51+
52+
}
53+
54+
}

spring-cloud-sleuth-otel-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
{
22
"properties": [
3+
{
4+
"name": "spring.sleuth.otel.multiple-tracer-configs-detector-enabled",
5+
"type": "java.lang.Boolean",
6+
"description": "Enable detection of autoconfiguration for multiple tracers (i.e.: Brave and OTel); only one of them should be used.",
7+
"defaultValue": true
8+
},
39
{
410
"name": "spring.sleuth.otel.propagation.sleuth-baggage.enabled",
511
"type": "java.lang.Boolean",

spring-cloud-sleuth-otel-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Auto Configuration
22
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
33
org.springframework.cloud.sleuth.autoconfig.otel.OtelAutoConfiguration,\
4+
org.springframework.cloud.sleuth.autoconfig.otel.MultipleTracerAutoConfigurationsDetector,\
45
org.springframework.cloud.sleuth.autoconfig.otel.instrument.opentracing.OtelOpentracingAutoConfiguration,\
56
org.springframework.cloud.sleuth.autoconfig.otel.zipkin2.ZipkinOtelAutoConfiguration,\
67
org.springframework.cloud.sleuth.autoconfig.otel.wavefront.WavefrontOtelAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2021-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.sleuth.autoconfig.otel;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import org.springframework.boot.autoconfigure.AutoConfigurations;
22+
import org.springframework.boot.test.context.FilteredClassLoader;
23+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
24+
25+
import static org.assertj.core.api.Assertions.assertThat;
26+
27+
class MultipleTracerAutoConfigurationsDetectorTest {
28+
29+
@Test
30+
void should_fail_when_brave_and_otel_autoconfig_is_on_the_classpath() {
31+
new ApplicationContextRunner()
32+
.withConfiguration(AutoConfigurations.of(MultipleTracerAutoConfigurationsDetector.class))
33+
.run(context -> assertThat(context.getStartupFailure()).hasRootCauseInstanceOf(
34+
MultipleTracerAutoConfigurationsDetector.MultipleTracersFoundException.class));
35+
}
36+
37+
@Test
38+
void should_not_fail_when_brave_autoconfig_is_not_on_the_classpath() {
39+
new ApplicationContextRunner()
40+
.withClassLoader(new FilteredClassLoader(
41+
"org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration"))
42+
.withConfiguration(AutoConfigurations.of(MultipleTracerAutoConfigurationsDetector.class))
43+
.run(context -> assertThat(context).hasNotFailed());
44+
}
45+
46+
@Test
47+
void should_not_fail_when_sleuth_is_disabled() {
48+
new ApplicationContextRunner().withPropertyValues("spring.sleuth.enabled=false")
49+
.withConfiguration(AutoConfigurations.of(MultipleTracerAutoConfigurationsDetector.class))
50+
.run(context -> assertThat(context).hasNotFailed());
51+
}
52+
53+
@Test
54+
void should_not_fail_when_detector_is_disabled() {
55+
new ApplicationContextRunner()
56+
.withPropertyValues("spring.sleuth.otel.multiple-tracer-configs-detector-enabled=false")
57+
.withConfiguration(AutoConfigurations.of(MultipleTracerAutoConfigurationsDetector.class))
58+
.run(context -> assertThat(context).hasNotFailed());
59+
}
60+
61+
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
# Auto Configuration
22
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
3-
org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration
3+
org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration
4+
5+
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
6+
org.springframework.cloud.sleuth.autoconfig.otel.MultipleTracerAutoConfigurationsDetectorFilter

tests/common/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
</dependency>
6060
<dependency>
6161
<groupId>org.springframework.cloud</groupId>
62-
<artifactId>spring-cloud-sleuth-otel-autoconfigure</artifactId>
62+
<artifactId>spring-cloud-sleuth-otel</artifactId>
6363
</dependency>
6464
<dependency>
6565
<groupId>io.opentelemetry</groupId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2021-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.sleuth.autoconfig.otel;
18+
19+
import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
20+
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
21+
22+
/**
23+
* Filter that can be registered in {@code spring.factories} to exclude
24+
* MultipleTracerAutoConfigurationsDetector. This can be handy in tests where there is no
25+
* other way to disable the detector (e.g.: property or context runner).
26+
*
27+
* @author Jonatan Ivanov
28+
*/
29+
public class MultipleTracerAutoConfigurationsDetectorFilter implements AutoConfigurationImportFilter {
30+
31+
private static final String EXCLUDED = "org.springframework.cloud.sleuth.autoconfig.otel.MultipleTracerAutoConfigurationsDetector";
32+
33+
@Override
34+
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
35+
boolean[] matches = new boolean[autoConfigurationClasses.length];
36+
for (int i = 0; i < autoConfigurationClasses.length; i++) {
37+
matches[i] = isMatching(autoConfigurationClasses[i]);
38+
}
39+
40+
return matches;
41+
}
42+
43+
private boolean isMatching(String autoConfigurationClass) {
44+
return !EXCLUDED.equals(autoConfigurationClass);
45+
}
46+
47+
}

tests/otel/spring-cloud-sleuth-instrumentation-annotation-tests/src/test/resources/application.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ logging.level.org.springframework.cloud: DEBUG
22
logging.level.com.netflix.discovery.InstanceInfoReplicator: ERROR
33
logging.level.org.springframework.cloud.sleuth.brave.instrument.web.client.feign: TRACE
44

5-
spring.autoconfigure.exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration, org.springframework.cloud.gateway.config.GatewayAutoConfiguration, org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration, org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration
5+
spring.sleuth.otel.multiple-tracer-configs-detector-enabled: false
6+
7+
spring.autoconfigure.exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration, org.springframework.cloud.gateway.config.GatewayAutoConfiguration, org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration, org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration

0 commit comments

Comments
 (0)