|
|
|
|
@ -16,8 +16,14 @@
@@ -16,8 +16,14 @@
|
|
|
|
|
|
|
|
|
|
package org.springframework.boot.actuate.autoconfigure.tracing; |
|
|
|
|
|
|
|
|
|
import java.time.Duration; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Collection; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.concurrent.CountDownLatch; |
|
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
|
import java.util.concurrent.TimeoutException; |
|
|
|
|
import java.util.stream.Stream; |
|
|
|
|
|
|
|
|
|
import io.micrometer.tracing.SpanCustomizer; |
|
|
|
|
@ -30,18 +36,26 @@ import io.micrometer.tracing.otel.bridge.Slf4JBaggageEventListener;
@@ -30,18 +36,26 @@ import io.micrometer.tracing.otel.bridge.Slf4JBaggageEventListener;
|
|
|
|
|
import io.micrometer.tracing.otel.bridge.Slf4JEventListener; |
|
|
|
|
import io.micrometer.tracing.otel.propagation.BaggageTextMapPropagator; |
|
|
|
|
import io.opentelemetry.api.OpenTelemetry; |
|
|
|
|
import io.opentelemetry.api.common.AttributeKey; |
|
|
|
|
import io.opentelemetry.api.common.Attributes; |
|
|
|
|
import io.opentelemetry.api.trace.Tracer; |
|
|
|
|
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; |
|
|
|
|
import io.opentelemetry.context.propagation.ContextPropagators; |
|
|
|
|
import io.opentelemetry.context.propagation.TextMapPropagator; |
|
|
|
|
import io.opentelemetry.extension.trace.propagation.B3Propagator; |
|
|
|
|
import io.opentelemetry.sdk.common.CompletableResultCode; |
|
|
|
|
import io.opentelemetry.sdk.resources.Resource; |
|
|
|
|
import io.opentelemetry.sdk.trace.SdkTracerProvider; |
|
|
|
|
import io.opentelemetry.sdk.trace.SpanProcessor; |
|
|
|
|
import io.opentelemetry.sdk.trace.data.SpanData; |
|
|
|
|
import io.opentelemetry.sdk.trace.export.SpanExporter; |
|
|
|
|
import io.opentelemetry.sdk.trace.samplers.Sampler; |
|
|
|
|
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; |
|
|
|
|
import org.junit.jupiter.api.Test; |
|
|
|
|
import org.junit.jupiter.params.ParameterizedTest; |
|
|
|
|
import org.junit.jupiter.params.provider.ValueSource; |
|
|
|
|
|
|
|
|
|
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration; |
|
|
|
|
import org.springframework.boot.autoconfigure.AutoConfigurations; |
|
|
|
|
import org.springframework.boot.test.context.FilteredClassLoader; |
|
|
|
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner; |
|
|
|
|
@ -143,6 +157,26 @@ class OpenTelemetryAutoConfigurationTests {
@@ -143,6 +157,26 @@ class OpenTelemetryAutoConfigurationTests {
|
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void shouldSetupDefaultResourceAttributes() { |
|
|
|
|
this.contextRunner |
|
|
|
|
.withConfiguration( |
|
|
|
|
AutoConfigurations.of(ObservationAutoConfiguration.class, MicrometerTracingAutoConfiguration.class)) |
|
|
|
|
.withUserConfiguration(InMemoryRecordingSpanExporterConfiguration.class) |
|
|
|
|
.withPropertyValues("management.tracing.sampling.probability=1.0") |
|
|
|
|
.run((context) -> { |
|
|
|
|
context.getBean(io.micrometer.tracing.Tracer.class).nextSpan().name("test").end(); |
|
|
|
|
InMemoryRecordingSpanExporter exporter = context.getBean(InMemoryRecordingSpanExporter.class); |
|
|
|
|
exporter.await(Duration.ofSeconds(10)); |
|
|
|
|
SpanData spanData = exporter.getExportedSpans().get(0); |
|
|
|
|
Map<AttributeKey<?>, Object> expectedAttributes = Resource.getDefault() |
|
|
|
|
.merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, "application"))) |
|
|
|
|
.getAttributes() |
|
|
|
|
.asMap(); |
|
|
|
|
assertThat(spanData.getResource().getAttributes().asMap()).isEqualTo(expectedAttributes); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void shouldAllowMultipleSpanProcessors() { |
|
|
|
|
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> { |
|
|
|
|
@ -297,4 +331,50 @@ class OpenTelemetryAutoConfigurationTests {
@@ -297,4 +331,50 @@ class OpenTelemetryAutoConfigurationTests {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Configuration(proxyBeanMethods = false) |
|
|
|
|
private static class InMemoryRecordingSpanExporterConfiguration { |
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
InMemoryRecordingSpanExporter spanExporter() { |
|
|
|
|
return new InMemoryRecordingSpanExporter(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static class InMemoryRecordingSpanExporter implements SpanExporter { |
|
|
|
|
|
|
|
|
|
private final List<SpanData> exportedSpans = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
private final CountDownLatch latch = new CountDownLatch(1); |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public CompletableResultCode export(Collection<SpanData> spans) { |
|
|
|
|
this.exportedSpans.addAll(spans); |
|
|
|
|
this.latch.countDown(); |
|
|
|
|
return CompletableResultCode.ofSuccess(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public CompletableResultCode flush() { |
|
|
|
|
return CompletableResultCode.ofSuccess(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public CompletableResultCode shutdown() { |
|
|
|
|
this.exportedSpans.clear(); |
|
|
|
|
return CompletableResultCode.ofSuccess(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<SpanData> getExportedSpans() { |
|
|
|
|
return this.exportedSpans; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void await(Duration timeout) throws InterruptedException, TimeoutException { |
|
|
|
|
if (!this.latch.await(timeout.toMillis(), TimeUnit.MILLISECONDS)) { |
|
|
|
|
throw new TimeoutException("Waiting for exporting spans timed out (%s)".formatted(timeout)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|