diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle index 8b3c9334f86..57278fae374 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle @@ -139,6 +139,7 @@ dependencies { testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) testImplementation(testFixtures(project(":spring-boot-project:spring-boot"))) testImplementation("io.micrometer:micrometer-observation-test") + testImplementation("io.opentelemetry:opentelemetry-exporter-common") testImplementation("io.projectreactor:reactor-test") testImplementation("io.prometheus:prometheus-metrics-exposition-formats") testImplementation("io.r2dbc:r2dbc-h2") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/otlp/OtlpTracingAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/otlp/OtlpTracingAutoConfigurationTests.java index 174592638a7..1d138a23706 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/otlp/OtlpTracingAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/otlp/OtlpTracingAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -16,10 +16,15 @@ package org.springframework.boot.actuate.autoconfigure.tracing.otlp; +import java.util.List; +import java.util.function.Supplier; + +import io.opentelemetry.exporter.internal.compression.GzipCompressor; import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.sdk.trace.export.SpanExporter; import okhttp3.HttpUrl; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.tracing.otlp.OtlpTracingConfigurations.ConnectionDetails.PropertiesOtlpTracingConnectionDetails; @@ -64,6 +69,27 @@ class OtlpTracingAutoConfigurationTests { .hasSingleBean(SpanExporter.class)); } + @Test + void shouldCustomizeHttpTransportWithProperties() { + this.contextRunner + .withPropertyValues("management.otlp.tracing.endpoint=http://localhost:4317/v1/traces", + "management.otlp.tracing.timeout=10m", "management.otlp.tracing.connect-timeout=20m", + "management.otlp.tracing.compression=GZIP", "management.otlp.tracing.headers.spring=boot") + .run((context) -> { + assertThat(context).hasSingleBean(OtlpHttpSpanExporter.class).hasSingleBean(SpanExporter.class); + OtlpHttpSpanExporter exporter = context.getBean(OtlpHttpSpanExporter.class); + assertThat(exporter).extracting("delegate.httpSender.client") + .hasFieldOrPropertyWithValue("connectTimeoutMillis", 1200000) + .hasFieldOrPropertyWithValue("callTimeoutMillis", 600000); + assertThat(exporter).extracting("delegate.httpSender.compressor").isInstanceOf(GzipCompressor.class); + assertThat(exporter).extracting("delegate.httpSender.headerSupplier") + .asInstanceOf(InstanceOfAssertFactories.type(Supplier.class)) + .satisfies((headerSupplier) -> assertThat(headerSupplier.get()) + .asInstanceOf(InstanceOfAssertFactories.map(String.class, List.class)) + .containsEntry("spring", List.of("boot"))); + }); + } + @Test void shouldSupplyBeansIfGrpcTransportIsEnabled() { this.contextRunner @@ -73,6 +99,28 @@ class OtlpTracingAutoConfigurationTests { .hasSingleBean(SpanExporter.class)); } + @Test + void shouldCustomizeGrpcTransportWithProperties() { + this.contextRunner + .withPropertyValues("management.otlp.tracing.endpoint=http://localhost:4317/v1/traces", + "management.otlp.tracing.transport=grpc", "management.otlp.tracing.timeout=10m", + "management.otlp.tracing.connect-timeout=20m", "management.otlp.tracing.compression=GZIP", + "management.otlp.tracing.headers.spring=boot") + .run((context) -> { + assertThat(context).hasSingleBean(OtlpGrpcSpanExporter.class).hasSingleBean(SpanExporter.class); + OtlpGrpcSpanExporter exporter = context.getBean(OtlpGrpcSpanExporter.class); + assertThat(exporter).extracting("delegate.grpcSender.client") + .hasFieldOrPropertyWithValue("connectTimeoutMillis", 1200000) + .hasFieldOrPropertyWithValue("callTimeoutMillis", 600000); + assertThat(exporter).extracting("delegate.grpcSender.compressor").isInstanceOf(GzipCompressor.class); + assertThat(exporter).extracting("delegate.grpcSender.headersSupplier") + .asInstanceOf(InstanceOfAssertFactories.type(Supplier.class)) + .satisfies((headerSupplier) -> assertThat(headerSupplier.get()) + .asInstanceOf(InstanceOfAssertFactories.map(String.class, List.class)) + .containsEntry("spring", List.of("boot"))); + }); + } + @Test void shouldNotSupplyBeansIfGlobalTracingIsDisabled() { this.contextRunner.withPropertyValues("management.tracing.enabled=false")