Skip to content

Commit bbaac07

Browse files
committed
Merge pull request #36155 from jonatan-ivanov
* pr/36155: Add missing OTel Span attributes Closes gh-36155
2 parents 83457bb + 58cfdbf commit bbaac07

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ OpenTelemetry openTelemetry(SdkTracerProvider sdkTracerProvider, ContextPropagat
9797
SdkTracerProvider otelSdkTracerProvider(Environment environment, ObjectProvider<SpanProcessor> spanProcessors,
9898
Sampler sampler) {
9999
String applicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME);
100+
Resource springResource = Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName));
100101
SdkTracerProviderBuilder builder = SdkTracerProvider.builder()
101102
.setSampler(sampler)
102-
.setResource(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName)));
103+
.setResource(Resource.getDefault().merge(springResource));
103104
spanProcessors.orderedStream().forEach(builder::addSpanProcessor);
104105
return builder.build();
105106
}

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

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

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

19+
import java.time.Duration;
1920
import java.util.ArrayList;
21+
import java.util.Collection;
2022
import java.util.List;
23+
import java.util.Map;
24+
import java.util.concurrent.CountDownLatch;
25+
import java.util.concurrent.TimeUnit;
26+
import java.util.concurrent.TimeoutException;
2127
import java.util.stream.Stream;
2228

2329
import io.micrometer.tracing.SpanCustomizer;
@@ -30,18 +36,26 @@
3036
import io.micrometer.tracing.otel.bridge.Slf4JEventListener;
3137
import io.micrometer.tracing.otel.propagation.BaggageTextMapPropagator;
3238
import io.opentelemetry.api.OpenTelemetry;
39+
import io.opentelemetry.api.common.AttributeKey;
40+
import io.opentelemetry.api.common.Attributes;
3341
import io.opentelemetry.api.trace.Tracer;
3442
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
3543
import io.opentelemetry.context.propagation.ContextPropagators;
3644
import io.opentelemetry.context.propagation.TextMapPropagator;
3745
import io.opentelemetry.extension.trace.propagation.B3Propagator;
46+
import io.opentelemetry.sdk.common.CompletableResultCode;
47+
import io.opentelemetry.sdk.resources.Resource;
3848
import io.opentelemetry.sdk.trace.SdkTracerProvider;
3949
import io.opentelemetry.sdk.trace.SpanProcessor;
50+
import io.opentelemetry.sdk.trace.data.SpanData;
51+
import io.opentelemetry.sdk.trace.export.SpanExporter;
4052
import io.opentelemetry.sdk.trace.samplers.Sampler;
53+
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
4154
import org.junit.jupiter.api.Test;
4255
import org.junit.jupiter.params.ParameterizedTest;
4356
import org.junit.jupiter.params.provider.ValueSource;
4457

58+
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
4559
import org.springframework.boot.autoconfigure.AutoConfigurations;
4660
import org.springframework.boot.test.context.FilteredClassLoader;
4761
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -143,6 +157,26 @@ void shouldBackOffOnCustomBeans() {
143157
});
144158
}
145159

160+
@Test
161+
void shouldSetupDefaultResourceAttributes() {
162+
this.contextRunner
163+
.withConfiguration(
164+
AutoConfigurations.of(ObservationAutoConfiguration.class, MicrometerTracingAutoConfiguration.class))
165+
.withUserConfiguration(InMemoryRecordingSpanExporterConfiguration.class)
166+
.withPropertyValues("management.tracing.sampling.probability=1.0")
167+
.run((context) -> {
168+
context.getBean(io.micrometer.tracing.Tracer.class).nextSpan().name("test").end();
169+
InMemoryRecordingSpanExporter exporter = context.getBean(InMemoryRecordingSpanExporter.class);
170+
exporter.await(Duration.ofSeconds(10));
171+
SpanData spanData = exporter.getExportedSpans().get(0);
172+
Map<AttributeKey<?>, Object> expectedAttributes = Resource.getDefault()
173+
.merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, "application")))
174+
.getAttributes()
175+
.asMap();
176+
assertThat(spanData.getResource().getAttributes().asMap()).isEqualTo(expectedAttributes);
177+
});
178+
}
179+
146180
@Test
147181
void shouldAllowMultipleSpanProcessors() {
148182
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> {
@@ -297,4 +331,50 @@ SpanCustomizer customSpanCustomizer() {
297331

298332
}
299333

334+
@Configuration(proxyBeanMethods = false)
335+
private static class InMemoryRecordingSpanExporterConfiguration {
336+
337+
@Bean
338+
InMemoryRecordingSpanExporter spanExporter() {
339+
return new InMemoryRecordingSpanExporter();
340+
}
341+
342+
}
343+
344+
private static class InMemoryRecordingSpanExporter implements SpanExporter {
345+
346+
private final List<SpanData> exportedSpans = new ArrayList<>();
347+
348+
private final CountDownLatch latch = new CountDownLatch(1);
349+
350+
@Override
351+
public CompletableResultCode export(Collection<SpanData> spans) {
352+
this.exportedSpans.addAll(spans);
353+
this.latch.countDown();
354+
return CompletableResultCode.ofSuccess();
355+
}
356+
357+
@Override
358+
public CompletableResultCode flush() {
359+
return CompletableResultCode.ofSuccess();
360+
}
361+
362+
@Override
363+
public CompletableResultCode shutdown() {
364+
this.exportedSpans.clear();
365+
return CompletableResultCode.ofSuccess();
366+
}
367+
368+
List<SpanData> getExportedSpans() {
369+
return this.exportedSpans;
370+
}
371+
372+
void await(Duration timeout) throws InterruptedException, TimeoutException {
373+
if (!this.latch.await(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
374+
throw new TimeoutException("Waiting for exporting spans timed out (%s)".formatted(timeout));
375+
}
376+
}
377+
378+
}
379+
300380
}

0 commit comments

Comments
 (0)