Skip to content

Commit 92fef40

Browse files
committed
Reuse registered global OpenTelemetry
Spring Boot instrumentation will be included when applications are running with OpenTelemetry Java Agent. Signed-off-by: Yanming Zhou <[email protected]>
1 parent b6b570e commit 92fef40

File tree

5 files changed

+63
-0
lines changed

5 files changed

+63
-0
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryAutoConfiguration.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.opentelemetry;
1818

19+
import io.opentelemetry.api.GlobalOpenTelemetry;
1920
import io.opentelemetry.api.OpenTelemetry;
2021
import io.opentelemetry.context.propagation.ContextPropagators;
2122
import io.opentelemetry.sdk.OpenTelemetrySdk;
@@ -29,23 +30,37 @@
2930
import org.springframework.beans.factory.ObjectProvider;
3031
import org.springframework.boot.autoconfigure.AutoConfiguration;
3132
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
33+
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
34+
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
3235
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3336
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
37+
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
3438
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3539
import org.springframework.context.annotation.Bean;
40+
import org.springframework.context.annotation.ConditionContext;
41+
import org.springframework.context.annotation.Conditional;
3642
import org.springframework.core.env.Environment;
43+
import org.springframework.core.type.AnnotatedTypeMetadata;
3744

3845
/**
3946
* {@link EnableAutoConfiguration Auto-configuration} for OpenTelemetry.
4047
*
4148
* @author Moritz Halbritter
49+
* @author Yanming Zhou
4250
* @since 3.2.0
4351
*/
4452
@AutoConfiguration
4553
@ConditionalOnClass(OpenTelemetrySdk.class)
4654
@EnableConfigurationProperties(OpenTelemetryProperties.class)
4755
public class OpenTelemetryAutoConfiguration {
4856

57+
@Bean
58+
@ConditionalOnMissingBean(OpenTelemetry.class)
59+
@Conditional(OnRegisteredGlobalOpenTelemetryCondition.class)
60+
OpenTelemetry globalOpenTelemetry() {
61+
return GlobalOpenTelemetry.get();
62+
}
63+
4964
@Bean
5065
@ConditionalOnMissingBean(OpenTelemetry.class)
5166
OpenTelemetrySdk openTelemetry(ObjectProvider<SdkTracerProvider> tracerProvider,
@@ -72,4 +87,15 @@ private Resource toResource(Environment environment, OpenTelemetryProperties pro
7287
return builder.build();
7388
}
7489

90+
static class OnRegisteredGlobalOpenTelemetryCondition extends SpringBootCondition {
91+
92+
@Override
93+
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
94+
boolean globalOpenTelemetryRegistered = GlobalOpenTelemetry.get() != OpenTelemetry.noop();
95+
return new ConditionOutcome(globalOpenTelemetryRegistered, ConditionMessage
96+
.of("GlobalOpenTelemetry is" + (globalOpenTelemetryRegistered ? "not" : "") + " NOOP"));
97+
}
98+
99+
}
100+
75101
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryAutoConfigurationTests.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.opentelemetry;
1818

19+
import io.opentelemetry.api.GlobalOpenTelemetry;
1920
import io.opentelemetry.api.OpenTelemetry;
2021
import io.opentelemetry.api.common.AttributeKey;
22+
import io.opentelemetry.api.trace.Tracer;
23+
import io.opentelemetry.api.trace.TracerProvider;
2124
import io.opentelemetry.context.propagation.ContextPropagators;
2225
import io.opentelemetry.sdk.OpenTelemetrySdk;
2326
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
2427
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
2528
import io.opentelemetry.sdk.resources.Resource;
2629
import io.opentelemetry.sdk.trace.SdkTracerProvider;
30+
import org.junit.jupiter.api.AfterEach;
2731
import org.junit.jupiter.api.Test;
2832

2933
import org.springframework.boot.autoconfigure.AutoConfiguration;
@@ -36,18 +40,26 @@
3640

3741
import static org.assertj.core.api.Assertions.assertThat;
3842
import static org.assertj.core.api.Assertions.entry;
43+
import static org.mockito.ArgumentMatchers.eq;
44+
import static org.mockito.BDDMockito.given;
3945
import static org.mockito.Mockito.mock;
4046

4147
/**
4248
* Tests for {@link OpenTelemetryAutoConfiguration}.
4349
*
4450
* @author Moritz Halbritter
51+
* @author Yanming Zhou
4552
*/
4653
class OpenTelemetryAutoConfigurationTests {
4754

4855
private final ApplicationContextRunner runner = new ApplicationContextRunner()
4956
.withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class));
5057

58+
@AfterEach
59+
void reset() {
60+
GlobalOpenTelemetry.resetForTest();
61+
}
62+
5163
@Test
5264
void isRegisteredInAutoConfigurationImports() {
5365
assertThat(ImportCandidates.load(AutoConfiguration.class, null).getCandidates())
@@ -62,6 +74,20 @@ void shouldProvideBeans() {
6274
});
6375
}
6476

77+
@Test
78+
void reuseRegisteredGlobalOpenTelemetry() {
79+
OpenTelemetry openTelemetry = mock(OpenTelemetry.class);
80+
TracerProvider tracerProvider = mock(TracerProvider.class);
81+
Tracer tracer = mock(Tracer.class);
82+
given(tracerProvider.get(eq("org.springframework.boot"))).willReturn(tracer);
83+
given(openTelemetry.getTracerProvider()).willReturn(tracerProvider);
84+
GlobalOpenTelemetry.set(openTelemetry);
85+
this.runner.run((context) -> {
86+
assertThat(context).doesNotHaveBean(OpenTelemetrySdk.class);
87+
assertThat(context.getBean(OpenTelemetry.class).getTracer("org.springframework.boot")).isSameAs(tracer);
88+
});
89+
}
90+
6591
@Test
6692
void shouldBackOffIfOpenTelemetryIsNotOnClasspath() {
6793
this.runner.withClassLoader(new FilteredClassLoader("io.opentelemetry")).run((context) -> {

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/BaggagePropagationIntegrationTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.micrometer.tracing.BaggageManager;
2323
import io.micrometer.tracing.Span;
2424
import io.micrometer.tracing.Tracer;
25+
import io.opentelemetry.api.GlobalOpenTelemetry;
2526
import io.opentelemetry.context.Context;
2627
import org.assertj.core.api.ThrowingConsumer;
2728
import org.junit.jupiter.api.AfterEach;
@@ -58,6 +59,7 @@ class BaggagePropagationIntegrationTests {
5859
@AfterEach
5960
void setup() {
6061
MDC.clear();
62+
GlobalOpenTelemetry.resetForTest();
6163
}
6264

6365
@ParameterizedTest

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryTracingAutoConfigurationTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import io.micrometer.tracing.otel.bridge.Slf4JBaggageEventListener;
3737
import io.micrometer.tracing.otel.bridge.Slf4JEventListener;
3838
import io.micrometer.tracing.otel.propagation.BaggageTextMapPropagator;
39+
import io.opentelemetry.api.GlobalOpenTelemetry;
3940
import io.opentelemetry.api.common.AttributeKey;
4041
import io.opentelemetry.api.common.Attributes;
4142
import io.opentelemetry.api.metrics.MeterProvider;
@@ -55,6 +56,7 @@
5556
import io.opentelemetry.sdk.trace.export.SpanExporter;
5657
import io.opentelemetry.sdk.trace.samplers.Sampler;
5758
import org.assertj.core.api.InstanceOfAssertFactories;
59+
import org.junit.jupiter.api.AfterEach;
5860
import org.junit.jupiter.api.Test;
5961
import org.junit.jupiter.params.ParameterizedTest;
6062
import org.junit.jupiter.params.provider.ValueSource;
@@ -93,6 +95,11 @@ class OpenTelemetryTracingAutoConfigurationTests {
9395
org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration.class,
9496
OpenTelemetryTracingAutoConfiguration.class));
9597

98+
@AfterEach
99+
void reset() {
100+
GlobalOpenTelemetry.resetForTest();
101+
}
102+
96103
@Test
97104
void shouldSupplyBeans() {
98105
this.contextRunner.run((context) -> {

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/otlp/OtlpTracingAutoConfigurationIntegrationTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.concurrent.TimeUnit;
2424

2525
import io.micrometer.tracing.Tracer;
26+
import io.opentelemetry.api.GlobalOpenTelemetry;
2627
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
2728
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
2829
import io.opentelemetry.sdk.common.CompletableResultCode;
@@ -83,6 +84,7 @@ void startServers() throws Exception {
8384
void stopServers() throws Exception {
8485
this.mockWebServer.close();
8586
this.mockGrpcServer.close();
87+
GlobalOpenTelemetry.resetForTest();
8688
}
8789

8890
@Test

0 commit comments

Comments
 (0)