mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Polish "Provide auto configuration for OpenTelemetry Logs"
See gh-40961
This commit is contained in:
parent
2d6f2488b7
commit
cfa05716ef
@ -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);
|
@ -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;
|
@ -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 {
|
||||||
|
|
||||||
}
|
}
|
@ -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);
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
@ -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 {
|
||||||
|
|
||||||
/**
|
/**
|
@ -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;
|
@ -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;
|
@ -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
|
||||||
|
@ -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
|
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user