Polish "Provide auto configuration for OpenTelemetry Logs"

See gh-40961
This commit is contained in:
Moritz Halbritter 2024-06-27 10:18:01 +02:00
parent 2d6f2488b7
commit cfa05716ef
12 changed files with 99 additions and 104 deletions

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.sdk.logs.LogRecordProcessor; import io.opentelemetry.sdk.logs.LogRecordProcessor;
@ -32,26 +32,25 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for OpenTelemetry Logs. * {@link EnableAutoConfiguration Auto-configuration} for OpenTelemetry logging.
* *
* @author Toshiaki Maki * @author Toshiaki Maki
* @since 3.4.0 * @since 3.4.0
*/ */
@AutoConfiguration("openTelemetryLogsAutoConfiguration") @AutoConfiguration
@ConditionalOnClass({ SdkLoggerProvider.class, OpenTelemetry.class }) @ConditionalOnClass({ SdkLoggerProvider.class, OpenTelemetry.class })
public class OpenTelemetryAutoConfiguration { public class OpenTelemetryLoggingAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public BatchLogRecordProcessor batchLogRecordProcessor(ObjectProvider<LogRecordExporter> logRecordExporters) { BatchLogRecordProcessor batchLogRecordProcessor(ObjectProvider<LogRecordExporter> logRecordExporters) {
return BatchLogRecordProcessor.builder(LogRecordExporter.composite(logRecordExporters.orderedStream().toList())) return BatchLogRecordProcessor.builder(LogRecordExporter.composite(logRecordExporters.orderedStream().toList()))
.build(); .build();
} }
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public SdkLoggerProvider otelSdkLoggerProvider(Resource resource, SdkLoggerProvider otelSdkLoggerProvider(Resource resource, ObjectProvider<LogRecordProcessor> logRecordProcessors,
ObjectProvider<LogRecordProcessor> logRecordProcessors,
ObjectProvider<SdkLoggerProviderBuilderCustomizer> customizers) { ObjectProvider<SdkLoggerProviderBuilderCustomizer> customizers) {
SdkLoggerProviderBuilder builder = SdkLoggerProvider.builder().setResource(resource); SdkLoggerProviderBuilder builder = SdkLoggerProvider.builder().setResource(resource);
logRecordProcessors.orderedStream().forEach(builder::addLogRecordProcessor); logRecordProcessors.orderedStream().forEach(builder::addLogRecordProcessor);

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry;
import io.opentelemetry.sdk.logs.SdkLoggerProvider; import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder; import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs.otlp; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter; import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
@ -27,15 +27,15 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for OTLP Logs. * {@link EnableAutoConfiguration Auto-configuration} for OTLP logging.
* *
* @author Toshiaki Maki * @author Toshiaki Maki
* @since 3.4.0 * @since 3.4.0
*/ */
@AutoConfiguration @AutoConfiguration
@ConditionalOnClass({ SdkLoggerProvider.class, OpenTelemetry.class, OtlpHttpLogRecordExporter.class }) @ConditionalOnClass({ SdkLoggerProvider.class, OpenTelemetry.class, OtlpHttpLogRecordExporter.class })
@EnableConfigurationProperties(OtlpProperties.class) @EnableConfigurationProperties(OtlpLoggingProperties.class)
@Import({ OtlpLogsConfigurations.ConnectionDetails.class, OtlpLogsConfigurations.Exporters.class }) @Import({ OtlpLoggingConfigurations.ConnectionDetails.class, OtlpLoggingConfigurations.Exporters.class })
public class OtlpLogsAutoConfiguration { public class OtlpLoggingAutoConfiguration {
} }

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs.otlp; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
import java.util.Locale; import java.util.Locale;
@ -28,36 +28,38 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* Configurations imported by {@link OtlpLogsAutoConfiguration}. * Configurations imported by {@link OtlpLoggingAutoConfiguration}.
* *
* @author Toshiaki Maki * @author Toshiaki Maki
* @since 3.4.0
*/ */
public class OtlpLogsConfigurations { final class OtlpLoggingConfigurations {
private OtlpLoggingConfigurations() {
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
static class ConnectionDetails { static class ConnectionDetails {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "management.otlp.logs", name = "endpoint") @ConditionalOnProperty(prefix = "management.otlp.logging", name = "endpoint")
OtlpLogsConnectionDetails otlpLogsConnectionDetails(OtlpProperties properties) { OtlpLoggingConnectionDetails otlpLogsConnectionDetails(OtlpLoggingProperties properties) {
return new PropertiesOtlpLogsConnectionDetails(properties); return new PropertiesOtlpLoggingConnectionDetails(properties);
} }
/** /**
* Adapts {@link OtlpProperties} to {@link OtlpLogsConnectionDetails}. * Adapts {@link OtlpLoggingProperties} to {@link OtlpLoggingConnectionDetails}.
*/ */
static class PropertiesOtlpLogsConnectionDetails implements OtlpLogsConnectionDetails { static class PropertiesOtlpLoggingConnectionDetails implements OtlpLoggingConnectionDetails {
private final OtlpProperties properties; private final OtlpLoggingProperties properties;
PropertiesOtlpLogsConnectionDetails(OtlpProperties properties) { PropertiesOtlpLoggingConnectionDetails(OtlpLoggingProperties properties) {
this.properties = properties; this.properties = properties;
} }
@Override @Override
public String getUrl() { public String getEndpoint() {
return this.properties.getEndpoint(); return this.properties.getEndpoint();
} }
@ -70,12 +72,12 @@ public class OtlpLogsConfigurations {
@ConditionalOnMissingBean(value = OtlpHttpLogRecordExporter.class, @ConditionalOnMissingBean(value = OtlpHttpLogRecordExporter.class,
type = "io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter") type = "io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter")
@ConditionalOnBean(OtlpLogsConnectionDetails.class) @ConditionalOnBean(OtlpLoggingConnectionDetails.class)
@Bean @Bean
OtlpHttpLogRecordExporter otlpHttpLogRecordExporter(OtlpProperties properties, OtlpHttpLogRecordExporter otlpHttpLogRecordExporter(OtlpLoggingProperties properties,
OtlpLogsConnectionDetails connectionDetails) { OtlpLoggingConnectionDetails connectionDetails) {
OtlpHttpLogRecordExporterBuilder builder = OtlpHttpLogRecordExporter.builder() OtlpHttpLogRecordExporterBuilder builder = OtlpHttpLogRecordExporter.builder()
.setEndpoint(connectionDetails.getUrl()) .setEndpoint(connectionDetails.getEndpoint())
.setCompression(properties.getCompression().name().toLowerCase(Locale.US)) .setCompression(properties.getCompression().name().toLowerCase(Locale.US))
.setTimeout(properties.getTimeout()); .setTimeout(properties.getTimeout());
properties.getHeaders().forEach(builder::addHeader); properties.getHeaders().forEach(builder::addHeader);

View File

@ -14,22 +14,22 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs.otlp; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
/** /**
* Details required to establish a connection to an OpenTelemetry logs service. * Details required to establish a connection to an OpenTelemetry logging service.
* *
* @author Toshiaki Maki * @author Toshiaki Maki
* @since 3.4.0 * @since 3.4.0
*/ */
public interface OtlpLogsConnectionDetails extends ConnectionDetails { public interface OtlpLoggingConnectionDetails extends ConnectionDetails {
/** /**
* Address to where logs will be published. * Address to where logs will be published.
* @return the address to where logs will be published * @return the address to where logs will be published
*/ */
String getUrl(); String getEndpoint();
} }

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs.otlp; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
import java.time.Duration; import java.time.Duration;
import java.util.HashMap; import java.util.HashMap;
@ -28,8 +28,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
* @author Jonatan Ivanov * @author Jonatan Ivanov
* @since 3.4.0 * @since 3.4.0
*/ */
@ConfigurationProperties("management.otlp.logs") @ConfigurationProperties("management.otlp.logging")
public class OtlpProperties { public class OtlpLoggingProperties {
/** /**
* URL to the OTel collector's HTTP API. * URL to the OTel collector's HTTP API.
@ -52,7 +52,7 @@ public class OtlpProperties {
/** /**
* Custom HTTP headers you want to pass to the collector, for example auth headers. * Custom HTTP headers you want to pass to the collector, for example auth headers.
*/ */
private Map<String, String> headers = new HashMap<>(); private final Map<String, String> headers = new HashMap<>();
public String getEndpoint() { public String getEndpoint() {
return this.endpoint; return this.endpoint;
@ -82,10 +82,6 @@ public class OtlpProperties {
return this.headers; return this.headers;
} }
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
public enum Compression { public enum Compression {
/** /**

View File

@ -15,6 +15,6 @@
*/ */
/** /**
* Auto-configuration for OpenTelemetry logs with OTLP. * Auto-configuration for OpenTelemetry logging with OTLP.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs.otlp; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;

View File

@ -15,6 +15,6 @@
*/ */
/** /**
* Auto-configuration for OpenTelemetry Logs. * Auto-configuration for OpenTelemetry logging.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry;

View File

@ -35,8 +35,8 @@ org.springframework.boot.actuate.autoconfigure.ldap.LdapHealthContributorAutoCon
org.springframework.boot.actuate.autoconfigure.liquibase.LiquibaseEndpointAutoConfiguration org.springframework.boot.actuate.autoconfigure.liquibase.LiquibaseEndpointAutoConfiguration
org.springframework.boot.actuate.autoconfigure.logging.LogFileWebEndpointAutoConfiguration org.springframework.boot.actuate.autoconfigure.logging.LogFileWebEndpointAutoConfiguration
org.springframework.boot.actuate.autoconfigure.logging.LoggersEndpointAutoConfiguration org.springframework.boot.actuate.autoconfigure.logging.LoggersEndpointAutoConfiguration
org.springframework.boot.actuate.autoconfigure.logs.OpenTelemetryAutoConfiguration org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.OpenTelemetryLoggingAutoConfiguration
org.springframework.boot.actuate.autoconfigure.logs.otlp.OtlpLogsAutoConfiguration org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp.OtlpLoggingAutoConfiguration
org.springframework.boot.actuate.autoconfigure.mail.MailHealthContributorAutoConfiguration org.springframework.boot.actuate.autoconfigure.mail.MailHealthContributorAutoConfiguration
org.springframework.boot.actuate.autoconfigure.management.HeapDumpWebEndpointAutoConfiguration org.springframework.boot.actuate.autoconfigure.management.HeapDumpWebEndpointAutoConfiguration
org.springframework.boot.actuate.autoconfigure.management.ThreadDumpEndpointAutoConfiguration org.springframework.boot.actuate.autoconfigure.management.ThreadDumpEndpointAutoConfiguration

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -41,18 +41,18 @@ import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Tests for {@link OpenTelemetryAutoConfiguration}. * Tests for {@link OpenTelemetryLoggingAutoConfiguration}.
* *
* @author Toshiaki Maki * @author Toshiaki Maki
*/ */
class OpenTelemetryAutoConfigurationTests { class OpenTelemetryLoggingAutoConfigurationTests {
private final ApplicationContextRunner contextRunner; private final ApplicationContextRunner contextRunner;
OpenTelemetryAutoConfigurationTests() { OpenTelemetryLoggingAutoConfigurationTests() {
this.contextRunner = new ApplicationContextRunner().withConfiguration(AutoConfigurations.of( this.contextRunner = new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(
org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration.class, org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration.class,
OpenTelemetryAutoConfiguration.class)); OpenTelemetryLoggingAutoConfiguration.class));
} }
@Test @Test

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs.otlp; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -32,25 +32,26 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.autoconfigure.logs.OpenTelemetryAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.OpenTelemetryLoggingAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.ApplicationContext;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Integration tests for {@link OtlpLogsAutoConfiguration}. * Integration tests for {@link OtlpLoggingAutoConfiguration}.
* *
* @author Toshiaki Maki * @author Toshiaki Maki
*/ */
public class OtlpLogsAutoConfigurationIntegrationTests { public class OtlpLoggingAutoConfigurationIntegrationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.application.name=otlp-logs-test", .withPropertyValues("spring.application.name=otlp-logs-test",
"management.otlp.logs.headers.Authorization=Bearer my-token") "management.otlp.logging.headers.Authorization=Bearer my-token")
.withConfiguration(AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class,
org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration.class, OpenTelemetryLoggingAutoConfiguration.class, OtlpLoggingAutoConfiguration.class));
OpenTelemetryAutoConfiguration.class, OtlpLogsAutoConfiguration.class));
private final MockWebServer mockWebServer = new MockWebServer(); private final MockWebServer mockWebServer = new MockWebServer();
@ -68,17 +69,10 @@ public class OtlpLogsAutoConfigurationIntegrationTests {
void httpLogRecordExporterShouldUseProtobufAndNoCompressionByDefault() { void httpLogRecordExporterShouldUseProtobufAndNoCompressionByDefault() {
this.mockWebServer.enqueue(new MockResponse()); this.mockWebServer.enqueue(new MockResponse());
this.contextRunner this.contextRunner
.withPropertyValues( .withPropertyValues("management.otlp.logging.endpoint=http://localhost:%d/v1/logs"
"management.otlp.logs.endpoint=http://localhost:%d/v1/logs".formatted(this.mockWebServer.getPort())) .formatted(this.mockWebServer.getPort()))
.run((context) -> { .run((context) -> {
SdkLoggerProvider loggerProvider = context.getBean(SdkLoggerProvider.class); logMessage(context);
loggerProvider.get("test")
.logRecordBuilder()
.setSeverity(Severity.INFO)
.setSeverityText("INFO")
.setBody("Hello")
.setTimestamp(Instant.now())
.emit();
RecordedRequest request = this.mockWebServer.takeRequest(10, TimeUnit.SECONDS); RecordedRequest request = this.mockWebServer.takeRequest(10, TimeUnit.SECONDS);
assertThat(request).isNotNull(); assertThat(request).isNotNull();
assertThat(request.getRequestLine()).contains("/v1/logs"); assertThat(request.getRequestLine()).contains("/v1/logs");
@ -86,12 +80,7 @@ public class OtlpLogsAutoConfigurationIntegrationTests {
assertThat(request.getHeader("Content-Encoding")).isNull(); assertThat(request.getHeader("Content-Encoding")).isNull();
assertThat(request.getBodySize()).isPositive(); assertThat(request.getBodySize()).isPositive();
try (Buffer body = request.getBody()) { try (Buffer body = request.getBody()) {
String bodyString = body.readString(StandardCharsets.UTF_8); assertLogMessage(body);
assertThat(bodyString).contains("otlp-logs-test");
assertThat(bodyString).contains("test");
assertThat(bodyString).contains("INFO");
assertThat(bodyString).contains("Hello");
} }
}); });
} }
@ -100,18 +89,10 @@ public class OtlpLogsAutoConfigurationIntegrationTests {
void httpLogRecordExporterCanBeConfiguredToUseGzipCompression() { void httpLogRecordExporterCanBeConfiguredToUseGzipCompression() {
this.mockWebServer.enqueue(new MockResponse()); this.mockWebServer.enqueue(new MockResponse());
this.contextRunner this.contextRunner
.withPropertyValues( .withPropertyValues("management.otlp.logging.endpoint=http://localhost:%d/v1/logs"
"management.otlp.logs.endpoint=http://localhost:%d/v1/logs".formatted(this.mockWebServer.getPort()), .formatted(this.mockWebServer.getPort()), "management.otlp.logging.compression=gzip")
"management.otlp.logs.compression=gzip")
.run((context) -> { .run((context) -> {
SdkLoggerProvider loggerProvider = context.getBean(SdkLoggerProvider.class); logMessage(context);
loggerProvider.get("test")
.logRecordBuilder()
.setBody("Hello")
.setSeverity(Severity.INFO)
.setSeverityText("INFO")
.setTimestamp(Instant.now())
.emit();
RecordedRequest request = this.mockWebServer.takeRequest(10, TimeUnit.SECONDS); RecordedRequest request = this.mockWebServer.takeRequest(10, TimeUnit.SECONDS);
assertThat(request).isNotNull(); assertThat(request).isNotNull();
assertThat(request.getRequestLine()).contains("/v1/logs"); assertThat(request.getRequestLine()).contains("/v1/logs");
@ -120,13 +101,28 @@ public class OtlpLogsAutoConfigurationIntegrationTests {
assertThat(request.getBodySize()).isPositive(); assertThat(request.getBodySize()).isPositive();
try (Buffer uncompressed = new Buffer(); Buffer body = request.getBody()) { try (Buffer uncompressed = new Buffer(); Buffer body = request.getBody()) {
uncompressed.writeAll(new GzipSource(body)); uncompressed.writeAll(new GzipSource(body));
String bodyString = uncompressed.readString(StandardCharsets.UTF_8); assertLogMessage(uncompressed);
assertThat(bodyString).contains("otlp-logs-test");
assertThat(bodyString).contains("test");
assertThat(bodyString).contains("INFO");
assertThat(bodyString).contains("Hello");
} }
}); });
} }
private static void logMessage(ApplicationContext context) {
SdkLoggerProvider loggerProvider = context.getBean(SdkLoggerProvider.class);
loggerProvider.get("test")
.logRecordBuilder()
.setSeverity(Severity.INFO)
.setSeverityText("INFO")
.setBody("Hello")
.setTimestamp(Instant.now())
.emit();
}
private static void assertLogMessage(Buffer body) {
String string = body.readString(StandardCharsets.UTF_8);
assertThat(string).contains("otlp-logs-test");
assertThat(string).contains("test");
assertThat(string).contains("INFO");
assertThat(string).contains("Hello");
}
} }

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.logs.otlp; package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter; import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter; import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter;
@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource; import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.boot.actuate.autoconfigure.logs.otlp.OtlpLogsConfigurations.ConnectionDetails.PropertiesOtlpLogsConnectionDetails; import org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp.OtlpLoggingConfigurations.ConnectionDetails.PropertiesOtlpLoggingConnectionDetails;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@ -34,28 +34,30 @@ import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Tests for {@link OtlpLogsAutoConfiguration}. * Tests for {@link OtlpLoggingAutoConfiguration}.
* *
* @author Toshiaki Maki * @author Toshiaki Maki
*/ */
class OtlpLogsAutoConfigurationTests { class OtlpLoggingAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(OtlpLogsAutoConfiguration.class)); .withConfiguration(AutoConfigurations.of(OtlpLoggingAutoConfiguration.class));
@Test @Test
void shouldNotSupplyBeansIfPropertyIsNotSet() { void shouldNotSupplyBeansIfPropertyIsNotSet() {
this.contextRunner.run((context) -> { this.contextRunner.run((context) -> {
assertThat(context).doesNotHaveBean(OtlpLogsConnectionDetails.class); assertThat(context).doesNotHaveBean(OtlpLoggingConnectionDetails.class);
assertThat(context).doesNotHaveBean(OtlpHttpLogRecordExporter.class); assertThat(context).doesNotHaveBean(OtlpHttpLogRecordExporter.class);
}); });
} }
@Test @Test
void shouldSupplyBeans() { void shouldSupplyBeans() {
this.contextRunner.withPropertyValues("management.otlp.logs.endpoint=http://localhost:4318/v1/logs") this.contextRunner.withPropertyValues("management.otlp.logging.endpoint=http://localhost:4318/v1/logs")
.run((context) -> { .run((context) -> {
assertThat(context).hasSingleBean(OtlpLogsConnectionDetails.class); assertThat(context).hasSingleBean(OtlpLoggingConnectionDetails.class);
OtlpLoggingConnectionDetails connectionDetails = context.getBean(OtlpLoggingConnectionDetails.class);
assertThat(connectionDetails.getEndpoint()).isEqualTo("http://localhost:4318/v1/logs");
assertThat(context).hasSingleBean(OtlpHttpLogRecordExporter.class) assertThat(context).hasSingleBean(OtlpHttpLogRecordExporter.class)
.hasSingleBean(LogRecordExporter.class); .hasSingleBean(LogRecordExporter.class);
}); });
@ -66,7 +68,7 @@ class OtlpLogsAutoConfigurationTests {
"io.opentelemetry.exporter.otlp.http.logs" }) "io.opentelemetry.exporter.otlp.http.logs" })
void shouldNotSupplyBeansIfDependencyIsMissing(String packageName) { void shouldNotSupplyBeansIfDependencyIsMissing(String packageName) {
this.contextRunner.withClassLoader(new FilteredClassLoader(packageName)).run((context) -> { this.contextRunner.withClassLoader(new FilteredClassLoader(packageName)).run((context) -> {
assertThat(context).doesNotHaveBean(OtlpLogsConnectionDetails.class); assertThat(context).doesNotHaveBean(OtlpLoggingConnectionDetails.class);
assertThat(context).doesNotHaveBean(OtlpHttpLogRecordExporter.class); assertThat(context).doesNotHaveBean(OtlpHttpLogRecordExporter.class);
}); });
} }
@ -88,8 +90,8 @@ class OtlpLogsAutoConfigurationTests {
@Test @Test
void shouldBackOffWhenCustomOtlpLogsConnectionDetailsIsDefined() { void shouldBackOffWhenCustomOtlpLogsConnectionDetailsIsDefined() {
this.contextRunner.withUserConfiguration(CustomOtlpLogsConnectionDetails.class).run((context) -> { this.contextRunner.withUserConfiguration(CustomOtlpLogsConnectionDetails.class).run((context) -> {
assertThat(context).hasSingleBean(OtlpLogsConnectionDetails.class) assertThat(context).hasSingleBean(OtlpLoggingConnectionDetails.class)
.doesNotHaveBean(PropertiesOtlpLogsConnectionDetails.class); .doesNotHaveBean(PropertiesOtlpLoggingConnectionDetails.class);
OtlpHttpLogRecordExporter otlpHttpLogRecordExporter = context.getBean(OtlpHttpLogRecordExporter.class); OtlpHttpLogRecordExporter otlpHttpLogRecordExporter = context.getBean(OtlpHttpLogRecordExporter.class);
assertThat(otlpHttpLogRecordExporter).extracting("delegate.httpSender.url") assertThat(otlpHttpLogRecordExporter).extracting("delegate.httpSender.url")
.isEqualTo(HttpUrl.get("https://otel.example.com/v1/logs")); .isEqualTo(HttpUrl.get("https://otel.example.com/v1/logs"));
@ -121,7 +123,7 @@ class OtlpLogsAutoConfigurationTests {
public static class CustomOtlpLogsConnectionDetails { public static class CustomOtlpLogsConnectionDetails {
@Bean @Bean
public OtlpLogsConnectionDetails customOtlpLogsConnectionDetails() { public OtlpLoggingConnectionDetails customOtlpLogsConnectionDetails() {
return () -> "https://otel.example.com/v1/logs"; return () -> "https://otel.example.com/v1/logs";
} }