Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OTLP log export for the OpenTelemetry Spring Starter #8493

Merged
merged 8 commits into from
Jun 8, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies {
compileOnly("io.opentelemetry:opentelemetry-extension-trace-propagators")
compileOnly("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator")
compileOnly("io.opentelemetry:opentelemetry-exporter-logging")
compileOnly("io.opentelemetry:opentelemetry-exporter-otlp-logs")
compileOnly("io.opentelemetry:opentelemetry-exporter-jaeger")
compileOnly("io.opentelemetry:opentelemetry-exporter-otlp")
compileOnly("io.opentelemetry:opentelemetry-exporter-zipkin")
Expand All @@ -62,6 +63,7 @@ dependencies {
testImplementation("io.opentelemetry:opentelemetry-extension-trace-propagators")
testImplementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator")
testImplementation("io.opentelemetry:opentelemetry-exporter-logging")
testImplementation("io.opentelemetry:opentelemetry-exporter-otlp-logs")
testImplementation("io.opentelemetry:opentelemetry-exporter-jaeger")
testImplementation("io.opentelemetry:opentelemetry-exporter-otlp")
testImplementation("io.opentelemetry:opentelemetry-exporter-zipkin")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
package io.opentelemetry.instrumentation.spring.autoconfigure;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.logs.GlobalLoggerProvider;
import io.opentelemetry.api.trace.TracerProvider;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.instrumentation.spring.autoconfigure.resources.SpringResourceConfigProperties;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor;
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
Expand Down Expand Up @@ -70,6 +75,26 @@ public SdkTracerProvider sdkTracerProvider(
.build();
}

@Bean
@ConditionalOnMissingBean
public SdkLoggerProvider sdkLoggerProvider(
ObjectProvider<List<LogRecordExporter>> loggerExportersProvider, Resource otelResource) {

SdkLoggerProviderBuilder loggerProviderBuilder = SdkLoggerProvider.builder();
loggerProviderBuilder.setResource(otelResource);

loggerExportersProvider.getIfAvailable(Collections::emptyList).stream()
.forEach(
loggerExporter ->
loggerProviderBuilder.addLogRecordProcessor(
BatchLogRecordProcessor.builder(loggerExporter).build()));

SdkLoggerProvider loggerProvider = loggerProviderBuilder.build();
jeanbisutti marked this conversation as resolved.
Show resolved Hide resolved
GlobalLoggerProvider.set(loggerProvider);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for the future (next release, actually): we'll have to set GlobalOpenTelemetry if we want appenders to work. Not that there's anything wrong with that, it's just that it's a behavioral change that we'll have to introduce.


return loggerProvider;
}

@Bean
@ConditionalOnMissingBean
public SdkMeterProvider sdkMeterProvider(
Expand Down Expand Up @@ -113,13 +138,15 @@ public Resource otelResource(
public OpenTelemetry openTelemetry(
ObjectProvider<ContextPropagators> propagatorsProvider,
SdkTracerProvider tracerProvider,
SdkMeterProvider meterProvider) {
SdkMeterProvider meterProvider,
SdkLoggerProvider loggerProvider) {

ContextPropagators propagators = propagatorsProvider.getIfAvailable(ContextPropagators::noop);

return OpenTelemetrySdk.builder()
.setTracerProvider(tracerProvider)
.setMeterProvider(meterProvider)
.setLoggerProvider(loggerProvider)
.setPropagators(propagators)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public final class OtlpExporterProperties {
@Nullable private Duration timeout;
private final SignalProperties traces = new SignalProperties();
private final SignalProperties metrics = new SignalProperties();
private final SignalProperties logs = new SignalProperties();

public boolean isEnabled() {
return enabled;
Expand Down Expand Up @@ -62,6 +63,10 @@ public SignalProperties getMetrics() {
return metrics;
}

public SignalProperties getLogs() {
return logs;
}

public static class SignalProperties {

private boolean enabled = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp;

import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter;
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import java.time.Duration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@AutoConfigureBefore(OpenTelemetryAutoConfiguration.class)
@EnableConfigurationProperties(OtlpExporterProperties.class)
@ConditionalOnProperty(
prefix = "otel.exporter.otlp",
name = {"enabled", "logs.enabled"},
matchIfMissing = true)
@ConditionalOnClass(OtlpGrpcLogRecordExporter.class)
public class OtlpLoggerExporterAutoConfiguration {

@Bean
@ConditionalOnMissingBean
public OtlpGrpcLogRecordExporter otelOtlpGrpcLogRecordExporter(
OtlpExporterProperties properties) {
OtlpGrpcLogRecordExporterBuilder builder = OtlpGrpcLogRecordExporter.builder();

String endpoint = properties.getLogs().getEndpoint();
if (endpoint == null) {
endpoint = properties.getEndpoint();
}
if (endpoint != null) {
builder.setEndpoint(endpoint);
}

Duration timeout = properties.getLogs().getTimeout();
if (timeout == null) {
timeout = properties.getTimeout();
}
if (timeout != null) {
builder.setTimeout(timeout);
}

return builder.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.jaeger.JaegerSpa
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingSpanExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLoggerExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.zipkin.ZipkinSpanExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.resttemplate.RestTemplateAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.webclient.WebClientAutoConfiguration,\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.jaeger.JaegerSpa
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingSpanExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLoggerExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.zipkin.ZipkinSpanExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.resttemplate.RestTemplateAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.webclient.WebClientAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.logs.GlobalLoggerProvider;
import io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
Expand All @@ -34,6 +37,11 @@ public OpenTelemetry customOpenTelemetry() {

private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();

@BeforeEach
void resetGlobalLoggerProvider() {
GlobalLoggerProvider.resetForTest();
}

@Test
@DisplayName(
"when Application Context contains OpenTelemetry bean should NOT initialize openTelemetry")
Expand All @@ -47,7 +55,8 @@ void customOpenTelemetry() {
.hasBean("customOpenTelemetry")
.doesNotHaveBean("openTelemetry")
.doesNotHaveBean("sdkTracerProvider")
.doesNotHaveBean("sdkMeterProvider"));
.doesNotHaveBean("sdkMeterProvider")
.doesNotHaveBean("sdkLoggerProvider"));
}

@Test
Expand All @@ -61,7 +70,8 @@ void initializeProvidersAndOpenTelemetry() {
assertThat(context)
.hasBean("openTelemetry")
.hasBean("sdkTracerProvider")
.hasBean("sdkMeterProvider"));
.hasBean("sdkMeterProvider")
.hasBean("sdkLoggerProvider"));
jeanbisutti marked this conversation as resolved.
Show resolved Hide resolved
}

@Test
Expand All @@ -75,6 +85,10 @@ void initializeOpenTelemetryWithCustomProviders() {
() -> SdkTracerProvider.builder().build())
.withBean(
"customMeterProvider", SdkMeterProvider.class, () -> SdkMeterProvider.builder().build())
.withBean(
"customLoggerProvider",
SdkLoggerProvider.class,
() -> SdkLoggerProvider.builder().build())
.withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class))
.run(
context ->
Expand All @@ -83,7 +97,9 @@ void initializeOpenTelemetryWithCustomProviders() {
.hasBean("customTracerProvider")
.doesNotHaveBean("sdkTracerProvider")
.hasBean("customMeterProvider")
.doesNotHaveBean("sdkMeterProvider"));
.doesNotHaveBean("sdkMeterProvider")
.hasBean("customLoggerProvider")
.doesNotHaveBean("sdkLoggerProvider"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

import static org.assertj.core.api.Assertions.assertThat;

import io.opentelemetry.api.logs.GlobalLoggerProvider;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
Expand All @@ -22,6 +24,11 @@ public class TraceAspectAutoConfigurationTest {
AutoConfigurations.of(
OpenTelemetryAutoConfiguration.class, TraceAspectAutoConfiguration.class));

@BeforeEach
void resetGlobalLoggerProvider() {
GlobalLoggerProvider.resetForTest();
}

@Test
@DisplayName("when aspects are ENABLED should initialize WithSpanAspect bean")
void aspectsEnabled() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

import static org.assertj.core.api.Assertions.assertThat;

import io.opentelemetry.api.logs.GlobalLoggerProvider;
import io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
Expand All @@ -23,6 +25,11 @@ class JaegerSpanExporterAutoConfigurationTest {
AutoConfigurations.of(
OpenTelemetryAutoConfiguration.class, JaegerSpanExporterAutoConfiguration.class));

@BeforeEach
void resetGlobalLoggerProvider() {
GlobalLoggerProvider.resetForTest();
}

@Test
@DisplayName("when exporters are ENABLED should initialize JaegerGrpcSpanExporter bean")
void exportersEnabled() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

import static org.assertj.core.api.Assertions.assertThat;

import io.opentelemetry.api.logs.GlobalLoggerProvider;
import io.opentelemetry.exporter.logging.LoggingMetricExporter;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
Expand All @@ -22,6 +24,11 @@ class LoggingMetricExporterAutoConfigurationTest {
OpenTelemetryAutoConfiguration.class,
LoggingMetricExporterAutoConfiguration.class));

@BeforeEach
void resetGlobalLoggerProvider() {
GlobalLoggerProvider.resetForTest();
}

@Test
void loggingEnabled() {
runner
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

import static org.assertj.core.api.Assertions.assertThat;

import io.opentelemetry.api.logs.GlobalLoggerProvider;
import io.opentelemetry.exporter.logging.LoggingSpanExporter;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
Expand All @@ -24,6 +26,11 @@ class LoggingSpanExporterAutoConfigurationTest {
OpenTelemetryAutoConfiguration.class,
LoggingSpanExporterAutoConfiguration.class));

@BeforeEach
void resetGlobalLoggerProvider() {
GlobalLoggerProvider.resetForTest();
}

@Test
@DisplayName("when exporters are ENABLED should initialize LoggingSpanExporter bean")
void loggingEnabled() {
Expand Down
Loading