|
@@ -7,49 +7,31 @@ package io.opentelemetry.instrumentation.spring.autoconfigure;
|
|
|
|
|
|
import io.opentelemetry.api.OpenTelemetry;
|
|
|
import io.opentelemetry.api.trace.TracerProvider;
|
|
|
-import io.opentelemetry.context.propagation.ContextPropagators;
|
|
|
-import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpExporterProperties;
|
|
|
-import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLogRecordExporterAutoConfiguration;
|
|
|
-import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration;
|
|
|
-import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration;
|
|
|
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.MapConverter;
|
|
|
-import io.opentelemetry.instrumentation.spring.autoconfigure.propagators.PropagationProperties;
|
|
|
-import io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration;
|
|
|
-import io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceProperties;
|
|
|
-import io.opentelemetry.instrumentation.spring.autoconfigure.resources.SpringConfigProperties;
|
|
|
-import io.opentelemetry.sdk.OpenTelemetrySdk;
|
|
|
-import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
|
|
+import io.opentelemetry.instrumentation.spring.autoconfigure.properties.OtelResourceProperties;
|
|
|
+import io.opentelemetry.instrumentation.spring.autoconfigure.properties.OtlpExporterProperties;
|
|
|
+import io.opentelemetry.instrumentation.spring.autoconfigure.properties.PropagationProperties;
|
|
|
+import io.opentelemetry.instrumentation.spring.autoconfigure.properties.SpringConfigProperties;
|
|
|
+import io.opentelemetry.instrumentation.spring.autoconfigure.resources.DistroVersionResourceProvider;
|
|
|
+import io.opentelemetry.instrumentation.spring.autoconfigure.resources.SpringResourceProvider;
|
|
|
+import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
|
|
+import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
|
|
|
+import io.opentelemetry.sdk.autoconfigure.internal.ComponentLoader;
|
|
|
+import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
|
|
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;
|
|
|
-import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
|
|
|
-import io.opentelemetry.sdk.metrics.export.PeriodicMetricReaderBuilder;
|
|
|
-import io.opentelemetry.sdk.resources.Resource;
|
|
|
-import io.opentelemetry.sdk.trace.SdkTracerProvider;
|
|
|
-import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
|
|
|
-import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
|
|
|
-import io.opentelemetry.sdk.trace.export.SpanExporter;
|
|
|
-import io.opentelemetry.sdk.trace.samplers.Sampler;
|
|
|
-import java.time.Duration;
|
|
|
-import java.util.Collections;
|
|
|
import java.util.List;
|
|
|
+import java.util.Optional;
|
|
|
+import java.util.stream.Collectors;
|
|
|
import org.springframework.beans.factory.ObjectProvider;
|
|
|
-import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
|
|
-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.context.properties.ConfigurationPropertiesBinding;
|
|
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
|
+import org.springframework.boot.info.BuildProperties;
|
|
|
+import org.springframework.context.ApplicationContext;
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
-import org.springframework.context.annotation.Conditional;
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
import org.springframework.core.env.Environment;
|
|
|
-import org.springframework.expression.spel.standard.SpelExpressionParser;
|
|
|
|
|
|
/**
|
|
|
* Create {@link io.opentelemetry.api.OpenTelemetry} bean if bean is missing.
|
|
@@ -60,7 +42,6 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
|
|
|
*/
|
|
|
@Configuration
|
|
|
@EnableConfigurationProperties({
|
|
|
- SamplerProperties.class,
|
|
|
OtlpExporterProperties.class,
|
|
|
OtelResourceProperties.class,
|
|
|
PropagationProperties.class
|
|
@@ -76,143 +57,54 @@ public class OpenTelemetryAutoConfiguration {
|
|
|
|
|
|
@Bean
|
|
|
@ConfigurationPropertiesBinding
|
|
|
- @Conditional(MapConverterCondition.class)
|
|
|
public MapConverter mapConverter() {
|
|
|
// needed for otlp exporter headers and OtelResourceProperties
|
|
|
return new MapConverter();
|
|
|
}
|
|
|
|
|
|
- static final class MapConverterCondition extends AnyNestedCondition {
|
|
|
- public MapConverterCondition() {
|
|
|
- super(ConfigurationPhase.REGISTER_BEAN);
|
|
|
- }
|
|
|
-
|
|
|
- @ConditionalOnBean(OtelResourceAutoConfiguration.class)
|
|
|
- static class Resource {}
|
|
|
-
|
|
|
- @ConditionalOnBean(OtlpLogRecordExporterAutoConfiguration.class)
|
|
|
- static class Logger {}
|
|
|
-
|
|
|
- @ConditionalOnBean(OtlpSpanExporterAutoConfiguration.class)
|
|
|
- static class Span {}
|
|
|
-
|
|
|
- @ConditionalOnBean(OtlpMetricExporterAutoConfiguration.class)
|
|
|
- static class Metric {}
|
|
|
- }
|
|
|
-
|
|
|
@Bean
|
|
|
- @ConditionalOnMissingBean
|
|
|
- ConfigProperties configProperties(
|
|
|
- Environment env,
|
|
|
- OtlpExporterProperties otlpExporterProperties,
|
|
|
- OtelResourceProperties resourceProperties,
|
|
|
- PropagationProperties propagationProperties) {
|
|
|
- return new SpringConfigProperties(
|
|
|
- env,
|
|
|
- new SpelExpressionParser(),
|
|
|
- otlpExporterProperties,
|
|
|
- resourceProperties,
|
|
|
- propagationProperties);
|
|
|
- }
|
|
|
-
|
|
|
- @Bean(destroyMethod = "") // SDK components are shutdown from the OpenTelemetry instance
|
|
|
- @ConditionalOnMissingBean
|
|
|
- public SdkTracerProvider sdkTracerProvider(
|
|
|
- SamplerProperties samplerProperties,
|
|
|
- ObjectProvider<List<SpanExporter>> spanExportersProvider,
|
|
|
- Resource otelResource) {
|
|
|
- SdkTracerProviderBuilder tracerProviderBuilder = SdkTracerProvider.builder();
|
|
|
-
|
|
|
- spanExportersProvider.getIfAvailable(Collections::emptyList).stream()
|
|
|
- .map(spanExporter -> BatchSpanProcessor.builder(spanExporter).build())
|
|
|
- .forEach(tracerProviderBuilder::addSpanProcessor);
|
|
|
-
|
|
|
- return tracerProviderBuilder
|
|
|
- .setResource(otelResource)
|
|
|
- .setSampler(Sampler.traceIdRatioBased(samplerProperties.getProbability()))
|
|
|
- .build();
|
|
|
- }
|
|
|
-
|
|
|
- @Bean(destroyMethod = "") // SDK components are shutdown from the OpenTelemetry instance
|
|
|
- @ConditionalOnMissingBean
|
|
|
- public SdkLoggerProvider sdkLoggerProvider(
|
|
|
- ObjectProvider<List<LogRecordExporter>> loggerExportersProvider, Resource otelResource) {
|
|
|
-
|
|
|
- SdkLoggerProviderBuilder loggerProviderBuilder = SdkLoggerProvider.builder();
|
|
|
- loggerProviderBuilder.setResource(otelResource);
|
|
|
-
|
|
|
- loggerExportersProvider
|
|
|
- .getIfAvailable(Collections::emptyList)
|
|
|
- .forEach(
|
|
|
- loggerExporter ->
|
|
|
- loggerProviderBuilder.addLogRecordProcessor(
|
|
|
- BatchLogRecordProcessor.builder(loggerExporter).build()));
|
|
|
-
|
|
|
- return loggerProviderBuilder.build();
|
|
|
+ public OpenTelemetrySdkComponentLoader openTelemetrySdkComponentLoader(
|
|
|
+ ApplicationContext applicationContext) {
|
|
|
+ return new OpenTelemetrySdkComponentLoader(applicationContext);
|
|
|
}
|
|
|
|
|
|
- @Bean(destroyMethod = "") // SDK components are shutdown from the OpenTelemetry instance
|
|
|
- @ConditionalOnMissingBean
|
|
|
- public SdkMeterProvider sdkMeterProvider(
|
|
|
- ConfigProperties configProperties,
|
|
|
- ObjectProvider<List<MetricExporter>> metricExportersProvider,
|
|
|
- Resource otelResource) {
|
|
|
-
|
|
|
- SdkMeterProviderBuilder meterProviderBuilder = SdkMeterProvider.builder();
|
|
|
-
|
|
|
- metricExportersProvider.getIfAvailable(Collections::emptyList).stream()
|
|
|
- .map(metricExporter -> createPeriodicMetricReader(configProperties, metricExporter))
|
|
|
- .forEach(meterProviderBuilder::registerMetricReader);
|
|
|
-
|
|
|
- return meterProviderBuilder.setResource(otelResource).build();
|
|
|
- }
|
|
|
-
|
|
|
- private static PeriodicMetricReader createPeriodicMetricReader(
|
|
|
- ConfigProperties properties, MetricExporter metricExporter) {
|
|
|
- PeriodicMetricReaderBuilder metricReaderBuilder =
|
|
|
- PeriodicMetricReader.builder(metricExporter);
|
|
|
- Duration interval = properties.getDuration("otel.metric.export.interval");
|
|
|
- if (interval != null) {
|
|
|
- metricReaderBuilder.setInterval(interval);
|
|
|
- }
|
|
|
- return metricReaderBuilder.build();
|
|
|
+ @Bean
|
|
|
+ public ResourceProvider otelSpringResourceProvider(Optional<BuildProperties> buildProperties) {
|
|
|
+ return new SpringResourceProvider(buildProperties);
|
|
|
}
|
|
|
|
|
|
@Bean
|
|
|
- @ConditionalOnMissingBean
|
|
|
- public Resource otelResource(
|
|
|
- ConfigProperties config, ObjectProvider<List<ResourceProvider>> resourceProviders) {
|
|
|
- Resource resource = Resource.getDefault();
|
|
|
- for (ResourceProvider resourceProvider :
|
|
|
- resourceProviders.getIfAvailable(Collections::emptyList)) {
|
|
|
- resource = resource.merge(resourceProvider.createResource(config));
|
|
|
- }
|
|
|
- return resource;
|
|
|
+ public ResourceProvider otelDistroVersionResourceProvider() {
|
|
|
+ return new DistroVersionResourceProvider();
|
|
|
}
|
|
|
|
|
|
@Bean
|
|
|
// If you change the bean name, also change it in the OpenTelemetryJdbcDriverAutoConfiguration
|
|
|
// class
|
|
|
public OpenTelemetry openTelemetry(
|
|
|
- ObjectProvider<ContextPropagators> propagatorsProvider,
|
|
|
- SdkTracerProvider tracerProvider,
|
|
|
- SdkMeterProvider meterProvider,
|
|
|
- SdkLoggerProvider loggerProvider,
|
|
|
- ObjectProvider<List<OpenTelemetryInjector>> openTelemetryConsumerProvider) {
|
|
|
-
|
|
|
- ContextPropagators propagators = propagatorsProvider.getIfAvailable(ContextPropagators::noop);
|
|
|
-
|
|
|
- OpenTelemetrySdk openTelemetry =
|
|
|
- OpenTelemetrySdk.builder()
|
|
|
- .setTracerProvider(tracerProvider)
|
|
|
- .setMeterProvider(meterProvider)
|
|
|
- .setLoggerProvider(loggerProvider)
|
|
|
- .setPropagators(propagators)
|
|
|
- .build();
|
|
|
-
|
|
|
- List<OpenTelemetryInjector> openTelemetryInjectors =
|
|
|
- openTelemetryConsumerProvider.getIfAvailable(() -> Collections.emptyList());
|
|
|
- openTelemetryInjectors.forEach(consumer -> consumer.accept(openTelemetry));
|
|
|
+ Environment env,
|
|
|
+ OtlpExporterProperties otlpExporterProperties,
|
|
|
+ OtelResourceProperties resourceProperties,
|
|
|
+ PropagationProperties propagationProperties,
|
|
|
+ OpenTelemetrySdkComponentLoader componentLoader,
|
|
|
+ ObjectProvider<OpenTelemetryInjector> openTelemetryConsumerProvider) {
|
|
|
+
|
|
|
+ OpenTelemetry openTelemetry =
|
|
|
+ AutoConfigureUtil.setComponentLoader(
|
|
|
+ AutoConfigureUtil.setConfigPropertiesCustomizer(
|
|
|
+ AutoConfiguredOpenTelemetrySdk.builder(),
|
|
|
+ c ->
|
|
|
+ SpringConfigProperties.create(
|
|
|
+ env,
|
|
|
+ otlpExporterProperties,
|
|
|
+ resourceProperties,
|
|
|
+ propagationProperties,
|
|
|
+ c)),
|
|
|
+ componentLoader)
|
|
|
+ .build()
|
|
|
+ .getOpenTelemetrySdk();
|
|
|
+
|
|
|
+ openTelemetryConsumerProvider.forEach(consumer -> consumer.accept(openTelemetry));
|
|
|
|
|
|
return openTelemetry;
|
|
|
}
|
|
@@ -228,4 +120,29 @@ public class OpenTelemetryAutoConfiguration {
|
|
|
return OpenTelemetry.noop();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The {@link ComponentLoader} is used by the SDK autoconfiguration to load all components, e.g.
|
|
|
+ * <a
|
|
|
+ * href="https://github.com/open-telemetry/opentelemetry-java/blob/4519a7e90243e5b75b3a46a14c872de88b95a9a1/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java#L405-L408">here</a>
|
|
|
+ */
|
|
|
+ public static class OpenTelemetrySdkComponentLoader implements ComponentLoader {
|
|
|
+ private final ApplicationContext applicationContext;
|
|
|
+
|
|
|
+ private final SpiHelper spiHelper =
|
|
|
+ SpiHelper.create(OpenTelemetrySdkComponentLoader.class.getClassLoader());
|
|
|
+
|
|
|
+ public OpenTelemetrySdkComponentLoader(ApplicationContext applicationContext) {
|
|
|
+ this.applicationContext = applicationContext;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public <T> Iterable<T> load(Class<T> spiClass) {
|
|
|
+ List<T> spi = spiHelper.load(spiClass);
|
|
|
+ List<T> beans =
|
|
|
+ applicationContext.getBeanProvider(spiClass).orderedStream().collect(Collectors.toList());
|
|
|
+ spi.addAll(beans);
|
|
|
+ return spi;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|