From 6af1fb5c2684f9c88c846e27515f79ae39b7e2cd Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Mon, 24 Aug 2026 14:05:24 +0200 Subject: [PATCH] Polish "Align OTLP signal-specific properties with common fallback configuration" Allow `management.opentelemetry.otlp.compression` to act as a common default for OTLP compression, mirroring the existing endpoint/headers fallback. Tracing, logging and metrics exporters now fall back to it when their own signal-specific compression property is unset. See gh-50461 --- ...itional-spring-configuration-metadata.json | 10 --- .../export/otlp/OtlpMetricsProperties.java | 6 +- .../OtlpMetricsPropertiesConfigAdapter.java | 13 ++- ...lpMetricsPropertiesConfigAdapterTests.java | 13 +++ .../otlp/OtlpMetricsPropertiesTests.java | 2 +- .../otlp/OtlpTracingConfigurations.java | 88 ++++++------------- .../otlp/OtlpTracingProperties.java | 6 +- ...cingAutoConfigurationIntegrationTests.java | 35 ++++++++ .../autoconfigure/OtlpProperties.java | 30 +++++++ .../otlp/OtlpLoggingConfigurations.java | 52 +++++------ .../logging/otlp/OtlpLoggingProperties.java | 6 +- ...gingAutoConfigurationIntegrationTests.java | 31 +++++++ .../OtlpLoggingAutoConfigurationTests.java | 14 ++- 13 files changed, 198 insertions(+), 108 deletions(-) diff --git a/module/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/module/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index a56c3b9afb6..25f10ce2939 100644 --- a/module/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/module/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -151,16 +151,6 @@ "description": "Whether auto-configuration of logging is enabled to export logs.", "defaultValue": true }, - { - "name": "management.opentelemetry.otlp.endpoint", - "type": "java.lang.String", - "description": "OTLP target endpoint URL." - }, - { - "name": "management.opentelemetry.otlp.headers", - "type": "java.util.Map", - "description": "Custom headers to be appended to OTLP requests." - }, { "name": "management.server.add-application-context-header", "type": "java.lang.Boolean", diff --git a/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsProperties.java b/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsProperties.java index 99c11d898da..7e20a1b01c4 100644 --- a/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsProperties.java +++ b/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsProperties.java @@ -53,7 +53,7 @@ public class OtlpMetricsProperties extends StepRegistryProperties { /** * Compression mode to use when exporting metrics. */ - private CompressionMode compressionMode = CompressionMode.NONE; + private @Nullable CompressionMode compressionMode; /** * Headers for the exported metrics. @@ -109,11 +109,11 @@ public class OtlpMetricsProperties extends StepRegistryProperties { this.aggregationTemporality = aggregationTemporality; } - public CompressionMode getCompressionMode() { + public @Nullable CompressionMode getCompressionMode() { return this.compressionMode; } - public void setCompressionMode(CompressionMode compressionMode) { + public void setCompressionMode(@Nullable CompressionMode compressionMode) { this.compressionMode = compressionMode; } diff --git a/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesConfigAdapter.java b/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesConfigAdapter.java index 2255b2be8b8..7b563e8384d 100644 --- a/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesConfigAdapter.java +++ b/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesConfigAdapter.java @@ -79,7 +79,18 @@ class OtlpMetricsPropertiesConfigAdapter extends StepRegistryPropertiesConfigAda @Override public CompressionMode compressionMode() { - return obtain(OtlpMetricsProperties::getCompressionMode, OtlpConfig.super::compressionMode); + CompressionMode compressionMode = this.properties.getCompressionMode(); + if (compressionMode != null) { + return compressionMode; + } + OtlpProperties.Compression commonCompression = this.otlpProperties.getCompression(); + if (commonCompression != null) { + return switch (commonCompression) { + case GZIP -> CompressionMode.GZIP; + case NONE -> CompressionMode.NONE; + }; + } + return OtlpConfig.super.compressionMode(); } @Override diff --git a/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesConfigAdapterTests.java b/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesConfigAdapterTests.java index 39be71c518d..5c3d140ed02 100644 --- a/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesConfigAdapterTests.java +++ b/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesConfigAdapterTests.java @@ -279,4 +279,17 @@ class OtlpMetricsPropertiesConfigAdapterTests { assertThat(createAdapter().url()).isEqualTo("http://signal-endpoint:4318/custom/metrics"); } + @Test + void whenPropertiesCompressionModeIsNotSetThenUseOtlpPropertiesCompressionAsFallback() { + this.otlpProperties.setCompression(OtlpProperties.Compression.GZIP); + assertThat(createAdapter().compressionMode()).isSameAs(CompressionMode.GZIP); + } + + @Test + void whenPropertiesCompressionModeIsSetThenItOverridesOtlpPropertiesCompression() { + this.otlpProperties.setCompression(OtlpProperties.Compression.GZIP); + this.properties.setCompressionMode(CompressionMode.NONE); + assertThat(createAdapter().compressionMode()).isSameAs(CompressionMode.NONE); + } + } diff --git a/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesTests.java b/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesTests.java index c34f0c39f20..78a66beb6b5 100644 --- a/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesTests.java +++ b/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/export/otlp/OtlpMetricsPropertiesTests.java @@ -36,7 +36,7 @@ class OtlpMetricsPropertiesTests extends StepRegistryPropertiesTests { OtlpConfig config = OtlpConfig.DEFAULT; assertStepRegistryDefaultValues(properties, config); assertThat(properties.getAggregationTemporality()).isSameAs(config.aggregationTemporality()); - assertThat(properties.getCompressionMode()).isSameAs(config.compressionMode()); + assertThat(properties.getCompressionMode()).isNull(); assertThat(properties.getHistogramFlavor()).isSameAs(config.histogramFlavor()); assertThat(properties.getMaxScale()).isEqualTo(config.maxScale()); assertThat(properties.getMaxBucketCount()).isEqualTo(config.maxBucketCount()); diff --git a/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingConfigurations.java b/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingConfigurations.java index a33a0c9f6c8..4fb14716cac 100644 --- a/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingConfigurations.java +++ b/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingConfigurations.java @@ -16,7 +16,6 @@ package org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp; -import java.time.Duration; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; @@ -34,20 +33,16 @@ import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; -import org.springframework.boot.autoconfigure.condition.ConditionOutcome; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.micrometer.tracing.autoconfigure.ConditionalOnEnabledTracingExport; import org.springframework.boot.opentelemetry.autoconfigure.OtlpProperties; import org.springframework.boot.ssl.SslBundle; import org.springframework.boot.ssl.SslBundles; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -81,13 +76,11 @@ final class OtlpTracingConfigurations { } @ConditionalOnProperty("management.opentelemetry.tracing.export.otlp.endpoint") - @SuppressWarnings("unused") static class TracingEndpoint { } @ConditionalOnProperty("management.opentelemetry.otlp.endpoint") - @SuppressWarnings("unused") static class CommonEndpoint { } @@ -115,6 +108,9 @@ final class OtlpTracingConfigurations { @Override public String getUrl(Transport transport) { + Assert.state(transport == this.properties.getTransport(), + "Requested transport %s doesn't match configured transport %s".formatted(transport, + this.properties.getTransport())); String endpoint = this.properties.getEndpoint(); if (!StringUtils.hasLength(endpoint)) { endpoint = this.otlpProperties.getEndpoint(); @@ -153,23 +149,13 @@ final class OtlpTracingConfigurations { OtlpTracingConnectionDetails connectionDetails, ObjectProvider meterProvider, ObjectProvider customizers) { OtlpHttpSpanExporterBuilder builder = OtlpHttpSpanExporter.builder() - .setEndpoint(connectionDetails.getUrl(Transport.HTTP)); - - Duration timeout = properties.getTimeout(); - builder.setTimeout(timeout); - - Duration connectTimeout = properties.getConnectTimeout(); - builder.setConnectTimeout(connectTimeout); - - String compression = properties.getCompression().name().toLowerCase(Locale.ROOT); - if (StringUtils.hasLength(compression)) { - builder.setCompression(compression); - } - + .setEndpoint(connectionDetails.getUrl(Transport.HTTP)) + .setTimeout(properties.getTimeout()) + .setConnectTimeout(properties.getConnectTimeout()) + .setCompression(resolveCompression(properties, otlpProperties).name().toLowerCase(Locale.ROOT)); Map headers = new LinkedHashMap<>(otlpProperties.getHeaders()); headers.putAll(properties.getHeaders()); headers.forEach(builder::addHeader); - meterProvider.ifAvailable(builder::setMeterProvider); configureSsl(connectionDetails, builder::setSslContext); customizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); @@ -182,29 +168,35 @@ final class OtlpTracingConfigurations { OtlpTracingConnectionDetails connectionDetails, ObjectProvider meterProvider, ObjectProvider customizers) { OtlpGrpcSpanExporterBuilder builder = OtlpGrpcSpanExporter.builder() - .setEndpoint(connectionDetails.getUrl(Transport.GRPC)); - - Duration timeout = properties.getTimeout(); - builder.setTimeout(timeout); - - Duration connectTimeout = properties.getConnectTimeout(); - builder.setConnectTimeout(connectTimeout); - - String compression = properties.getCompression().name().toLowerCase(Locale.ROOT); - if (StringUtils.hasLength(compression)) { - builder.setCompression(compression); - } - + .setEndpoint(connectionDetails.getUrl(Transport.GRPC)) + .setTimeout(properties.getTimeout()) + .setConnectTimeout(properties.getConnectTimeout()) + .setCompression(resolveCompression(properties, otlpProperties).name().toLowerCase(Locale.ROOT)); Map headers = new LinkedHashMap<>(otlpProperties.getHeaders()); headers.putAll(properties.getHeaders()); headers.forEach(builder::addHeader); - meterProvider.ifAvailable(builder::setMeterProvider); configureSsl(connectionDetails, builder::setSslContext); customizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); return builder.build(); } + private OtlpTracingProperties.Compression resolveCompression(OtlpTracingProperties properties, + OtlpProperties otlpProperties) { + OtlpTracingProperties.Compression compression = properties.getCompression(); + if (compression != null) { + return compression; + } + OtlpProperties.Compression commonCompression = otlpProperties.getCompression(); + if (commonCompression != null) { + return switch (commonCompression) { + case GZIP -> OtlpTracingProperties.Compression.GZIP; + case NONE -> OtlpTracingProperties.Compression.NONE; + }; + } + return OtlpTracingProperties.Compression.NONE; + } + private void configureSsl(OtlpTracingConnectionDetails connectionDetails, SslContextConfigurer sslContextConfigurer) { SslBundle sslBundle = connectionDetails.getSslBundle(); @@ -230,32 +222,6 @@ final class OtlpTracingConfigurations { } - static class HttpTransportCondition extends SpringBootCondition { - - @Override - public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { - String tracingTransport = context.getEnvironment() - .getProperty("management.opentelemetry.tracing.export.otlp.transport"); - String activeTransport = (tracingTransport != null) ? tracingTransport : "http"; - return new ConditionOutcome("http".equalsIgnoreCase(activeTransport), - "Transport is " + activeTransport); - } - - } - - static class GrpcTransportCondition extends SpringBootCondition { - - @Override - public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { - String tracingTransport = context.getEnvironment() - .getProperty("management.opentelemetry.tracing.export.otlp.transport"); - String activeTransport = (tracingTransport != null) ? tracingTransport : "http"; - return new ConditionOutcome("grpc".equalsIgnoreCase(activeTransport), - "Transport is " + activeTransport); - } - - } - } } diff --git a/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingProperties.java b/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingProperties.java index b76c63cb610..c4390ea1ec9 100644 --- a/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingProperties.java +++ b/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingProperties.java @@ -59,7 +59,7 @@ public class OtlpTracingProperties { /** * Method used to compress the payload. */ - private Compression compression = Compression.NONE; + private @Nullable Compression compression; /** * Custom HTTP headers you want to pass to the collector, for example auth headers. @@ -100,11 +100,11 @@ public class OtlpTracingProperties { this.transport = transport; } - public Compression getCompression() { + public @Nullable Compression getCompression() { return this.compression; } - public void setCompression(Compression compression) { + public void setCompression(@Nullable Compression compression) { this.compression = compression; } diff --git a/module/spring-boot-micrometer-tracing-opentelemetry/src/test/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingAutoConfigurationIntegrationTests.java b/module/spring-boot-micrometer-tracing-opentelemetry/src/test/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingAutoConfigurationIntegrationTests.java index e42e7de54ba..bb758039245 100644 --- a/module/spring-boot-micrometer-tracing-opentelemetry/src/test/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingAutoConfigurationIntegrationTests.java +++ b/module/spring-boot-micrometer-tracing-opentelemetry/src/test/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/otlp/OtlpTracingAutoConfigurationIntegrationTests.java @@ -134,6 +134,41 @@ class OtlpTracingAutoConfigurationIntegrationTests { }); } + @Test + void httpSpanExporterFallsBackToCommonCompressionWhenSignalSpecificCompressionIsNotSet() { + this.mockWebServer.enqueue(new MockResponse()); + this.contextRunner + .withPropertyValues("management.opentelemetry.otlp.compression=gzip", + "management.opentelemetry.tracing.export.otlp.endpoint=http://localhost:%d/test" + .formatted(this.mockWebServer.getPort())) + .run((context) -> { + context.getBean(Tracer.class).nextSpan().name("test").end(); + assertThat(context.getBean(OtlpHttpSpanExporter.class).flush()) + .isSameAs(CompletableResultCode.ofSuccess()); + RecordedRequest request = this.mockWebServer.takeRequest(10, TimeUnit.SECONDS); + assertThat(request).isNotNull(); + assertThat(request.getHeader("Content-Encoding")).isEqualTo("gzip"); + }); + } + + @Test + void httpSpanExporterSignalSpecificCompressionWinsOverCommonCompression() { + this.mockWebServer.enqueue(new MockResponse()); + this.contextRunner + .withPropertyValues("management.opentelemetry.otlp.compression=gzip", + "management.opentelemetry.tracing.export.otlp.compression=none", + "management.opentelemetry.tracing.export.otlp.endpoint=http://localhost:%d/test" + .formatted(this.mockWebServer.getPort())) + .run((context) -> { + context.getBean(Tracer.class).nextSpan().name("test").end(); + assertThat(context.getBean(OtlpHttpSpanExporter.class).flush()) + .isSameAs(CompletableResultCode.ofSuccess()); + RecordedRequest request = this.mockWebServer.takeRequest(10, TimeUnit.SECONDS); + assertThat(request).isNotNull(); + assertThat(request.getHeader("Content-Encoding")).isNull(); + }); + } + @Test void grpcSpanExporterShouldExportSpans() { this.contextRunner diff --git a/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/OtlpProperties.java b/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/OtlpProperties.java index 1aed3ee1b89..6bc97903bc0 100644 --- a/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/OtlpProperties.java +++ b/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/OtlpProperties.java @@ -42,6 +42,11 @@ public class OtlpProperties { */ private final Map headers = new LinkedHashMap<>(); + /** + * Method used to compress the payload. + */ + private @Nullable Compression compression; + public @Nullable String getEndpoint() { return this.endpoint; } @@ -54,4 +59,29 @@ public class OtlpProperties { return this.headers; } + public @Nullable Compression getCompression() { + return this.compression; + } + + public void setCompression(@Nullable Compression compression) { + this.compression = compression; + } + + /** + * Compression methods. + */ + public enum Compression { + + /** + * Gzip compression. + */ + GZIP, + + /** + * No compression. + */ + NONE + + } + } diff --git a/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingConfigurations.java b/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingConfigurations.java index e511d357f79..0ef2d0a1055 100644 --- a/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingConfigurations.java +++ b/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingConfigurations.java @@ -16,7 +16,6 @@ package org.springframework.boot.opentelemetry.autoconfigure.logging.otlp; -import java.time.Duration; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; @@ -78,13 +77,11 @@ final class OtlpLoggingConfigurations { } @ConditionalOnProperty("management.opentelemetry.logging.export.otlp.endpoint") - @SuppressWarnings("unused") static class LoggingEndpoint { } @ConditionalOnProperty("management.opentelemetry.otlp.endpoint") - @SuppressWarnings("unused") static class CommonEndpoint { } @@ -112,6 +109,9 @@ final class OtlpLoggingConfigurations { @Override public String getUrl(Transport transport) { + Assert.state(transport == this.properties.getTransport(), + "Requested transport %s doesn't match configured transport %s".formatted(transport, + this.properties.getTransport())); String endpoint = this.properties.getEndpoint(); if (!StringUtils.hasLength(endpoint)) { endpoint = this.otlpProperties.getEndpoint(); @@ -152,20 +152,13 @@ final class OtlpLoggingConfigurations { ObjectProvider meterProvider, ObjectProvider customizers) { OtlpHttpLogRecordExporterBuilder builder = OtlpHttpLogRecordExporter.builder() - .setEndpoint(connectionDetails.getUrl(Transport.HTTP)); - - Duration timeout = properties.getTimeout(); - builder.setTimeout(timeout); - - String compression = properties.getCompression().name().toLowerCase(Locale.ROOT); - if (StringUtils.hasLength(compression)) { - builder.setCompression(compression); - } - + .setEndpoint(connectionDetails.getUrl(Transport.HTTP)) + .setTimeout(properties.getTimeout()) + .setConnectTimeout(properties.getConnectTimeout()) + .setCompression(resolveCompression(properties, otlpProperties).name().toLowerCase(Locale.US)); Map headers = new LinkedHashMap<>(otlpProperties.getHeaders()); headers.putAll(properties.getHeaders()); headers.forEach(builder::addHeader); - meterProvider.ifAvailable(builder::setMeterProvider); configureSsl(connectionDetails, builder::setSslContext); customizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); @@ -179,26 +172,35 @@ final class OtlpLoggingConfigurations { ObjectProvider meterProvider, ObjectProvider customizers) { OtlpGrpcLogRecordExporterBuilder builder = OtlpGrpcLogRecordExporter.builder() - .setEndpoint(connectionDetails.getUrl(Transport.GRPC)); - - Duration timeout = properties.getTimeout(); - builder.setTimeout(timeout); - - String compression = properties.getCompression().name().toLowerCase(Locale.ROOT); - if (StringUtils.hasLength(compression)) { - builder.setCompression(compression); - } - + .setEndpoint(connectionDetails.getUrl(Transport.GRPC)) + .setTimeout(properties.getTimeout()) + .setConnectTimeout(properties.getConnectTimeout()) + .setCompression(resolveCompression(properties, otlpProperties).name().toLowerCase(Locale.US)); Map headers = new LinkedHashMap<>(otlpProperties.getHeaders()); headers.putAll(properties.getHeaders()); headers.forEach(builder::addHeader); - meterProvider.ifAvailable(builder::setMeterProvider); configureSsl(connectionDetails, builder::setSslContext); customizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); return builder.build(); } + private OtlpLoggingProperties.Compression resolveCompression(OtlpLoggingProperties properties, + OtlpProperties otlpProperties) { + OtlpLoggingProperties.Compression compression = properties.getCompression(); + if (compression != null) { + return compression; + } + OtlpProperties.Compression commonCompression = otlpProperties.getCompression(); + if (commonCompression != null) { + return switch (commonCompression) { + case GZIP -> OtlpLoggingProperties.Compression.GZIP; + case NONE -> OtlpLoggingProperties.Compression.NONE; + }; + } + return OtlpLoggingProperties.Compression.NONE; + } + private void configureSsl(OtlpLoggingConnectionDetails connectionDetails, SslContextConfigurer sslContextConfigurer) { SslBundle sslBundle = connectionDetails.getSslBundle(); diff --git a/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingProperties.java b/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingProperties.java index ebb114ae24b..68749110f4b 100644 --- a/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingProperties.java +++ b/module/spring-boot-opentelemetry/src/main/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingProperties.java @@ -59,7 +59,7 @@ public class OtlpLoggingProperties { /** * Method used to compress the payload. */ - private Compression compression = Compression.NONE; + private @Nullable Compression compression; /** * Custom HTTP headers you want to pass to the collector, for example auth headers. @@ -100,11 +100,11 @@ public class OtlpLoggingProperties { this.transport = transport; } - public Compression getCompression() { + public @Nullable Compression getCompression() { return this.compression; } - public void setCompression(Compression compression) { + public void setCompression(@Nullable Compression compression) { this.compression = compression; } diff --git a/module/spring-boot-opentelemetry/src/test/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingAutoConfigurationIntegrationTests.java b/module/spring-boot-opentelemetry/src/test/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingAutoConfigurationIntegrationTests.java index 6d52496c3fa..475036f8d6f 100644 --- a/module/spring-boot-opentelemetry/src/test/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingAutoConfigurationIntegrationTests.java +++ b/module/spring-boot-opentelemetry/src/test/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingAutoConfigurationIntegrationTests.java @@ -108,6 +108,37 @@ class OtlpLoggingAutoConfigurationIntegrationTests { }); } + @Test + void httpLogRecordExporterFallsBackToCommonCompressionWhenSignalSpecificCompressionIsNotSet() { + this.mockWebServer.enqueue(new MockResponse()); + this.contextRunner + .withPropertyValues("management.opentelemetry.logging.export.otlp.endpoint=http://localhost:%d/v1/logs" + .formatted(this.mockWebServer.getPort()), "management.opentelemetry.otlp.compression=gzip") + .run((context) -> { + logMessage(context); + RecordedRequest request = this.mockWebServer.takeRequest(10, TimeUnit.SECONDS); + assertThat(request).isNotNull(); + assertThat(request.getHeader("Content-Encoding")).isEqualTo("gzip"); + }); + } + + @Test + void httpLogRecordExporterSignalSpecificCompressionWinsOverCommonCompression() { + this.mockWebServer.enqueue(new MockResponse()); + this.contextRunner + .withPropertyValues( + "management.opentelemetry.logging.export.otlp.endpoint=http://localhost:%d/v1/logs" + .formatted(this.mockWebServer.getPort()), + "management.opentelemetry.logging.export.otlp.compression=none", + "management.opentelemetry.otlp.compression=gzip") + .run((context) -> { + logMessage(context); + RecordedRequest request = this.mockWebServer.takeRequest(10, TimeUnit.SECONDS); + assertThat(request).isNotNull(); + assertThat(request.getHeader("Content-Encoding")).isNull(); + }); + } + private static void logMessage(ApplicationContext context) { SdkLoggerProvider loggerProvider = context.getBean(SdkLoggerProvider.class); loggerProvider.get("test") diff --git a/module/spring-boot-opentelemetry/src/test/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingAutoConfigurationTests.java b/module/spring-boot-opentelemetry/src/test/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingAutoConfigurationTests.java index 800f68bd9ef..49ac80726d1 100644 --- a/module/spring-boot-opentelemetry/src/test/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingAutoConfigurationTests.java +++ b/module/spring-boot-opentelemetry/src/test/java/org/springframework/boot/opentelemetry/autoconfigure/logging/otlp/OtlpLoggingAutoConfigurationTests.java @@ -323,14 +323,26 @@ class OtlpLoggingAutoConfigurationTests { } @Test - void shouldAppendLogsPathToCommonEndpoint() { + void shouldAppendLogsPathToCommonEndpointForHttpTransport() { OtlpLoggingProperties properties = new OtlpLoggingProperties(); + properties.setTransport(Transport.HTTP); OtlpProperties otlpProperties = new OtlpProperties(); otlpProperties.setEndpoint("http://localhost:4318"); PropertiesOtlpLoggingConnectionDetails connectionDetails = new PropertiesOtlpLoggingConnectionDetails( properties, otlpProperties, null); assertThat(connectionDetails.getUrl(Transport.HTTP)).isEqualTo("http://localhost:4318/v1/logs"); + } + + @Test + void shouldNotAppendLogsPathToCommonEndpointForGrpcTransport() { + OtlpLoggingProperties properties = new OtlpLoggingProperties(); + properties.setTransport(Transport.GRPC); + OtlpProperties otlpProperties = new OtlpProperties(); + otlpProperties.setEndpoint("http://localhost:4318"); + PropertiesOtlpLoggingConnectionDetails connectionDetails = new PropertiesOtlpLoggingConnectionDetails( + properties, otlpProperties, null); + assertThat(connectionDetails.getUrl(Transport.GRPC)).isEqualTo("http://localhost:4318"); }