From 29aad586940133c5774d965f23f2129841e253b5 Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Thu, 12 Jan 2023 18:15:38 -0600 Subject: [PATCH 1/5] Cleanup autoconfigured resources in case of exception --- sdk-extensions/autoconfigure/build.gradle.kts | 19 --- ...AutoConfiguredOpenTelemetrySdkBuilder.java | 144 ++++++++++------- .../LogRecordExporterConfiguration.java | 9 +- .../LoggerProviderConfiguration.java | 22 ++- .../MeterProviderConfiguration.java | 11 +- .../MetricExporterConfiguration.java | 21 ++- .../SpanExporterConfiguration.java | 27 ++-- .../TracerProviderConfiguration.java | 20 ++- .../AutoConfiguredOpenTelemetrySdkTest.java | 43 +++++ .../LogRecordExporterConfigurationTest.java | 42 +++-- .../LoggerProviderConfigurationTest.java | 31 ++-- .../MeterProviderConfigurationTest.java | 4 +- .../MetricExporterConfigurationTest.java | 15 +- .../TracerProviderConfigurationTest.java | 52 +++--- .../AutoConfiguredOpenTelemetrySdkTest.java | 43 +++-- .../sdk/autoconfigure/ConfigErrorTest.java | 9 ++ .../ConfigurableLogRecordExporterTest.java | 24 ++- .../ConfigurableMetricExporterTest.java | 97 ++++++----- .../ConfigurableSpanExporterTest.java | 152 ++++++++++++------ .../sdk/autoconfigure/FullConfigTest.java | 11 +- .../LoggerProviderConfigurationTest.java | 55 ++++--- .../MetricExporterConfigurationTest.java | 35 ++-- .../SpanExporterConfigurationTest.java | 7 +- .../internal/testing/CleanupExtension.java | 37 +++++ 24 files changed, 619 insertions(+), 311 deletions(-) rename sdk-extensions/autoconfigure/src/{testInitializeRegistersGlobal => testFullConfig}/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java (56%) rename sdk-extensions/autoconfigure/src/{testConfigError => testFullConfig}/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java (91%) create mode 100644 testing-internal/src/main/java/io/opentelemetry/internal/testing/CleanupExtension.java diff --git a/sdk-extensions/autoconfigure/build.gradle.kts b/sdk-extensions/autoconfigure/build.gradle.kts index 2a9fa1592a2..67756cf62ac 100644 --- a/sdk-extensions/autoconfigure/build.gradle.kts +++ b/sdk-extensions/autoconfigure/build.gradle.kts @@ -51,13 +51,6 @@ testing { } } } - val testConfigError by registering(JvmTestSuite::class) { - dependencies { - implementation(project(":extensions:trace-propagators")) - implementation(project(":exporters:otlp:all")) - implementation(project(":exporters:otlp:logs")) - } - } val testFullConfig by registering(JvmTestSuite::class) { dependencies { implementation(project(":extensions:trace-propagators")) @@ -86,8 +79,6 @@ testing { environment("OTEL_LOGS_EXPORTER", "otlp") environment("OTEL_RESOURCE_ATTRIBUTES", "service.name=test,cat=meow") environment("OTEL_PROPAGATORS", "tracecontext,baggage,b3,b3multi,jaeger,ottrace,test") - environment("OTEL_BSP_SCHEDULE_DELAY", "10") - environment("OTEL_METRIC_EXPORT_INTERVAL", "10") environment("OTEL_EXPORTER_OTLP_HEADERS", "cat=meow,dog=bark") environment("OTEL_EXPORTER_OTLP_TIMEOUT", "5000") environment("OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", "2") @@ -97,16 +88,6 @@ testing { } } } - val testInitializeRegistersGlobal by registering(JvmTestSuite::class) { - targets { - all { - testTask { - environment("OTEL_TRACES_EXPORTER", "none") - environment("OTEL_METRICS_EXPORTER", "none") - } - } - } - } } } diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java index ff670471cf0..0e625be2da0 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java @@ -16,6 +16,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.logs.SdkLoggerProvider; import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder; @@ -28,6 +29,8 @@ import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import io.opentelemetry.sdk.trace.export.SpanExporter; import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.io.Closeable; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -329,66 +332,93 @@ public AutoConfiguredOpenTelemetrySdk build() { Resource resource = ResourceConfiguration.configureResource(config, serviceClassLoader, resourceCustomizer); - OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder().build(); - boolean sdkEnabled = !config.getBoolean("otel.sdk.disabled", false); - - if (sdkEnabled) { - SdkMeterProviderBuilder meterProviderBuilder = SdkMeterProvider.builder(); - meterProviderBuilder.setResource(resource); - MeterProviderConfiguration.configureMeterProvider( - meterProviderBuilder, config, serviceClassLoader, metricExporterCustomizer); - meterProviderBuilder = meterProviderCustomizer.apply(meterProviderBuilder, config); - SdkMeterProvider meterProvider = meterProviderBuilder.build(); - - SdkTracerProviderBuilder tracerProviderBuilder = SdkTracerProvider.builder(); - tracerProviderBuilder.setResource(resource); - TracerProviderConfiguration.configureTracerProvider( - tracerProviderBuilder, - config, - serviceClassLoader, - meterProvider, - spanExporterCustomizer, - samplerCustomizer); - tracerProviderBuilder = tracerProviderCustomizer.apply(tracerProviderBuilder, config); - SdkTracerProvider tracerProvider = tracerProviderBuilder.build(); - - SdkLoggerProviderBuilder loggerProviderBuilder = SdkLoggerProvider.builder(); - loggerProviderBuilder.setResource(resource); - LoggerProviderConfiguration.configureLoggerProvider( - loggerProviderBuilder, - config, - serviceClassLoader, - meterProvider, - logRecordExporterCustomizer); - loggerProviderBuilder = loggerProviderCustomizer.apply(loggerProviderBuilder, config); - SdkLoggerProvider loggerProvider = loggerProviderBuilder.build(); - - ContextPropagators propagators = - PropagatorConfiguration.configurePropagators( - config, serviceClassLoader, propagatorCustomizer); - - OpenTelemetrySdkBuilder sdkBuilder = - OpenTelemetrySdk.builder() - .setTracerProvider(tracerProvider) - .setLoggerProvider(loggerProvider) - .setMeterProvider(meterProvider) - .setPropagators(propagators); - - openTelemetrySdk = sdkBuilder.build(); - - if (registerShutdownHook) { - Runtime.getRuntime().addShutdownHook(new Thread(openTelemetrySdk::close)); + // Track any closeable resources created throughout configuration. If an exception short + // circuits configuration, partially configured components will be closed. + List closeables = new ArrayList<>(); + + try { + OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder().build(); + boolean sdkEnabled = !config.getBoolean("otel.sdk.disabled", false); + + if (sdkEnabled) { + SdkMeterProviderBuilder meterProviderBuilder = SdkMeterProvider.builder(); + meterProviderBuilder.setResource(resource); + MeterProviderConfiguration.configureMeterProvider( + meterProviderBuilder, config, serviceClassLoader, metricExporterCustomizer, closeables); + meterProviderBuilder = meterProviderCustomizer.apply(meterProviderBuilder, config); + SdkMeterProvider meterProvider = meterProviderBuilder.build(); + closeables.add(meterProvider); + + SdkTracerProviderBuilder tracerProviderBuilder = SdkTracerProvider.builder(); + tracerProviderBuilder.setResource(resource); + TracerProviderConfiguration.configureTracerProvider( + tracerProviderBuilder, + config, + serviceClassLoader, + meterProvider, + spanExporterCustomizer, + samplerCustomizer, + closeables); + tracerProviderBuilder = tracerProviderCustomizer.apply(tracerProviderBuilder, config); + SdkTracerProvider tracerProvider = tracerProviderBuilder.build(); + closeables.add(tracerProvider); + + SdkLoggerProviderBuilder loggerProviderBuilder = SdkLoggerProvider.builder(); + loggerProviderBuilder.setResource(resource); + LoggerProviderConfiguration.configureLoggerProvider( + loggerProviderBuilder, + config, + serviceClassLoader, + meterProvider, + logRecordExporterCustomizer, + closeables); + loggerProviderBuilder = loggerProviderCustomizer.apply(loggerProviderBuilder, config); + SdkLoggerProvider loggerProvider = loggerProviderBuilder.build(); + closeables.add(loggerProvider); + + if (registerShutdownHook) { + Runtime.getRuntime().addShutdownHook(new Thread(openTelemetrySdk::close)); + } + + ContextPropagators propagators = + PropagatorConfiguration.configurePropagators( + config, serviceClassLoader, propagatorCustomizer); + + OpenTelemetrySdkBuilder sdkBuilder = + OpenTelemetrySdk.builder() + .setTracerProvider(tracerProvider) + .setLoggerProvider(loggerProvider) + .setMeterProvider(meterProvider) + .setPropagators(propagators); + + openTelemetrySdk = sdkBuilder.build(); } - } - if (setResultAsGlobal) { - GlobalOpenTelemetry.set(openTelemetrySdk); - GlobalLoggerProvider.set(openTelemetrySdk.getSdkLoggerProvider()); - logger.log( - Level.FINE, "Global OpenTelemetry set to {0} by autoconfiguration", openTelemetrySdk); - } + if (setResultAsGlobal) { + GlobalOpenTelemetry.set(openTelemetrySdk); + GlobalLoggerProvider.set(openTelemetrySdk.getSdkLoggerProvider()); + logger.log( + Level.FINE, "Global OpenTelemetry set to {0} by autoconfiguration", openTelemetrySdk); + } - return AutoConfiguredOpenTelemetrySdk.create(openTelemetrySdk, resource, config); + return AutoConfiguredOpenTelemetrySdk.create(openTelemetrySdk, resource, config); + } catch (RuntimeException e) { + logger.info( + "Error encountered during autoconfiguration. Closing partially configured components."); + for (Closeable closeable : closeables) { + try { + logger.fine("Closing " + closeable.getClass().getName()); + closeable.close(); + } catch (IOException ex) { + logger.warning( + "Error closing " + closeable.getClass().getName() + ": " + ex.getMessage()); + } + } + if (e instanceof ConfigurationException) { + throw e; + } + throw new ConfigurationException("Unexpected configuration error", e); + } } @SuppressWarnings("deprecation") // Support deprecated SdkTracerProviderConfigurer diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java index aad0105ec8c..a712ee30397 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java @@ -10,8 +10,10 @@ import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider; import io.opentelemetry.sdk.logs.export.LogRecordExporter; +import java.io.Closeable; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; @@ -33,7 +35,8 @@ static Map configureLogRecordExporters( ConfigProperties config, ClassLoader serviceClassLoader, BiFunction - logRecordExporterCustomizer) { + logRecordExporterCustomizer, + List closeables) { Set exporterNames = DefaultConfigProperties.getSet(config, "otel.logs.exporter"); // Default to no exporter @@ -55,8 +58,12 @@ static Map configureLogRecordExporters( Map exportersByName = new HashMap<>(); for (String name : exporterNames) { LogRecordExporter logRecordExporter = configureExporter(name, spiExportersManager); + closeables.add(logRecordExporter); LogRecordExporter customizedLogRecordExporter = logRecordExporterCustomizer.apply(logRecordExporter, config); + if (customizedLogRecordExporter != logRecordExporter) { + closeables.add(customizedLogRecordExporter); + } exportersByName.put(name, customizedLogRecordExporter); } diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfiguration.java index 1f31f70defa..c83bf34728d 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfiguration.java @@ -17,6 +17,7 @@ import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessorBuilder; import io.opentelemetry.sdk.logs.export.LogRecordExporter; import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor; +import java.io.Closeable; import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; @@ -32,14 +33,16 @@ static void configureLoggerProvider( ClassLoader serviceClassLoader, MeterProvider meterProvider, BiFunction - logRecordExporterCustomizer) { + logRecordExporterCustomizer, + List closeables) { loggerProviderBuilder.setLogLimits(() -> configureLogLimits(config)); Map exportersByName = - configureLogRecordExporters(config, serviceClassLoader, logRecordExporterCustomizer); + configureLogRecordExporters( + config, serviceClassLoader, logRecordExporterCustomizer, closeables); - configureLogRecordProcessors(config, exportersByName, meterProvider) + configureLogRecordProcessors(config, exportersByName, meterProvider, closeables) .forEach(loggerProviderBuilder::addLogRecordProcessor); } @@ -47,20 +50,25 @@ static void configureLoggerProvider( static List configureLogRecordProcessors( ConfigProperties config, Map exportersByName, - MeterProvider meterProvider) { + MeterProvider meterProvider, + List closeables) { Map exportersByNameCopy = new HashMap<>(exportersByName); List logRecordProcessors = new ArrayList<>(); LogRecordExporter exporter = exportersByNameCopy.remove("logging"); if (exporter != null) { - logRecordProcessors.add(SimpleLogRecordProcessor.create(exporter)); + LogRecordProcessor logRecordProcessor = SimpleLogRecordProcessor.create(exporter); + closeables.add(logRecordProcessor); + logRecordProcessors.add(logRecordProcessor); } if (!exportersByNameCopy.isEmpty()) { LogRecordExporter compositeLogRecordExporter = LogRecordExporter.composite(exportersByNameCopy.values()); - logRecordProcessors.add( - configureBatchLogRecordProcessor(config, compositeLogRecordExporter, meterProvider)); + LogRecordProcessor logRecordProcessor = + configureBatchLogRecordProcessor(config, compositeLogRecordExporter, meterProvider); + closeables.add(logRecordProcessor); + logRecordProcessors.add(logRecordProcessor); } return logRecordProcessors; diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfiguration.java index 186b4f6c725..aaab88488f5 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfiguration.java @@ -13,6 +13,7 @@ import io.opentelemetry.sdk.metrics.export.MetricReader; import io.opentelemetry.sdk.metrics.internal.SdkMeterProviderUtil; import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter; +import java.io.Closeable; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -28,7 +29,8 @@ static void configureMeterProvider( ConfigProperties config, ClassLoader serviceClassLoader, BiFunction - metricExporterCustomizer) { + metricExporterCustomizer, + List closeables) { // Configure default exemplar filters. String exemplarFilter = @@ -46,7 +48,7 @@ static void configureMeterProvider( break; } - configureMetricReaders(config, serviceClassLoader, metricExporterCustomizer) + configureMetricReaders(config, serviceClassLoader, metricExporterCustomizer, closeables) .forEach(meterProviderBuilder::registerMetricReader); } @@ -54,7 +56,8 @@ static List configureMetricReaders( ConfigProperties config, ClassLoader serviceClassLoader, BiFunction - metricExporterCustomizer) { + metricExporterCustomizer, + List closeables) { Set exporterNames = DefaultConfigProperties.getSet(config, "otel.metrics.exporter"); if (exporterNames.contains("none")) { if (exporterNames.size() > 1) { @@ -71,7 +74,7 @@ static List configureMetricReaders( .map( exporterName -> MetricExporterConfiguration.configureReader( - exporterName, config, serviceClassLoader, metricExporterCustomizer)) + exporterName, config, serviceClassLoader, metricExporterCustomizer, closeables)) .filter(Objects::nonNull) .collect(Collectors.toList()); } diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java index cb9411eeb7f..b7eacfc0644 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java @@ -11,8 +11,10 @@ import io.opentelemetry.sdk.metrics.export.MetricExporter; import io.opentelemetry.sdk.metrics.export.MetricReader; import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import java.io.Closeable; import java.time.Duration; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.BiFunction; import javax.annotation.Nullable; @@ -35,7 +37,8 @@ static MetricReader configureReader( ConfigProperties config, ClassLoader serviceClassLoader, BiFunction - metricExporterCustomizer) { + metricExporterCustomizer, + List closeables) { if (name.equals("prometheus")) { // PrometheusHttpServer is implemented as MetricReader (not MetricExporter) and uses // the AutoConfigurationCustomizer#addMeterProviderCustomizer SPI hook instead of @@ -53,11 +56,19 @@ static MetricReader configureReader( metricExporterSpiManager(config, serviceClassLoader); MetricExporter metricExporter = configureExporter(name, spiExportersManager); - metricExporter = metricExporterCustomizer.apply(metricExporter, config); + closeables.add(metricExporter); + MetricExporter customizedMetricExporter = + metricExporterCustomizer.apply(metricExporter, config); + if (customizedMetricExporter != metricExporter) { + closeables.add(customizedMetricExporter); + } - return PeriodicMetricReader.builder(metricExporter) - .setInterval(config.getDuration("otel.metric.export.interval", DEFAULT_EXPORT_INTERVAL)) - .build(); + MetricReader reader = + PeriodicMetricReader.builder(customizedMetricExporter) + .setInterval(config.getDuration("otel.metric.export.interval", DEFAULT_EXPORT_INTERVAL)) + .build(); + closeables.add(reader); + return reader; } // Visible for testing diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java index 93bec0b55a4..c1dd0824ad6 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java @@ -5,19 +5,18 @@ package io.opentelemetry.sdk.autoconfigure; -import static java.util.stream.Collectors.toMap; - import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider; import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.io.Closeable; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; -import java.util.function.Function; final class SpanExporterConfiguration { @@ -38,7 +37,8 @@ static Map configureSpanExporters( ConfigProperties config, ClassLoader serviceClassLoader, BiFunction - spanExporterCustomizer) { + spanExporterCustomizer, + List closeables) { Set exporterNames = DefaultConfigProperties.getSet(config, "otel.traces.exporter"); if (exporterNames.contains(EXPORTER_NONE)) { if (exporterNames.size() > 1) { @@ -50,6 +50,7 @@ static Map configureSpanExporters( if (customized == noop) { return Collections.emptyMap(); } + closeables.add(customized); return Collections.singletonMap(EXPORTER_NONE, customized); } @@ -60,13 +61,17 @@ static Map configureSpanExporters( NamedSpiManager spiExportersManager = spanExporterSpiManager(config, serviceClassLoader); - return exporterNames.stream() - .collect( - toMap( - Function.identity(), - exporterName -> - spanExporterCustomizer.apply( - configureExporter(exporterName, spiExportersManager), config))); + Map map = new HashMap<>(); + for (String exporterName : exporterNames) { + SpanExporter spanExporter = configureExporter(exporterName, spiExportersManager); + closeables.add(spanExporter); + SpanExporter customizedSpanExporter = spanExporterCustomizer.apply(spanExporter, config); + if (customizedSpanExporter != spanExporter) { + closeables.add(customizedSpanExporter); + } + map.put(exporterName, customizedSpanExporter); + } + return Collections.unmodifiableMap(map); } // Visible for testing diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfiguration.java index 8493fe13611..05b87b756a3 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfiguration.java @@ -18,6 +18,7 @@ import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; import io.opentelemetry.sdk.trace.export.SpanExporter; import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.io.Closeable; import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; @@ -37,7 +38,8 @@ static void configureTracerProvider( MeterProvider meterProvider, BiFunction spanExporterCustomizer, - BiFunction samplerCustomizer) { + BiFunction samplerCustomizer, + List closeables) { tracerProviderBuilder.setSpanLimits(configureSpanLimits(config)); @@ -47,27 +49,33 @@ static void configureTracerProvider( Map exportersByName = SpanExporterConfiguration.configureSpanExporters( - config, serviceClassLoader, spanExporterCustomizer); + config, serviceClassLoader, spanExporterCustomizer, closeables); - configureSpanProcessors(config, exportersByName, meterProvider) + configureSpanProcessors(config, exportersByName, meterProvider, closeables) .forEach(tracerProviderBuilder::addSpanProcessor); } static List configureSpanProcessors( ConfigProperties config, Map exportersByName, - MeterProvider meterProvider) { + MeterProvider meterProvider, + List closeables) { Map exportersByNameCopy = new HashMap<>(exportersByName); List spanProcessors = new ArrayList<>(); SpanExporter exporter = exportersByNameCopy.remove("logging"); if (exporter != null) { - spanProcessors.add(SimpleSpanProcessor.create(exporter)); + SpanProcessor spanProcessor = SimpleSpanProcessor.create(exporter); + closeables.add(spanProcessor); + spanProcessors.add(spanProcessor); } if (!exportersByNameCopy.isEmpty()) { SpanExporter compositeSpanExporter = SpanExporter.composite(exportersByNameCopy.values()); - spanProcessors.add(configureBatchSpanProcessor(config, compositeSpanExporter, meterProvider)); + SpanProcessor spanProcessor = + configureBatchSpanProcessor(config, compositeSpanExporter, meterProvider); + closeables.add(spanProcessor); + spanProcessors.add(spanProcessor); } return spanProcessors; diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java index 56a6b99f248..5c18e7322e7 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java @@ -8,7 +8,9 @@ import static io.opentelemetry.api.common.AttributeKey.stringKey; import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -27,6 +29,7 @@ import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.logs.LogRecordProcessor; import io.opentelemetry.sdk.logs.SdkLoggerProvider; @@ -60,8 +63,11 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; @ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) class AutoConfiguredOpenTelemetrySdkTest { @Mock private IdGenerator idGenerator; @@ -439,4 +445,41 @@ void testNonStringProperties() { assertThat(value3).isEqualTo("7"); }); } + + @Test + void configurationError_ClosesResources() { + // AutoConfiguredOpenTelemetrySdk should close partially configured resources if an exception + // short circuits configuration. Verify that SdkTracerProvider, SdkMeterProvider, and + // SdkLoggerProvider + // are closed when configuration fails late due to an invalid propagator. + SdkTracerProvider tracerProvider = mock(SdkTracerProvider.class); + SdkMeterProvider meterProvider = mock(SdkMeterProvider.class); + SdkLoggerProvider loggerProvider = mock(SdkLoggerProvider.class); + SdkTracerProviderBuilder tracerProviderBuilder = mock(SdkTracerProviderBuilder.class); + SdkMeterProviderBuilder meterProviderBuilder = mock(SdkMeterProviderBuilder.class); + SdkLoggerProviderBuilder loggerProviderBuilder = mock(SdkLoggerProviderBuilder.class); + when(tracerProviderBuilder.build()).thenReturn(tracerProvider); + when(meterProviderBuilder.build()).thenReturn(meterProvider); + when(loggerProviderBuilder.build()).thenReturn(loggerProvider); + + assertThatThrownBy( + () -> + // Override the provider builders with mocks which we can verify are closed + AutoConfiguredOpenTelemetrySdk.builder() + .addTracerProviderCustomizer((u1, u2) -> tracerProviderBuilder) + .addMeterProviderCustomizer((u1, u2) -> meterProviderBuilder) + .addLoggerProviderCustomizer((u1, u2) -> loggerProviderBuilder) + .addPropertiesSupplier(() -> singletonMap("otel.metrics.exporter", "none")) + .addPropertiesSupplier(() -> singletonMap("otel.traces.exporter", "none")) + .addPropertiesSupplier(() -> singletonMap("otel.logs.exporter", "none")) + .addPropertiesSupplier(() -> singletonMap("otel.propagators", "foo")) + .setResultAsGlobal(false) + .build()) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Unrecognized value for otel.propagators"); + + verify(tracerProvider).close(); + verify(meterProvider).close(); + verify(loggerProvider).close(); + } } diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfigurationTest.java index a97ba27e010..d1533f034c7 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfigurationTest.java @@ -6,18 +6,25 @@ package io.opentelemetry.sdk.autoconfigure; import static io.opentelemetry.sdk.autoconfigure.LogRecordExporterConfiguration.configureExporter; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.common.collect.ImmutableMap; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.logs.export.LogRecordExporter; +import java.io.Closeable; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; class LogRecordExporterConfigurationTest { + @RegisterExtension CleanupExtension cleanup = new CleanupExtension(); + @Test void configureExporter_KnownSpiExportersNotOnClasspath() { NamedSpiManager spiExportersManager = @@ -48,46 +55,55 @@ void configureExporter_KnownSpiExportersNotOnClasspath() { @Test void configureLogRecordExporters_duplicates() { - ConfigProperties config = - DefaultConfigProperties.createForTest(ImmutableMap.of("otel.logs.exporter", "otlp,otlp")); + List closeables = new ArrayList<>(); assertThatThrownBy( () -> LogRecordExporterConfiguration.configureLogRecordExporters( - config, + DefaultConfigProperties.createForTest( + ImmutableMap.of("otel.logs.exporter", "otlp,otlp")), LogRecordExporterConfiguration.class.getClassLoader(), - (a, unused) -> a)) + (a, unused) -> a, + closeables)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("otel.logs.exporter contains duplicates: [otlp]"); + cleanup.addCloseables(closeables); + assertThat(closeables).isEmpty(); } @Test void configureLogRecordExporters_unrecognized() { - ConfigProperties config = - DefaultConfigProperties.createForTest(ImmutableMap.of("otel.logs.exporter", "foo")); + List closeables = new ArrayList<>(); assertThatThrownBy( () -> LogRecordExporterConfiguration.configureLogRecordExporters( - config, + DefaultConfigProperties.createForTest( + ImmutableMap.of("otel.logs.exporter", "foo")), LogRecordExporterConfiguration.class.getClassLoader(), - (a, unused) -> a)) + (a, unused) -> a, + new ArrayList<>())) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("Unrecognized value for otel.logs.exporter: foo"); + cleanup.addCloseables(closeables); + assertThat(closeables).isEmpty(); } @Test void configureLogRecordExporters_multipleWithNone() { - ConfigProperties config = - DefaultConfigProperties.createForTest(ImmutableMap.of("otel.logs.exporter", "otlp,none")); + List closeables = new ArrayList<>(); assertThatThrownBy( () -> LogRecordExporterConfiguration.configureLogRecordExporters( - config, + DefaultConfigProperties.createForTest( + ImmutableMap.of("otel.logs.exporter", "otlp,none")), LogRecordExporterConfiguration.class.getClassLoader(), - (a, unused) -> a)) + (a, unused) -> a, + closeables)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("otel.logs.exporter contains none along with other exporters"); + cleanup.addCloseables(closeables); + assertThat(closeables).isEmpty(); } } diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfigurationTest.java index 9c5ccb84afd..5eda442a27d 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfigurationTest.java @@ -10,23 +10,25 @@ import com.google.common.collect.ImmutableMap; import io.opentelemetry.api.metrics.MeterProvider; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.logs.LogLimits; import io.opentelemetry.sdk.logs.LogRecordProcessor; import io.opentelemetry.sdk.logs.SdkLoggerProvider; import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder; -import io.opentelemetry.sdk.trace.SpanLimits; +import java.io.Closeable; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.function.Supplier; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; class LoggerProviderConfigurationTest { - private static final ConfigProperties EMPTY = - DefaultConfigProperties.createForTest(Collections.emptyMap()); + @RegisterExtension CleanupExtension cleanup = new CleanupExtension(); @Test void configureLoggerProvider() { @@ -34,6 +36,7 @@ void configureLoggerProvider() { ImmutableMap.of( "otel.logs.exporter", "none", "otel.attribute.count.limit", "5"); + List closeables = new ArrayList<>(); // We don't have any exporters on classpath for this test so check no-op case. Exporter cases // are verified in other test sets like testFullConfig. @@ -43,10 +46,11 @@ void configureLoggerProvider() { DefaultConfigProperties.createForTest(properties), LoggerProviderConfiguration.class.getClassLoader(), MeterProvider.noop(), - (a, unused) -> a); - SdkLoggerProvider loggerProvider = builder.build(); + (a, unused) -> a, + closeables); + cleanup.addCloseables(closeables); - try { + try (SdkLoggerProvider loggerProvider = builder.build()) { assertThat(loggerProvider) .extracting("sharedState") .satisfies( @@ -60,18 +64,19 @@ void configureLoggerProvider() { .extracting(supplier -> (LogLimits) supplier.get()) .isEqualTo(LogLimits.builder().setMaxNumberOfAttributes(5).build()); }); - } finally { - loggerProvider.shutdown(); + assertThat(closeables).isEmpty(); } } @Test - void configureSpanLimits() { - assertThat(LoggerProviderConfiguration.configureLogLimits(EMPTY)) + void configureLogLimits() { + assertThat( + LoggerProviderConfiguration.configureLogLimits( + DefaultConfigProperties.createForTest(Collections.emptyMap()))) .isEqualTo(LogLimits.getDefault()); - SpanLimits config = - TracerProviderConfiguration.configureSpanLimits( + LogLimits config = + LoggerProviderConfiguration.configureLogLimits( DefaultConfigProperties.createForTest( ImmutableMap.of( "otel.attribute.value.length.limit", "100", diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java index e26fc8cda64..aebd2c85611 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java @@ -15,6 +15,7 @@ import io.opentelemetry.sdk.metrics.internal.exemplar.AlwaysOnFilter; import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter; import io.opentelemetry.sdk.metrics.internal.exemplar.TraceBasedExemplarFilter; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -51,7 +52,8 @@ private static ObjectAssert assertExemplarFilter(Map a); + (a, b) -> a, + new ArrayList<>()); return assertThat(builder) .extracting("exemplarFilter", as(InstanceOfAssertFactories.type(ExemplarFilter.class))); } diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java index c5d6f5187d4..3b67873a224 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java @@ -7,33 +7,46 @@ import static io.opentelemetry.sdk.autoconfigure.MetricExporterConfiguration.configureExporter; import static io.opentelemetry.sdk.autoconfigure.MetricExporterConfiguration.configureReader; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.metrics.export.MetricExporter; +import java.io.Closeable; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; class MetricExporterConfigurationTest { private static final ConfigProperties EMPTY = DefaultConfigProperties.createForTest(Collections.emptyMap()); + @RegisterExtension CleanupExtension cleanup = new CleanupExtension(); + @Test void configureReader_PrometheusNotOnClasspath() { + List closeables = new ArrayList<>(); + assertThatThrownBy( () -> configureReader( "prometheus", EMPTY, MetricExporterConfiguration.class.getClassLoader(), - (a, b) -> a)) + (a, b) -> a, + new ArrayList<>())) .isInstanceOf(ConfigurationException.class) .hasMessage( "otel.metrics.exporter set to \"prometheus\" but opentelemetry-exporter-prometheus" + " not found on classpath. Make sure to add it as a dependency."); + cleanup.addCloseables(closeables); + assertThat(closeables).isEmpty(); } @Test diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfigurationTest.java index db56602d21c..26259d8fe87 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfigurationTest.java @@ -10,13 +10,12 @@ import static org.mockito.Mockito.when; import com.google.common.collect.ImmutableMap; -import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.MeterProvider; +import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import io.opentelemetry.sdk.trace.SpanLimits; @@ -25,21 +24,23 @@ import io.opentelemetry.sdk.trace.export.SpanExporter; import io.opentelemetry.sdk.trace.internal.JcTools; import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.io.Closeable; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Queue; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; -// NB: We use AssertJ extracting to reflectively access implementation details to test configuration -// because the use of BatchSpanProcessor makes it difficult to verify values through public means. @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) class TracerProviderConfigurationTest { @@ -47,6 +48,8 @@ class TracerProviderConfigurationTest { private static final ConfigProperties EMPTY = DefaultConfigProperties.createForTest(Collections.emptyMap()); + @RegisterExtension CleanupExtension cleanup = new CleanupExtension(); + @Mock private SpanExporter mockSpanExporter; @BeforeEach @@ -60,44 +63,39 @@ void configureTracerProvider() { properties.put("otel.bsp.schedule.delay", "100000"); properties.put("otel.traces.sampler", "always_off"); properties.put("otel.traces.exporter", "none"); + List closeables = new ArrayList<>(); - Resource resource = Resource.create(Attributes.builder().put("cat", "meow").build()); // We don't have any exporters on classpath for this test so check no-op case. Exporter cases // are verified in other test sets like testFullConfig. - SdkTracerProviderBuilder tracerProviderBuilder = - SdkTracerProvider.builder().setResource(resource); + SdkTracerProviderBuilder tracerProviderBuilder = SdkTracerProvider.builder(); TracerProviderConfiguration.configureTracerProvider( tracerProviderBuilder, DefaultConfigProperties.createForTest(properties), TracerProviderConfiguration.class.getClassLoader(), MeterProvider.noop(), (a, unused) -> a, - (a, unused) -> a); - SdkTracerProvider tracerProvider = tracerProviderBuilder.build(); - try { + (a, unused) -> a, + closeables); + + try (SdkTracerProvider tracerProvider = tracerProviderBuilder.build()) { assertThat(tracerProvider.getSampler()).isEqualTo(Sampler.alwaysOff()); assertThat(tracerProvider) .extracting("sharedState") .satisfies( - sharedState -> { - assertThat(sharedState).extracting("resource").isEqualTo(resource); - assertThat(sharedState) - .extracting("activeSpanProcessor") - .isEqualTo(SpanProcessor.composite()); - }); - } finally { - tracerProvider.shutdown(); + sharedState -> + assertThat(sharedState) + .extracting("activeSpanProcessor") + .isEqualTo(SpanProcessor.composite())); + assertThat(closeables).isEmpty(); } } @Test void configureBatchSpanProcessor_empty() { - BatchSpanProcessor processor = + try (BatchSpanProcessor processor = TracerProviderConfiguration.configureBatchSpanProcessor( - EMPTY, mockSpanExporter, MeterProvider.noop()); - - try { + EMPTY, mockSpanExporter, MeterProvider.noop())) { assertThat(processor) .extracting("worker") .satisfies( @@ -115,8 +113,6 @@ void configureBatchSpanProcessor_empty() { Queue.class, queue -> assertThat(JcTools.capacity(queue)).isEqualTo(2048)); assertThat(worker).extracting("spanExporter").isEqualTo(mockSpanExporter); }); - } finally { - processor.shutdown(); } } @@ -128,13 +124,11 @@ void configureBatchSpanProcessor_configured() { properties.put("otel.bsp.max.export.batch.size", "3"); properties.put("otel.bsp.export.timeout", "4"); - BatchSpanProcessor processor = + try (BatchSpanProcessor processor = TracerProviderConfiguration.configureBatchSpanProcessor( DefaultConfigProperties.createForTest(properties), mockSpanExporter, - MeterProvider.noop()); - - try { + MeterProvider.noop())) { assertThat(processor) .extracting("worker") .satisfies( @@ -152,8 +146,6 @@ void configureBatchSpanProcessor_configured() { Queue.class, queue -> assertThat(JcTools.capacity(queue)).isEqualTo(2)); assertThat(worker).extracting("spanExporter").isEqualTo(mockSpanExporter); }); - } finally { - processor.shutdown(); } } diff --git a/sdk-extensions/autoconfigure/src/testInitializeRegistersGlobal/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java similarity index 56% rename from sdk-extensions/autoconfigure/src/testInitializeRegistersGlobal/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java rename to sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java index 02113ad5a10..0772a7a8259 100644 --- a/sdk-extensions/autoconfigure/src/testInitializeRegistersGlobal/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java @@ -12,11 +12,14 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.logs.GlobalLoggerProvider; import io.opentelemetry.sdk.OpenTelemetrySdk; +import java.lang.reflect.Field; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.junitpioneer.jupiter.SetSystemProperty; +@SetSystemProperty(key = "otel.traces.exporter", value = "none") +@SetSystemProperty(key = "otel.metrics.exporter", value = "none") class AutoConfiguredOpenTelemetrySdkTest { @RegisterExtension @@ -30,24 +33,23 @@ void setUp() { @Test void initializeAndGet() { - OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); - assertThat(GlobalOpenTelemetry.get()) - // ObfuscatedOpenTelemetry - .extracting("delegate") - .isSameAs(sdk); + try (OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk()) { + assertThat(GlobalOpenTelemetry.get()) + // ObfuscatedOpenTelemetry + .extracting("delegate") + .isSameAs(sdk); + } } @Test void initializeAndGet_noGlobal() { - OpenTelemetrySdk sdk = + try (OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.builder() .setResultAsGlobal(false) .build() - .getOpenTelemetrySdk(); - // TODO: calling get() will call initialize() again and autoconfigure another instance of the - // SDK; in that case the get() method will return OpenTelemetrySdk and not - // ObfuscatedOpenTelemetry - assertThat(GlobalOpenTelemetry.get()).isNotSameAs(sdk); + .getOpenTelemetrySdk()) { + assertThat(GlobalOpenTelemetry.get()).isNotSameAs(sdk); + } } @Test @@ -63,10 +65,21 @@ void globalOpenTelemetry_AutoConfigureDisabled() { @Test @SetSystemProperty(key = "otel.java.global-autoconfigure.enabled", value = "true") void globalOpenTelemetry_AutoConfigureEnabled() { - assertThat(GlobalOpenTelemetry.get()) - .extracting("delegate") - .isInstanceOf(OpenTelemetrySdk.class); + OpenTelemetry openTelemetry = unobfuscate(GlobalOpenTelemetry.get()); + assertThat(openTelemetry).isInstanceOf(OpenTelemetrySdk.class); + ((OpenTelemetrySdk) openTelemetry).close(); + } - assertThat(logs.getEvents().size()).isEqualTo(0); + private static OpenTelemetry unobfuscate(OpenTelemetry openTelemetry) { + try { + Field delegateField = + Class.forName("io.opentelemetry.api.GlobalOpenTelemetry$ObfuscatedOpenTelemetry") + .getDeclaredField("delegate"); + delegateField.setAccessible(true); + Object delegate = delegateField.get(openTelemetry); + return (OpenTelemetry) delegate; + } catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) { + throw new IllegalStateException("Error unobfuscating OpenTelemetry", e); + } } } diff --git a/sdk-extensions/autoconfigure/src/testConfigError/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java similarity index 91% rename from sdk-extensions/autoconfigure/src/testConfigError/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java rename to sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java index 66e3cc1288f..31d8a817fbb 100644 --- a/sdk-extensions/autoconfigure/src/testConfigError/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java @@ -11,9 +11,11 @@ import io.github.netmikey.logunit.api.LogCapturer; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.logs.GlobalLoggerProvider; import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.internal.testing.slf4j.SuppressLogger; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.junitpioneer.jupiter.SetSystemProperty; @@ -27,9 +29,16 @@ class ConfigErrorTest { @RegisterExtension LogCapturer logs = LogCapturer.create().captureForType(GlobalOpenTelemetry.class); + @BeforeEach + void setup() { + GlobalOpenTelemetry.resetForTest(); + GlobalLoggerProvider.resetForTest(); + } + @Test @SetSystemProperty(key = "otel.propagators", value = "cat") void invalidPropagator() { + // TODO(jack-berg): confirm log warnings go away once exporters are properly shutdown (#5113) assertThatThrownBy(AutoConfiguredOpenTelemetrySdk::initialize) .isInstanceOf(ConfigurationException.class) .hasMessage( diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableLogRecordExporterTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableLogRecordExporterTest.java index 84e8b741d3c..bdc64e0ac81 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableLogRecordExporterTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableLogRecordExporterTest.java @@ -9,26 +9,39 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.common.collect.ImmutableMap; +import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.autoconfigure.provider.TestConfigurableLogRecordExporterProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.logs.export.LogRecordExporter; +import java.io.Closeable; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; class ConfigurableLogRecordExporterTest { + @RegisterExtension CleanupExtension cleanup = new CleanupExtension(); + @Test void configureLogRecordExporters_spiExporter() { ConfigProperties config = DefaultConfigProperties.createForTest( ImmutableMap.of("test.option", "true", "otel.logs.exporter", "testExporter")); + List closeables = new ArrayList<>(); + Map exportersByName = LogRecordExporterConfiguration.configureLogRecordExporters( - config, LogRecordExporterConfiguration.class.getClassLoader(), (a, unused) -> a); + config, + LogRecordExporterConfiguration.class.getClassLoader(), + (a, unused) -> a, + closeables); + cleanup.addCloseables(closeables); assertThat(exportersByName) .hasSize(1) @@ -37,6 +50,9 @@ void configureLogRecordExporters_spiExporter() { .isInstanceOf(TestConfigurableLogRecordExporterProvider.TestLogRecordExporter.class) .extracting("config") .isSameAs(config); + assertThat(closeables) + .hasExactlyElementsOfTypes( + TestConfigurableLogRecordExporterProvider.TestLogRecordExporter.class); } @Test @@ -44,12 +60,16 @@ void configureLogRecordExporters_emptyClassLoader() { ConfigProperties config = DefaultConfigProperties.createForTest( ImmutableMap.of("test.option", "true", "otel.logs.exporter", "testExporter")); + List closeables = new ArrayList<>(); + assertThatThrownBy( () -> LogRecordExporterConfiguration.configureLogRecordExporters( - config, new URLClassLoader(new URL[0], null), (a, unused) -> a)) + config, new URLClassLoader(new URL[0], null), (a, unused) -> a, closeables)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("testExporter"); + cleanup.addCloseables(closeables); + assertThat(closeables).isEmpty(); } @Test diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableMetricExporterTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableMetricExporterTest.java index 58391b7e086..ece4b561e61 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableMetricExporterTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableMetricExporterTest.java @@ -9,39 +9,48 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.common.collect.ImmutableMap; +import io.opentelemetry.exporter.logging.LoggingMetricExporter; import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; +import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.autoconfigure.provider.TestConfigurableMetricExporterProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.metrics.export.MetricExporter; +import io.opentelemetry.sdk.metrics.export.MetricReader; import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import java.io.Closeable; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.Collections; -import java.util.concurrent.TimeUnit; +import java.util.List; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; -public class ConfigurableMetricExporterTest { +class ConfigurableMetricExporterTest { + + @RegisterExtension CleanupExtension cleanup = new CleanupExtension(); @Test - void configuration() { + void configureExporter_spiExporter() { ConfigProperties config = DefaultConfigProperties.createForTest(ImmutableMap.of("test.option", "true")); - MetricExporter metricExporter = + + try (MetricExporter metricExporter = MetricExporterConfiguration.configureExporter( "testExporter", MetricExporterConfiguration.metricExporterSpiManager( - config, ConfigurableMetricExporterTest.class.getClassLoader())); - - assertThat(metricExporter) - .isInstanceOf(TestConfigurableMetricExporterProvider.TestMetricExporter.class) - .extracting("config") - .isSameAs(config); + config, ConfigurableMetricExporterTest.class.getClassLoader()))) { + assertThat(metricExporter) + .isInstanceOf(TestConfigurableMetricExporterProvider.TestMetricExporter.class) + .extracting("config") + .isSameAs(config); + } } @Test - void emptyClassLoader() { + void configureExporter_emptyClassLoader() { assertThatThrownBy( () -> MetricExporterConfiguration.configureExporter( @@ -54,7 +63,7 @@ void emptyClassLoader() { } @Test - void exporterNotFound() { + void configureExporter_exporterNotFound() { assertThatThrownBy( () -> MetricExporterConfiguration.configureExporter( @@ -71,50 +80,64 @@ void configureMetricReaders_multipleWithNone() { ConfigProperties config = DefaultConfigProperties.createForTest( ImmutableMap.of("otel.metrics.exporter", "otlp,none")); + List closeables = new ArrayList<>(); assertThatThrownBy( () -> MeterProviderConfiguration.configureMetricReaders( config, ConfigurableMetricExporterTest.class.getClassLoader(), - (a, unused) -> a)) + (a, unused) -> a, + closeables)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("otel.metrics.exporter contains none along with other exporters"); + cleanup.addCloseables(closeables); + assertThat(closeables).isEmpty(); } @Test - void defaultExporter() { + void configureMetricReaders_defaultExporter() { ConfigProperties config = DefaultConfigProperties.createForTest(Collections.emptyMap()); + List closeables = new ArrayList<>(); - assertThat( - MeterProviderConfiguration.configureMetricReaders( - config, - MeterProviderConfiguration.class.getClassLoader(), - (metricExporter, unused) -> metricExporter)) - .hasSize(1) - .first() - .isInstanceOf(PeriodicMetricReader.class) - .extracting("exporter") - .isInstanceOf(OtlpGrpcMetricExporter.class) - .satisfies( - metricExporter -> - ((OtlpGrpcMetricExporter) metricExporter).shutdown().join(10, TimeUnit.SECONDS)); + List metricReaders = + MeterProviderConfiguration.configureMetricReaders( + config, + MeterProviderConfiguration.class.getClassLoader(), + (metricExporter, unused) -> metricExporter, + closeables); + cleanup.addCloseables(closeables); + + assertThat(metricReaders) + .satisfiesExactly( + metricReader -> + assertThat(metricReader) + .isInstanceOf(PeriodicMetricReader.class) + .extracting("exporter") + .isInstanceOf(OtlpGrpcMetricExporter.class)); + assertThat(closeables) + .hasExactlyElementsOfTypes(OtlpGrpcMetricExporter.class, PeriodicMetricReader.class); } @Test - void configureMultipleMetricExporters() { + void configureMetricReaders_multipleExporters() { ConfigProperties config = DefaultConfigProperties.createForTest( ImmutableMap.of("otel.metrics.exporter", "otlp,logging")); + List closeables = new ArrayList<>(); + + List metricReaders = + MeterProviderConfiguration.configureMetricReaders( + config, + MeterProviderConfiguration.class.getClassLoader(), + (metricExporter, unused) -> metricExporter, + closeables); + cleanup.addCloseables(closeables); - assertThat( - MeterProviderConfiguration.configureMetricReaders( - config, - MeterProviderConfiguration.class.getClassLoader(), - (metricExporter, unused) -> metricExporter)) - .hasSize(2) - .hasAtLeastOneElementOfType(PeriodicMetricReader.class) - .hasAtLeastOneElementOfType(PeriodicMetricReader.class) - .allSatisfy(metricReader -> metricReader.shutdown().join(10, TimeUnit.SECONDS)); + assertThat(metricReaders).hasSize(2).hasOnlyElementsOfType(PeriodicMetricReader.class); + assertThat(closeables) + .hasSize(4) + .hasOnlyElementsOfTypes( + PeriodicMetricReader.class, LoggingMetricExporter.class, OtlpGrpcMetricExporter.class); } } diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableSpanExporterTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableSpanExporterTest.java index cec35c285ed..0cfc0c2c54b 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableSpanExporterTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableSpanExporterTest.java @@ -13,30 +13,41 @@ import io.opentelemetry.exporter.logging.LoggingSpanExporter; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter; +import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.autoconfigure.provider.TestConfigurableSpanExporterProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.io.Closeable; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; -public class ConfigurableSpanExporterTest { +class ConfigurableSpanExporterTest { + + @RegisterExtension CleanupExtension cleanup = new CleanupExtension(); @Test void configureSpanExporters_spiExporter() { ConfigProperties config = DefaultConfigProperties.createForTest( ImmutableMap.of("test.option", "true", "otel.traces.exporter", "testExporter")); + List closeables = new ArrayList<>(); + Map exportersByName = SpanExporterConfiguration.configureSpanExporters( - config, SpanExporterConfiguration.class.getClassLoader(), (a, unused) -> a); + config, SpanExporterConfiguration.class.getClassLoader(), (a, unused) -> a, closeables); + cleanup.addCloseables(closeables); assertThat(exportersByName) .hasSize(1) @@ -45,6 +56,8 @@ void configureSpanExporters_spiExporter() { .isInstanceOf(TestConfigurableSpanExporterProvider.TestSpanExporter.class) .extracting("config") .isSameAs(config); + assertThat(closeables) + .hasExactlyElementsOfTypes(TestConfigurableSpanExporterProvider.TestSpanExporter.class); } @Test @@ -52,12 +65,19 @@ void configureSpanExporters_emptyClassLoader() { ConfigProperties config = DefaultConfigProperties.createForTest( ImmutableMap.of("test.option", "true", "otel.traces.exporter", "testExporter")); + List closeables = new ArrayList<>(); + assertThatThrownBy( () -> SpanExporterConfiguration.configureSpanExporters( - config, new URLClassLoader(new URL[0], null), (a, unused) -> a)) + config, + new URLClassLoader(new URL[0], null), + (a, unused) -> a, + new ArrayList<>())) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("testExporter"); + cleanup.addCloseables(closeables); + assertThat(closeables).isEmpty(); } @Test @@ -65,30 +85,42 @@ void configureSpanExporters_duplicates() { ConfigProperties config = DefaultConfigProperties.createForTest( ImmutableMap.of("otel.traces.exporter", "otlp,otlp,logging")); + List closeables = new ArrayList<>(); assertThatThrownBy( () -> SpanExporterConfiguration.configureSpanExporters( - config, SpanExporterConfiguration.class.getClassLoader(), (a, unused) -> a)) + config, + SpanExporterConfiguration.class.getClassLoader(), + (a, unused) -> a, + closeables)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("otel.traces.exporter contains duplicates: [otlp]"); + cleanup.addCloseables(closeables); + assertThat(closeables).isEmpty(); } @Test void configureSpanExporters_multipleWithNone() { ConfigProperties config = DefaultConfigProperties.createForTest(ImmutableMap.of("otel.traces.exporter", "otlp,none")); + List closeables = new ArrayList<>(); assertThatThrownBy( () -> SpanExporterConfiguration.configureSpanExporters( - config, SpanExporterConfiguration.class.getClassLoader(), (a, unused) -> a)) + config, + SpanExporterConfiguration.class.getClassLoader(), + (a, unused) -> a, + closeables)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("otel.traces.exporter contains none along with other exporters"); + cleanup.addCloseables(closeables); + assertThat(closeables).isEmpty(); } @Test - void exporterNotFound() { + void configureExporter_NotFound() { assertThatThrownBy( () -> SpanExporterConfiguration.configureExporter( @@ -100,48 +132,58 @@ void exporterNotFound() { @Test void configureSpanProcessors_simpleSpanProcessor() { String exporterName = "logging"; - Map propMap = Collections.singletonMap("otel.traces.exporter", exporterName); - SpanExporter exporter = LoggingSpanExporter.create(); - ConfigProperties properties = DefaultConfigProperties.createForTest(propMap); - - assertThat( - TracerProviderConfiguration.configureSpanProcessors( - properties, ImmutableMap.of(exporterName, exporter), MeterProvider.noop())) - .hasSize(1) - .first() - .isInstanceOf(SimpleSpanProcessor.class); + List closeables = new ArrayList<>(); + + List spanProcessors = + TracerProviderConfiguration.configureSpanProcessors( + DefaultConfigProperties.createForTest( + Collections.singletonMap("otel.traces.exporter", exporterName)), + ImmutableMap.of(exporterName, LoggingSpanExporter.create()), + MeterProvider.noop(), + closeables); + cleanup.addCloseables(closeables); + + assertThat(spanProcessors).hasExactlyElementsOfTypes(SimpleSpanProcessor.class); + assertThat(closeables).hasExactlyElementsOfTypes(SimpleSpanProcessor.class); } @Test void configureSpanProcessors_batchSpanProcessor() { String exporterName = "zipkin"; - Map propMap = Collections.singletonMap("otel.traces.exporter", exporterName); - SpanExporter exporter = ZipkinSpanExporter.builder().build(); - ConfigProperties properties = DefaultConfigProperties.createForTest(propMap); - - assertThat( - TracerProviderConfiguration.configureSpanProcessors( - properties, ImmutableMap.of(exporterName, exporter), MeterProvider.noop())) - .hasSize(1) - .first() - .isInstanceOf(BatchSpanProcessor.class); + List closeables = new ArrayList<>(); + + List spanProcessors = + TracerProviderConfiguration.configureSpanProcessors( + DefaultConfigProperties.createForTest( + Collections.singletonMap("otel.traces.exporter", exporterName)), + ImmutableMap.of(exporterName, ZipkinSpanExporter.builder().build()), + MeterProvider.noop(), + closeables); + cleanup.addCloseables(closeables); + + assertThat(spanProcessors).hasExactlyElementsOfTypes(BatchSpanProcessor.class); + assertThat(closeables).hasExactlyElementsOfTypes(BatchSpanProcessor.class); } @Test void configureSpanProcessors_multipleExporters() { - SpanExporter otlpExporter = OtlpGrpcSpanExporter.builder().build(); - SpanExporter zipkinExporter = ZipkinSpanExporter.builder().build(); - ConfigProperties properties = - DefaultConfigProperties.createForTest( - Collections.singletonMap("otel.traces.exporter", "otlp,zipkin")); - - assertThat( - TracerProviderConfiguration.configureSpanProcessors( - properties, - ImmutableMap.of("otlp", otlpExporter, "zipkin", zipkinExporter), - MeterProvider.noop())) - .hasSize(1) - .hasAtLeastOneElementOfType(BatchSpanProcessor.class) + List closeables = new ArrayList<>(); + + List spanProcessors = + TracerProviderConfiguration.configureSpanProcessors( + DefaultConfigProperties.createForTest( + Collections.singletonMap("otel.traces.exporter", "otlp,zipkin")), + ImmutableMap.of( + "otlp", + OtlpGrpcSpanExporter.builder().build(), + "zipkin", + ZipkinSpanExporter.builder().build()), + MeterProvider.noop(), + closeables); + cleanup.addCloseables(closeables); + + assertThat(spanProcessors) + .hasExactlyElementsOfTypes(BatchSpanProcessor.class) .first() .extracting("worker") .extracting("spanExporter") @@ -162,21 +204,31 @@ void configureSpanProcessors_multipleExporters() { .hasAtLeastOneElementOfType(OtlpGrpcSpanExporter.class); }); }); + assertThat(closeables).hasExactlyElementsOfTypes(BatchSpanProcessor.class); } @Test void configureSpanProcessors_multipleExportersWithLogging() { - SpanExporter loggingExporter = LoggingSpanExporter.create(); - SpanExporter zipkinExporter = ZipkinSpanExporter.builder().build(); - ConfigProperties properties = - DefaultConfigProperties.createForTest( - Collections.singletonMap("otel.traces.exporter", "logging,zipkin")); - - assertThat( - TracerProviderConfiguration.configureSpanProcessors( - properties, - ImmutableMap.of("logging", loggingExporter, "zipkin", zipkinExporter), - MeterProvider.noop())) + List closeables = new ArrayList<>(); + + List spanProcessors = + TracerProviderConfiguration.configureSpanProcessors( + DefaultConfigProperties.createForTest( + Collections.singletonMap("otel.traces.exporter", "logging,zipkin")), + ImmutableMap.of( + "logging", + LoggingSpanExporter.create(), + "zipkin", + ZipkinSpanExporter.builder().build()), + MeterProvider.noop(), + closeables); + cleanup.addCloseables(closeables); + + assertThat(spanProcessors) + .hasSize(2) + .hasAtLeastOneElementOfType(SimpleSpanProcessor.class) + .hasAtLeastOneElementOfType(BatchSpanProcessor.class); + assertThat(closeables) .hasSize(2) .hasAtLeastOneElementOfType(SimpleSpanProcessor.class) .hasAtLeastOneElementOfType(BatchSpanProcessor.class); diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FullConfigTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FullConfigTest.java index 52c96da33b3..1c4c726192d 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FullConfigTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FullConfigTest.java @@ -41,6 +41,7 @@ import io.opentelemetry.proto.metrics.v1.Metric; import io.opentelemetry.proto.metrics.v1.ResourceMetrics; import io.opentelemetry.proto.metrics.v1.ScopeMetrics; +import io.opentelemetry.sdk.OpenTelemetrySdk; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -143,7 +144,7 @@ public void export( } }; - private AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk; + private OpenTelemetrySdk openTelemetrySdk; @BeforeEach void setUp() { @@ -158,12 +159,12 @@ void setUp() { // Initialize here so we can shutdown when done GlobalOpenTelemetry.resetForTest(); GlobalLoggerProvider.resetForTest(); - autoConfiguredOpenTelemetrySdk = AutoConfiguredOpenTelemetrySdk.initialize(); + openTelemetrySdk = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); } @AfterEach void afterEach() { - autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk().shutdown().join(10, TimeUnit.SECONDS); + openTelemetrySdk.close(); GlobalOpenTelemetry.resetForTest(); GlobalLoggerProvider.resetForTest(); } @@ -204,6 +205,10 @@ void configures() throws Exception { logger.logRecordBuilder().setBody("debug log message").setSeverity(Severity.DEBUG).emit(); logger.logRecordBuilder().setBody("info log message").setSeverity(Severity.INFO).emit(); + openTelemetrySdk.getSdkTracerProvider().forceFlush().join(10, TimeUnit.SECONDS); + openTelemetrySdk.getSdkMeterProvider().forceFlush().join(10, TimeUnit.SECONDS); + openTelemetrySdk.getSdkLoggerProvider().forceFlush().join(10, TimeUnit.SECONDS); + await().untilAsserted(() -> assertThat(otlpTraceRequests).hasSize(1)); ExportTraceServiceRequest traceRequest = otlpTraceRequests.take(); diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfigurationTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfigurationTest.java index 5fff386ee69..347b4665925 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfigurationTest.java @@ -11,26 +11,34 @@ import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter; import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter; +import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import io.opentelemetry.sdk.logs.LogRecordProcessor; 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.logs.export.SimpleLogRecordProcessor; import io.opentelemetry.sdk.trace.internal.JcTools; +import java.io.Closeable; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; class LoggerProviderConfigurationTest { + @RegisterExtension CleanupExtension cleanup = new CleanupExtension(); + @Test void configureLoggerProvider() { Map properties = Collections.singletonMap("otel.logs.exporter", "otlp"); + List closeables = new ArrayList<>(); SdkLoggerProviderBuilder builder = SdkLoggerProvider.builder(); LoggerProviderConfiguration.configureLoggerProvider( @@ -38,10 +46,11 @@ void configureLoggerProvider() { DefaultConfigProperties.createForTest(properties), LoggerProviderConfiguration.class.getClassLoader(), MeterProvider.noop(), - (a, unused) -> a); - SdkLoggerProvider loggerProvider = builder.build(); + (a, unused) -> a, + closeables); + cleanup.addCloseables(closeables); - try { + try (SdkLoggerProvider loggerProvider = builder.build()) { assertThat(loggerProvider) .extracting("sharedState") .satisfies( @@ -65,21 +74,33 @@ void configureLoggerProvider() { ArrayBlockingQueue.class, queue -> assertThat(queue.remainingCapacity()).isEqualTo(2048)); })); - } finally { - loggerProvider.shutdown(); + assertThat(closeables) + .hasExactlyElementsOfTypes( + OtlpGrpcLogRecordExporter.class, BatchLogRecordProcessor.class); } } @Test void configureLogRecordProcessors_multipleExportersWithLogging() { - LogRecordExporter loggingExporter = SystemOutLogRecordExporter.create(); - LogRecordExporter otlpExporter = OtlpGrpcLogRecordExporter.builder().build(); + List closeables = new ArrayList<>(); + + List logRecordProcessors = + LoggerProviderConfiguration.configureLogRecordProcessors( + DefaultConfigProperties.createForTest(Collections.emptyMap()), + ImmutableMap.of( + "logging", + SystemOutLogRecordExporter.create(), + "otlp", + OtlpGrpcLogRecordExporter.builder().build()), + MeterProvider.noop(), + closeables); + cleanup.addCloseables(closeables); - assertThat( - LoggerProviderConfiguration.configureLogRecordProcessors( - DefaultConfigProperties.createForTest(Collections.emptyMap()), - ImmutableMap.of("logging", loggingExporter, "otlp", otlpExporter), - MeterProvider.noop())) + assertThat(logRecordProcessors) + .hasSize(2) + .hasAtLeastOneElementOfType(SimpleLogRecordProcessor.class) + .hasAtLeastOneElementOfType(BatchLogRecordProcessor.class); + assertThat(closeables) .hasSize(2) .hasAtLeastOneElementOfType(SimpleLogRecordProcessor.class) .hasAtLeastOneElementOfType(BatchLogRecordProcessor.class); @@ -93,13 +114,11 @@ void configureBatchLogRecordProcessor() { properties.put("otel.blrp.max.export.batch.size", "3"); properties.put("otel.blrp.export.timeout", "4"); - BatchLogRecordProcessor processor = + try (BatchLogRecordProcessor processor = LoggerProviderConfiguration.configureBatchLogRecordProcessor( DefaultConfigProperties.createForTest(properties), SystemOutLogRecordExporter.create(), - MeterProvider.noop()); - - try { + MeterProvider.noop())) { assertThat(processor) .extracting("worker") .satisfies( @@ -119,8 +138,6 @@ void configureBatchLogRecordProcessor() { .extracting("logRecordExporter") .isInstanceOf(SystemOutLogRecordExporter.class); }); - } finally { - processor.shutdown(); } } } diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java index dcec4c24042..5f6a7721459 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java @@ -14,35 +14,47 @@ import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingMetricExporter; import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; import io.opentelemetry.exporter.prometheus.PrometheusHttpServer; +import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider; -import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.export.MetricExporter; import io.opentelemetry.sdk.metrics.export.MetricReader; +import java.io.Closeable; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; class MetricExporterConfigurationTest { private static final ConfigProperties EMPTY = DefaultConfigProperties.createForTest(Collections.emptyMap()); + @RegisterExtension CleanupExtension cleanup = new CleanupExtension(); + @Test void configureReader_PrometheusOnClasspath() { - assertThat( - MetricExporterConfiguration.configureReader( - "prometheus", - EMPTY, - MetricExporterConfigurationTest.class.getClassLoader(), - (a, b) -> a)) - .isNull(); + List closeables = new ArrayList<>(); + + MetricReader reader = + MetricExporterConfiguration.configureReader( + "prometheus", + EMPTY, + MetricExporterConfigurationTest.class.getClassLoader(), + (a, b) -> a, + closeables); + cleanup.addCloseables(closeables); + + assertThat(reader).isNull(); + assertThat(closeables).isEmpty(); } /** @@ -58,14 +70,13 @@ void autoConfiguredOpenTelemetrySdk_PrometheusOnClasspath() { config.put("otel.metrics.exporter", "prometheus"); config.put("otel.logs.exporter", "none"); - OpenTelemetrySdk sdk = + try (OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.builder() .setResultAsGlobal(false) .setConfig(DefaultConfigProperties.createForTest(config)) .build() - .getOpenTelemetrySdk(); - try (SdkMeterProvider meterProvider = sdk.getSdkMeterProvider()) { - assertThat(meterProvider) + .getOpenTelemetrySdk()) { + assertThat(sdk.getSdkMeterProvider()) .extracting("registeredReaders", as(InstanceOfAssertFactories.list(Object.class))) .satisfiesExactly( registeredReader -> diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java index bcb1ced7b98..01724e7b79d 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java @@ -63,19 +63,16 @@ void configureOtlpTimeout() { ConfigProperties config = DefaultConfigProperties.createForTest( Collections.singletonMap("otel.exporter.otlp.timeout", "10")); - SpanExporter exporter = + try (SpanExporter exporter = SpanExporterConfiguration.configureExporter( "otlp", SpanExporterConfiguration.spanExporterSpiManager( - config, SpanExporterConfigurationTest.class.getClassLoader())); - try { + config, SpanExporterConfigurationTest.class.getClassLoader()))) { assertThat(exporter) .isInstanceOfSatisfying( OtlpGrpcSpanExporter.class, otlp -> assertThat(otlp).extracting("delegate.client.callTimeoutMillis").isEqualTo(10)); - } finally { - exporter.shutdown(); } } } diff --git a/testing-internal/src/main/java/io/opentelemetry/internal/testing/CleanupExtension.java b/testing-internal/src/main/java/io/opentelemetry/internal/testing/CleanupExtension.java new file mode 100644 index 00000000000..2a08e5f414d --- /dev/null +++ b/testing-internal/src/main/java/io/opentelemetry/internal/testing/CleanupExtension.java @@ -0,0 +1,37 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.internal.testing; + +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +/** An extension that assists in cleaning up {@link Closeable}s after test completion. */ +public class CleanupExtension implements AfterEachCallback { + + private final List closeables = new ArrayList<>(); + + /** Add {@link Closeable}s to be cleaned up after test completion. */ + public void addCloseables(Collection closeables) { + this.closeables.addAll(closeables); + } + + @Override + public void afterEach(ExtensionContext context) { + for (Closeable closeable : closeables) { + try { + closeable.close(); + } catch (IOException e) { + // Ignore + } + } + closeables.clear(); + } +} From 83a8378dd6b202675575eba5b6827c0d4082493e Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Tue, 17 Jan 2023 10:53:50 -0600 Subject: [PATCH 2/5] Improve test coverage --- .../AutoConfiguredOpenTelemetrySdkTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java index 5c18e7322e7..b152954f6b8 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java @@ -10,12 +10,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import io.github.netmikey.logunit.api.LogCapturer; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.logs.GlobalLoggerProvider; @@ -27,6 +29,7 @@ import io.opentelemetry.context.ContextKey; import io.opentelemetry.context.propagation.TextMapGetter; import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.internal.testing.slf4j.SuppressLogger; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; @@ -47,6 +50,7 @@ import io.opentelemetry.sdk.trace.export.SpanExporter; import io.opentelemetry.sdk.trace.samplers.Sampler; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collections; @@ -60,6 +64,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; @@ -70,6 +75,9 @@ @MockitoSettings(strictness = Strictness.LENIENT) class AutoConfiguredOpenTelemetrySdkTest { + @RegisterExtension + LogCapturer logs = LogCapturer.create().captureForType(AutoConfiguredOpenTelemetrySdkBuilder.class); + @Mock private IdGenerator idGenerator; @Mock private TextMapPropagator propagator1; @Mock private TextMapPropagator propagator2; @@ -447,6 +455,7 @@ void testNonStringProperties() { } @Test + @SuppressLogger(AutoConfiguredOpenTelemetrySdkBuilder.class) void configurationError_ClosesResources() { // AutoConfiguredOpenTelemetrySdk should close partially configured resources if an exception // short circuits configuration. Verify that SdkTracerProvider, SdkMeterProvider, and @@ -462,6 +471,9 @@ void configurationError_ClosesResources() { when(meterProviderBuilder.build()).thenReturn(meterProvider); when(loggerProviderBuilder.build()).thenReturn(loggerProvider); + // Throw an error when closing and verify other resources are still closed + doThrow(new IOException("Error!")).when(tracerProvider).close(); + assertThatThrownBy( () -> // Override the provider builders with mocks which we can verify are closed @@ -481,5 +493,7 @@ void configurationError_ClosesResources() { verify(tracerProvider).close(); verify(meterProvider).close(); verify(loggerProvider).close(); + + logs.assertContains("Error closing io.opentelemetry.sdk.trace.SdkTracerProvider: Error!"); } } From 7dfde738303b022c4393a1ef096cfd659d77679d Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Tue, 17 Jan 2023 11:18:36 -0600 Subject: [PATCH 3/5] Spotless --- .../sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java index b152954f6b8..613ee907683 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java @@ -76,7 +76,8 @@ class AutoConfiguredOpenTelemetrySdkTest { @RegisterExtension - LogCapturer logs = LogCapturer.create().captureForType(AutoConfiguredOpenTelemetrySdkBuilder.class); + LogCapturer logs = + LogCapturer.create().captureForType(AutoConfiguredOpenTelemetrySdkBuilder.class); @Mock private IdGenerator idGenerator; @Mock private TextMapPropagator propagator1; From e8e454d63040a0c613f55b049a979f0cb11bfb76 Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Sat, 21 Jan 2023 08:08:45 -0600 Subject: [PATCH 4/5] Reduce logging level to info for multiple shutdowns --- .../exporter/internal/grpc/OkHttpGrpcExporter.java | 2 +- .../exporter/internal/grpc/UpstreamGrpcExporter.java | 2 +- .../opentelemetry/exporter/internal/okhttp/OkHttpExporter.java | 2 +- .../exporter/jaeger/thrift/JaegerThriftSpanExporter.java | 2 +- .../exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java | 2 +- .../exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java | 2 +- .../exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java | 2 +- .../opentelemetry/exporter/logging/LoggingMetricExporter.java | 2 +- .../io/opentelemetry/exporter/logging/LoggingSpanExporter.java | 2 +- .../io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java | 2 +- .../main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java | 2 +- .../main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/OkHttpGrpcExporter.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/OkHttpGrpcExporter.java index 6a7e5cdef27..2178f47fc51 100644 --- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/OkHttpGrpcExporter.java +++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/OkHttpGrpcExporter.java @@ -215,7 +215,7 @@ private static String grpcMessage(Response response) { @Override public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } client.dispatcher().cancelAll(); diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/UpstreamGrpcExporter.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/UpstreamGrpcExporter.java index e395e2b5fba..8be6a425193 100644 --- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/UpstreamGrpcExporter.java +++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/UpstreamGrpcExporter.java @@ -124,7 +124,7 @@ public void onFailure(Throwable t) { @Override public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); } return CompletableResultCode.ofSuccess(); } diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/okhttp/OkHttpExporter.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/okhttp/OkHttpExporter.java index 5d7c50229dc..5cd207e327a 100644 --- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/okhttp/OkHttpExporter.java +++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/okhttp/OkHttpExporter.java @@ -146,7 +146,7 @@ public void onResponse(Call call, Response response) { public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } client.dispatcher().cancelAll(); diff --git a/exporters/jaeger-thrift/src/main/java/io/opentelemetry/exporter/jaeger/thrift/JaegerThriftSpanExporter.java b/exporters/jaeger-thrift/src/main/java/io/opentelemetry/exporter/jaeger/thrift/JaegerThriftSpanExporter.java index 35a14551d62..d835e5b3498 100644 --- a/exporters/jaeger-thrift/src/main/java/io/opentelemetry/exporter/jaeger/thrift/JaegerThriftSpanExporter.java +++ b/exporters/jaeger-thrift/src/main/java/io/opentelemetry/exporter/jaeger/thrift/JaegerThriftSpanExporter.java @@ -154,7 +154,7 @@ public static JaegerThriftSpanExporterBuilder builder() { @Override public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); } return CompletableResultCode.ofSuccess(); } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java index cc5a12d190b..dc76e7a9e3b 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java @@ -67,7 +67,7 @@ public CompletableResultCode flush() { @Override public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); } return CompletableResultCode.ofSuccess(); } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java index dbb4ed8ae41..14ba6df348a 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java @@ -97,7 +97,7 @@ public CompletableResultCode flush() { @Override public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); } return CompletableResultCode.ofSuccess(); } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java index 4b99f2864ab..05cd9dfcad6 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java @@ -64,7 +64,7 @@ public CompletableResultCode flush() { @Override public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); } return CompletableResultCode.ofSuccess(); } diff --git a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/LoggingMetricExporter.java b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/LoggingMetricExporter.java index f4bcf6a58cf..f3cf8421022 100644 --- a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/LoggingMetricExporter.java +++ b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/LoggingMetricExporter.java @@ -98,7 +98,7 @@ public CompletableResultCode flush() { @Override public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } return flush(); diff --git a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/LoggingSpanExporter.java b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/LoggingSpanExporter.java index 7b5001cf0b5..3d19f9e9ee8 100644 --- a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/LoggingSpanExporter.java +++ b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/LoggingSpanExporter.java @@ -88,7 +88,7 @@ public CompletableResultCode flush() { @Override public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } return flush(); diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java index b5ea22172a2..6809da33211 100644 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java @@ -103,7 +103,7 @@ public CompletableResultCode flush() { @Override public CompletableResultCode shutdown() { if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } try { diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java index d7b35c9ed86..50b7dcdc800 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java @@ -107,7 +107,7 @@ public CompletableResultCode forceFlush() { */ public CompletableResultCode shutdown() { if (sharedState.hasBeenShutdown()) { - LOGGER.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } return sharedState.shutdown(); diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java index 44d33f09347..2e07af579a9 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java @@ -101,7 +101,7 @@ public Sampler getSampler() { */ public CompletableResultCode shutdown() { if (sharedState.hasBeenShutdown()) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); + logger.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } return sharedState.shutdown(); From 0d63dc6aa54c012f41ab660b5676e03902cb04fe Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Sat, 21 Jan 2023 08:22:39 -0600 Subject: [PATCH 5/5] Fix build --- .../main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java index 50b7dcdc800..8d4814af57a 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java @@ -107,7 +107,7 @@ public CompletableResultCode forceFlush() { */ public CompletableResultCode shutdown() { if (sharedState.hasBeenShutdown()) { - logger.log(Level.INFO, "Calling shutdown() multiple times."); + LOGGER.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } return sharedState.shutdown();