From 1e073fcff20697fd5f2eb39bd6246d06a1231089 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Thu, 28 Oct 2021 08:41:14 +0900 Subject: [PATCH] Add an auto-configuration builder. (#3753) * Add an auto-configuration builder. * Test * Builder * More * Revamp * Customizer only customizes * Pass config to customizers * More specific name * Cleanup * Cleanup * SPI test * Clean * Clean * Clean * Shutdown once instead of flush and shutdown for simple * Clean * Cleanups * Cleanup --- .../api/GlobalOpenTelemetry.java | 7 +- ...emetry-sdk-extension-autoconfigure-spi.txt | 13 +- .../spi/AutoConfigurationCustomizer.java | 69 ++++++ .../AutoConfigurationCustomizerProvider.java | 16 ++ sdk-extensions/autoconfigure/build.gradle.kts | 3 + .../AutoConfiguredOpenTelemetrySdk.java | 55 +++++ ...AutoConfiguredOpenTelemetrySdkBuilder.java | 197 ++++++++++++++++++ .../DefaultConfigProperties.java | 12 +- .../autoconfigure/EnvironmentResource.java | 10 +- ...penTelemetryResourceAutoConfiguration.java | 26 ++- .../OpenTelemetrySdkAutoConfiguration.java | 45 +++- .../PropagatorConfiguration.java | 9 +- .../SpanExporterConfiguration.java | 17 +- .../TracerProviderConfiguration.java | 16 +- .../EnvironmentResourceTest.java | 1 + .../sdk/autoconfigure/NotOnClasspathTest.java | 3 +- ...OpenTelemetrySdkAutoConfigurationTest.java | 136 ++++++++++++ .../PropagatorConfigurationTest.java | 2 +- .../sdk/autoconfigure/ResourceTest.java | 17 +- .../TracerProviderConfigurationTest.java | 5 +- .../sdk/autoconfigure/ConfigErrorTest.java | 8 +- .../ConfigurableSpanExporterTest.java | 8 +- .../sdk/autoconfigure/FullConfigTest.java | 4 + .../sdk/autoconfigure/ResourceTest.java | 1 + .../autoconfigure/SpanExporterCustomizer.java | 52 +++++ ...re.spi.AutoConfigurationCustomizerProvider | 1 + ...OpenTelemetrySdkAutoConfigurationTest.java | 8 +- .../sdk/autoconfigure/JaegerConfigTest.java | 2 +- .../sdk/autoconfigure/PrometheusTest.java | 2 +- .../resources/ResourceDisabledByEnvTest.java | 24 --- .../ResourceDisabledByPropertyTest.java | 24 --- .../sdk/autoconfigure/ZipkinConfigTest.java | 2 +- 32 files changed, 699 insertions(+), 96 deletions(-) create mode 100644 sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizer.java create mode 100644 sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizerProvider.java create mode 100644 sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdk.java create mode 100644 sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java create mode 100644 sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfigurationTest.java create mode 100644 sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterCustomizer.java create mode 100644 sdk-extensions/autoconfigure/src/testFullConfig/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider delete mode 100644 sdk-extensions/autoconfigure/src/testResourceDisabledByEnv/java/io/opentelemetry/sdk/resources/ResourceDisabledByEnvTest.java delete mode 100644 sdk-extensions/autoconfigure/src/testResourceDisabledByProperty/java/io/opentelemetry/sdk/resources/ResourceDisabledByPropertyTest.java diff --git a/api/all/src/main/java/io/opentelemetry/api/GlobalOpenTelemetry.java b/api/all/src/main/java/io/opentelemetry/api/GlobalOpenTelemetry.java index 3167af45cc..b38eaa1d90 100644 --- a/api/all/src/main/java/io/opentelemetry/api/GlobalOpenTelemetry.java +++ b/api/all/src/main/java/io/opentelemetry/api/GlobalOpenTelemetry.java @@ -161,14 +161,17 @@ public final class GlobalOpenTelemetry { final Class openTelemetrySdkAutoConfiguration; try { openTelemetrySdkAutoConfiguration = - Class.forName("io.opentelemetry.sdk.autoconfigure.OpenTelemetrySdkAutoConfiguration"); + Class.forName("io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk"); } catch (ClassNotFoundException e) { return null; } try { Method initialize = openTelemetrySdkAutoConfiguration.getMethod("initialize"); - return (OpenTelemetry) initialize.invoke(null); + Object autoConfiguredSdk = initialize.invoke(null); + Method getOpenTelemetrySdk = + openTelemetrySdkAutoConfiguration.getMethod("getOpenTelemetrySdk"); + return (OpenTelemetry) getOpenTelemetrySdk.invoke(autoConfiguredSdk); } catch (NoSuchMethodException | IllegalAccessException e) { throw new IllegalStateException( "OpenTelemetrySdkAutoConfiguration detected on classpath " diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt index df26146497..432fb9ba7e 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt @@ -1,2 +1,13 @@ Comparing source compatibility of against -No changes. \ No newline at end of file ++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer (not serializable) + +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. + +++ NEW SUPERCLASS: java.lang.Object + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addPropagatorCustomizer(java.util.function.BiFunction) + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addPropertiesSupplier(java.util.function.Supplier) + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addResourceCustomizer(java.util.function.BiFunction) + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addSamplerCustomizer(java.util.function.BiFunction) + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addSpanExporterCustomizer(java.util.function.BiFunction) ++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider (not serializable) + +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. + +++ NEW SUPERCLASS: java.lang.Object + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void customize(io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer) diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizer.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizer.java new file mode 100644 index 0000000000..b3ed5822cc --- /dev/null +++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizer.java @@ -0,0 +1,69 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.autoconfigure.spi; + +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.Supplier; + +/** A builder for customizing OpenTelemetry auto-configuration. */ +public interface AutoConfigurationCustomizer { + + /** + * Adds a {@link BiFunction} to invoke with the default autoconfigured {@link TextMapPropagator} + * to allow customization. The return value of the {@link BiFunction} will replace the passed-in + * argument. + * + *

Multiple calls will execute the customizers in order. + */ + AutoConfigurationCustomizer addPropagatorCustomizer( + BiFunction + propagatorCustomizer); + + /** + * Adds a {@link BiFunction} to invoke with the default autoconfigured {@link Resource} to allow + * customization. The return value of the {@link BiFunction} will replace the passed-in argument. + * + *

Multiple calls will execute the customizers in order. + */ + AutoConfigurationCustomizer addResourceCustomizer( + BiFunction resourceCustomizer); + + /** + * Adds a {@link BiFunction} to invoke with the default autoconfigured {@link Sampler} to allow + * customization. The return value of the {@link BiFunction} will replace the passed-in argument. + * + *

Multiple calls will execute the customizers in order. + */ + AutoConfigurationCustomizer addSamplerCustomizer( + BiFunction samplerCustomizer); + + /** + * Adds a {@link BiFunction} to invoke with the default autoconfigured {@link SpanExporter} to + * allow customization. The return value of the {@link BiFunction} will replace the passed-in + * argument. + * + *

Multiple calls will execute the customizers in order. + */ + AutoConfigurationCustomizer addSpanExporterCustomizer( + BiFunction + exporterCustomizer); + + /** + * Adds a {@link Supplier} of a map of property names and values to use as defaults for the {@link + * ConfigProperties} used during auto-configuration. The order of precedence of properties is + * system properties > environment variables > the suppliers registered with this method. + * + *

Multiple calls will cause properties to be merged in order, with later ones overwriting + * duplicate keys in earlier ones. + */ + AutoConfigurationCustomizer addPropertiesSupplier( + Supplier> propertiesSupplier); +} diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizerProvider.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizerProvider.java new file mode 100644 index 0000000000..200fa2b611 --- /dev/null +++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizerProvider.java @@ -0,0 +1,16 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.autoconfigure.spi; + +/** A service provider interface (SPI) for customizing auto-configuration. */ +public interface AutoConfigurationCustomizerProvider { + + /** + * Method invoked when auto-configuring the SDK to allow further customization of + * auto-configuration. + */ + void customize(AutoConfigurationCustomizer autoConfiguration); +} diff --git a/sdk-extensions/autoconfigure/build.gradle.kts b/sdk-extensions/autoconfigure/build.gradle.kts index b2b17b8c21..b3c759dd43 100644 --- a/sdk-extensions/autoconfigure/build.gradle.kts +++ b/sdk-extensions/autoconfigure/build.gradle.kts @@ -37,6 +37,8 @@ dependencies { compileOnly(project(":exporters:prometheus")) compileOnly(project(":exporters:zipkin")) + annotationProcessor("com.google.auto.value:auto-value") + testImplementation(project(path = ":sdk:trace-shaded-deps")) testImplementation(project(":sdk:testing")) @@ -98,6 +100,7 @@ tasks { environment("OTEL_EXPORTER_OTLP_TIMEOUT", "5000") environment("OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", "2") environment("OTEL_TEST_CONFIGURED", "true") + environment("OTEL_TEST_WRAPPED", "1") } val testInitializeRegistersGlobal by existing(Test::class) { diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdk.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdk.java new file mode 100644 index 0000000000..04304f63b5 --- /dev/null +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdk.java @@ -0,0 +1,55 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.autoconfigure; + +import com.google.auto.value.AutoValue; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.resources.Resource; + +/** + * An auto-configured OpenTelemetry SDK. As an alternative to programmatically configuring the SDK + * using {@link OpenTelemetrySdk#builder()}, this package can be used to automatically configure the + * SDK using environment properties specified by OpenTelemetry. + */ +@AutoValue +public abstract class AutoConfiguredOpenTelemetrySdk { + + /** + * Returns an {@link AutoConfiguredOpenTelemetrySdk} automatically initialized through recognized + * system properties and environment variables. + * + *

This will automatically set the resulting SDK as the {@link + * io.opentelemetry.api.GlobalOpenTelemetry} instance. + */ + public static AutoConfiguredOpenTelemetrySdk initialize() { + return builder().build(); + } + + /** + * Returns a new {@link AutoConfiguredOpenTelemetrySdkBuilder} which can be used to customize + * auto-configuration behavior. + */ + public static AutoConfiguredOpenTelemetrySdkBuilder builder() { + return new AutoConfiguredOpenTelemetrySdkBuilder(); + } + + static AutoConfiguredOpenTelemetrySdk create( + OpenTelemetrySdk sdk, Resource resource, ConfigProperties config) { + return new AutoValue_AutoConfiguredOpenTelemetrySdk(sdk, resource, config); + } + + /** Returns the {@link OpenTelemetrySdk} that was auto-configured. */ + public abstract OpenTelemetrySdk getOpenTelemetrySdk(); + + /** Returns the {@link Resource} that was auto-configured. */ + public abstract Resource getResource(); + + /** Returns the {@link ConfigProperties} used for auto-configuration. */ + public abstract ConfigProperties getConfig(); + + AutoConfiguredOpenTelemetrySdk() {} +} 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 new file mode 100644 index 0000000000..5792e8f637 --- /dev/null +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java @@ -0,0 +1,197 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.autoconfigure; + +import static java.util.Objects.requireNonNull; + +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.sdk.OpenTelemetrySdk; +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.resources.Resource; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.function.BiFunction; +import java.util.function.Supplier; +import javax.annotation.Nullable; + +/** + * A builder for configuring auto-configuration of the OpenTelemetry SDK. Notably, auto-configured + * components can be customized, for example by delegating to them from a wrapper that tweaks + * behavior such as filtering out telemetry attributes. + */ +public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigurationCustomizer { + + @Nullable private ConfigProperties config; + + private BiFunction + propagatorCustomizer = (a, unused) -> a; + private BiFunction + spanExporterCustomizer = (a, unused) -> a; + private BiFunction resourceCustomizer = + (a, unused) -> a; + private BiFunction samplerCustomizer = + (a, unused) -> a; + + private Supplier> propertiesSupplier = Collections::emptyMap; + + private boolean setResultAsGlobal = true; + + AutoConfiguredOpenTelemetrySdkBuilder() { + for (AutoConfigurationCustomizerProvider customizer : + ServiceLoader.load(AutoConfigurationCustomizerProvider.class)) { + customizer.customize(this); + } + } + + /** + * Sets the {@link ConfigProperties} to use when resolving properties for auto-configuration. + * {@link #addPropertiesSupplier(Supplier)} will have no effect if this method is used. + */ + AutoConfiguredOpenTelemetrySdkBuilder setConfig(ConfigProperties config) { + requireNonNull(config, "config"); + this.config = config; + return this; + } + + /** + * Adds a {@link BiFunction} to invoke with the default autoconfigured {@link TextMapPropagator} + * to allow customization. The return value of the {@link BiFunction} will replace the passed-in + * argument. + * + *

Multiple calls will execute the customizers in order. + */ + @Override + public AutoConfiguredOpenTelemetrySdkBuilder addPropagatorCustomizer( + BiFunction + propagatorCustomizer) { + requireNonNull(propagatorCustomizer, "propagatorCustomizer"); + this.propagatorCustomizer = mergeCustomizer(this.propagatorCustomizer, propagatorCustomizer); + return this; + } + + /** + * Adds a {@link BiFunction} to invoke with the default autoconfigured {@link Resource} to allow + * customization. The return value of the {@link BiFunction} will replace the passed-in argument. + * + *

Multiple calls will execute the customizers in order. + */ + @Override + public AutoConfiguredOpenTelemetrySdkBuilder addResourceCustomizer( + BiFunction resourceCustomizer) { + requireNonNull(resourceCustomizer, "resourceCustomizer"); + this.resourceCustomizer = mergeCustomizer(this.resourceCustomizer, resourceCustomizer); + return this; + } + + /** + * Adds a {@link BiFunction} to invoke with the default autoconfigured {@link Sampler} to allow + * customization. The return value of the {@link BiFunction} will replace the passed-in argument. + * + *

Multiple calls will execute the customizers in order. + */ + @Override + public AutoConfiguredOpenTelemetrySdkBuilder addSamplerCustomizer( + BiFunction samplerCustomizer) { + requireNonNull(samplerCustomizer, "samplerCustomizer"); + this.samplerCustomizer = mergeCustomizer(this.samplerCustomizer, samplerCustomizer); + return this; + } + + /** + * Adds a {@link BiFunction} to invoke with the default autoconfigured {@link SpanExporter} to + * allow customization. The return value of the {@link BiFunction} will replace the passed-in + * argument. + * + *

Multiple calls will execute the customizers in order. + */ + @Override + public AutoConfiguredOpenTelemetrySdkBuilder addSpanExporterCustomizer( + BiFunction + spanExporterCustomizer) { + requireNonNull(spanExporterCustomizer, "spanExporterCustomizer"); + this.spanExporterCustomizer = + mergeCustomizer(this.spanExporterCustomizer, spanExporterCustomizer); + return this; + } + + /** + * Adds a {@link Supplier} of a map of property names and values to use as defaults for the {@link + * ConfigProperties} used during auto-configuration. The order of precedence of properties is + * system properties > environment variables > the suppliers registered with this method. + * + *

Multiple calls will cause properties to be merged in order, with later ones overwriting + * duplicate keys in earlier ones. + */ + @Override + public AutoConfiguredOpenTelemetrySdkBuilder addPropertiesSupplier( + Supplier> propertiesSupplier) { + requireNonNull(propertiesSupplier, "propertiesSupplier"); + this.propertiesSupplier = mergeProperties(this.propertiesSupplier, propertiesSupplier); + return this; + } + + /** + * Sets whether the configured {@link OpenTelemetrySdk} should be set as the application's + * {@linkplain io.opentelemetry.api.GlobalOpenTelemetry global} instance. + */ + public AutoConfiguredOpenTelemetrySdkBuilder setResultAsGlobal(boolean setResultAsGlobal) { + this.setResultAsGlobal = setResultAsGlobal; + return this; + } + + /** + * Returns a new {@link AutoConfiguredOpenTelemetrySdk} holding components auto-configured using + * the settings of this {@link AutoConfiguredOpenTelemetrySdkBuilder}. + */ + @SuppressWarnings("deprecation") // Using classes which will be made package-private later. + public AutoConfiguredOpenTelemetrySdk build() { + ConfigProperties config = getConfig(); + Resource resource = + OpenTelemetryResourceAutoConfiguration.configureResource(config, resourceCustomizer); + OpenTelemetrySdk sdk = + OpenTelemetrySdkAutoConfiguration.newOpenTelemetrySdk( + config, + resource, + propagatorCustomizer, + spanExporterCustomizer, + samplerCustomizer, + setResultAsGlobal); + return AutoConfiguredOpenTelemetrySdk.create(sdk, resource, config); + } + + private ConfigProperties getConfig() { + ConfigProperties config = this.config; + if (config == null) { + config = DefaultConfigProperties.get(propertiesSupplier.get()); + } + return config; + } + + private static BiFunction mergeCustomizer( + BiFunction first, + BiFunction second) { + return (I configured, ConfigProperties config) -> { + O1 firstResult = first.apply(configured, config); + return second.apply(firstResult, config); + }; + } + + private static Supplier> mergeProperties( + Supplier> first, Supplier> second) { + return () -> { + Map merged = new HashMap<>(); + merged.putAll(first.get()); + merged.putAll(second.get()); + return merged; + }; + } +} diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/DefaultConfigProperties.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/DefaultConfigProperties.java index 9e912df717..c65c84bcdb 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/DefaultConfigProperties.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/DefaultConfigProperties.java @@ -30,18 +30,22 @@ final class DefaultConfigProperties implements ConfigProperties { private final Map config; - static ConfigProperties get() { - return new DefaultConfigProperties(System.getProperties(), System.getenv()); + static ConfigProperties get(Map defaultProperties) { + return new DefaultConfigProperties(System.getProperties(), System.getenv(), defaultProperties); } // Visible for testing static ConfigProperties createForTest(Map properties) { - return new DefaultConfigProperties(properties, Collections.emptyMap()); + return new DefaultConfigProperties(properties, Collections.emptyMap(), Collections.emptyMap()); } private DefaultConfigProperties( - Map systemProperties, Map environmentVariables) { + Map systemProperties, + Map environmentVariables, + Map defaultProperties) { Map config = new HashMap<>(); + defaultProperties.forEach( + (name, value) -> config.put(name.toLowerCase(Locale.ROOT).replace('-', '.'), value)); environmentVariables.forEach( (name, value) -> config.put(name.toLowerCase(Locale.ROOT).replace('_', '.'), value)); systemProperties.forEach( diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/EnvironmentResource.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/EnvironmentResource.java index d6061ebac7..3f9abbfde1 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/EnvironmentResource.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/EnvironmentResource.java @@ -10,12 +10,16 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import java.util.Collections; /** * Factory for a {@link Resource} which parses the standard "otel.resource.attributes" system * property or OTEL_RESOURCE_ATTRIBUTES environment variable. Will also use * OTEL_SERVICE_NAME/otel.service.name to specifically set the service name. + * + * @deprecated Use {@link AutoConfiguredOpenTelemetrySdk#getResource()}. */ +@Deprecated public final class EnvironmentResource { // Visible for testing @@ -26,9 +30,13 @@ public final class EnvironmentResource { * Returns a {@link Resource} which contains information from the standard * "otel.resource.attributes"/"otel.service.name" system properties or * OTEL_RESOURCE_ATTRIBUTES/OTEL_SERVICE_NAME environment variables. + * + * @deprecated Use the information retrievable from {@link + * AutoConfiguredOpenTelemetrySdk#getResource()}. */ + @Deprecated public static Resource get() { - return create(DefaultConfigProperties.get()); + return create(DefaultConfigProperties.get(Collections.emptyMap())); } static Resource create(ConfigProperties config) { diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetryResourceAutoConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetryResourceAutoConfiguration.java index 479048900f..e1a02789bd 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetryResourceAutoConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetryResourceAutoConfiguration.java @@ -8,11 +8,18 @@ package io.opentelemetry.sdk.autoconfigure; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; +import java.util.Collections; import java.util.HashSet; import java.util.ServiceLoader; import java.util.Set; +import java.util.function.BiFunction; -/** Auto-configuration for the OpenTelemetry {@link Resource}. */ +/** + * Auto-configuration for the OpenTelemetry {@link Resource}. + * + * @deprecated Use {@link AutoConfiguredOpenTelemetrySdk#getResource()}. + */ +@Deprecated public final class OpenTelemetryResourceAutoConfiguration { /** @@ -20,16 +27,29 @@ public final class OpenTelemetryResourceAutoConfiguration { * *

This method will auto-configure the returned {@link Resource} using system properties and * environment variables. + * + * @deprecated Use {@link AutoConfiguredOpenTelemetrySdk#getResource()}. */ + @Deprecated public static Resource configureResource() { - return configureResource(DefaultConfigProperties.get()); + return configureResource(DefaultConfigProperties.get(Collections.emptyMap())); } /** * Returns a {@link Resource} automatically initialized through recognized system properties and * environment variables. + * + * @deprecated Use {@link AutoConfiguredOpenTelemetrySdk#getResource()}. */ + @Deprecated public static Resource configureResource(ConfigProperties config) { + return configureResource(config, (a, unused) -> a); + } + + @SuppressWarnings("deprecation") // Uses class which will be made package private + static Resource configureResource( + ConfigProperties config, + BiFunction resourceCustomizer) { Resource result = Resource.getDefault(); // TODO(anuraaga): We use a hyphen only once in this artifact, for @@ -46,7 +66,7 @@ public final class OpenTelemetryResourceAutoConfiguration { result = result.merge(EnvironmentResource.create(config)); - return result; + return resourceCustomizer.apply(result, config); } private OpenTelemetryResourceAutoConfiguration() {} diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfiguration.java index 7190264844..e3b4074cba 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfiguration.java @@ -9,6 +9,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.metrics.GlobalMeterProvider; import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.metrics.SdkMeterProviderConfigurer; @@ -17,13 +18,19 @@ import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; import io.opentelemetry.sdk.metrics.exemplar.ExemplarFilter; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.sdk.trace.samplers.Sampler; import java.util.ServiceLoader; +import java.util.function.BiFunction; /** * Auto-configuration for the OpenTelemetry SDK. As an alternative to programmatically configuring * the SDK using {@link OpenTelemetrySdk#builder()}, this package can be used to automatically * configure the SDK using environment properties specified by OpenTelemetry. + * + * @deprecated Use {@link AutoConfiguredOpenTelemetrySdk}. */ +@Deprecated public final class OpenTelemetrySdkAutoConfiguration { /** @@ -32,9 +39,12 @@ public final class OpenTelemetrySdkAutoConfiguration { * *

This will automatically set the resulting SDK as the {@link * io.opentelemetry.api.GlobalOpenTelemetry} instance. + * + * @deprecated Use {@link AutoConfiguredOpenTelemetrySdk#initialize()}. */ + @Deprecated public static OpenTelemetrySdk initialize() { - return initialize(true); + return AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); } /** @@ -43,9 +53,15 @@ public final class OpenTelemetrySdkAutoConfiguration { * * @param setResultAsGlobal Whether to automatically set the configured SDK as the {@link * io.opentelemetry.api.GlobalOpenTelemetry} instance. + * @deprecated Use {@code + * AutoConfiguredSdk.builder().setResultAsGlobal(setResultAsGlobal).build().getOpenTelemetrySdk()}. */ + @Deprecated public static OpenTelemetrySdk initialize(boolean setResultAsGlobal) { - return initialize(setResultAsGlobal, DefaultConfigProperties.get()); + return AutoConfiguredOpenTelemetrySdk.builder() + .setResultAsGlobal(setResultAsGlobal) + .build() + .getOpenTelemetrySdk(); } /** @@ -56,16 +72,35 @@ public final class OpenTelemetrySdkAutoConfiguration { * GlobalOpenTelemetry} instance. * @param config A {@link ConfigProperties} instance that contains properties that are to be used * to auto-configure the returned {@link OpenTelemetrySdk}. + * @deprecated Use {@code + * AutoConfiguredSdk.builder().setResultAsGlobal(setResultAsGlobal).setConfig(config).build().getOpenTelemetrySdk()}. */ + @Deprecated public static OpenTelemetrySdk initialize(boolean setResultAsGlobal, ConfigProperties config) { - ContextPropagators propagators = PropagatorConfiguration.configurePropagators(config); + return AutoConfiguredOpenTelemetrySdk.builder() + .setResultAsGlobal(setResultAsGlobal) + .setConfig(config) + .build() + .getOpenTelemetrySdk(); + } - Resource resource = OpenTelemetryResourceAutoConfiguration.configureResource(config); + static OpenTelemetrySdk newOpenTelemetrySdk( + ConfigProperties config, + Resource resource, + BiFunction + propagatorCustomizer, + BiFunction + spanExporterCustomizer, + BiFunction samplerCustomizer, + boolean setResultAsGlobal) { + ContextPropagators propagators = + PropagatorConfiguration.configurePropagators(config, propagatorCustomizer); configureMeterProvider(resource, config); SdkTracerProvider tracerProvider = - TracerProviderConfiguration.configureTracerProvider(resource, config); + TracerProviderConfiguration.configureTracerProvider( + resource, config, spanExporterCustomizer, samplerCustomizer); OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder() diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/PropagatorConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/PropagatorConfiguration.java index 27228fa32b..819142c2c8 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/PropagatorConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/PropagatorConfiguration.java @@ -17,10 +17,14 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.BiFunction; final class PropagatorConfiguration { - static ContextPropagators configurePropagators(ConfigProperties config) { + static ContextPropagators configurePropagators( + ConfigProperties config, + BiFunction + propagatorCustomizer) { Set propagators = new LinkedHashSet<>(); List requestedPropagators = config.getList("otel.propagators"); if (requestedPropagators.isEmpty()) { @@ -36,7 +40,8 @@ final class PropagatorConfiguration { config); for (String propagatorName : requestedPropagators) { - propagators.add(getPropagator(propagatorName, spiPropagators)); + propagators.add( + propagatorCustomizer.apply(getPropagator(propagatorName, spiPropagators), config)); } return ContextPropagators.create(TextMapPropagator.composite(propagators)); 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 26af736aa6..d8d41f0e89 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 @@ -32,6 +32,7 @@ import java.util.HashSet; 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 { @@ -39,7 +40,10 @@ final class SpanExporterConfiguration { private static final String EXPORTER_NONE = "none"; // Visible for testing - static Map configureSpanExporters(ConfigProperties config) { + static Map configureSpanExporters( + ConfigProperties config, + BiFunction + spanExporterCustomizer) { List exporterNamesList = config.getList("otel.traces.exporter"); Set exporterNames = new HashSet<>(exporterNamesList); if (exporterNamesList.size() != exporterNames.size()) { @@ -58,7 +62,12 @@ final class SpanExporterConfiguration { throw new ConfigurationException( "otel.traces.exporter contains " + EXPORTER_NONE + " along with other exporters"); } - return Collections.emptyMap(); + SpanExporter noop = SpanExporter.composite(); + SpanExporter customized = spanExporterCustomizer.apply(noop, config); + if (customized == noop) { + return Collections.emptyMap(); + } + return Collections.singletonMap("none", customized); } if (exporterNames.isEmpty()) { @@ -77,7 +86,9 @@ final class SpanExporterConfiguration { .collect( toMap( Function.identity(), - exporterName -> configureExporter(exporterName, config, spiExporters))); + exporterName -> + spanExporterCustomizer.apply( + configureExporter(exporterName, config, spiExporters), config))); } // 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 fe2ccaba20..68ce88cc24 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 @@ -27,19 +27,27 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ServiceLoader; +import java.util.function.BiFunction; final class TracerProviderConfiguration { - static SdkTracerProvider configureTracerProvider(Resource resource, ConfigProperties config) { + static SdkTracerProvider configureTracerProvider( + Resource resource, + ConfigProperties config, + BiFunction + spanExporterCustomizer, + BiFunction samplerCustomizer) { SdkTracerProviderBuilder tracerProviderBuilder = SdkTracerProvider.builder() .setResource(resource) .setSpanLimits(configureSpanLimits(config)); String sampler = config.getString("otel.traces.sampler"); - if (sampler != null) { - tracerProviderBuilder.setSampler(configureSampler(sampler, config)); + if (sampler == null) { + sampler = "parentbased_always_on"; } + tracerProviderBuilder.setSampler( + samplerCustomizer.apply(configureSampler(sampler, config), config)); // Run user configuration before setting exporters from environment to allow user span // processors to effect export. @@ -49,7 +57,7 @@ final class TracerProviderConfiguration { } Map exportersByName = - SpanExporterConfiguration.configureSpanExporters(config); + SpanExporterConfiguration.configureSpanExporters(config, spanExporterCustomizer); configureSpanProcessors(config, exportersByName) .forEach(tracerProviderBuilder::addSpanProcessor); diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/EnvironmentResourceTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/EnvironmentResourceTest.java index 840adff68a..9b6841f223 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/EnvironmentResourceTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/EnvironmentResourceTest.java @@ -14,6 +14,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; import org.junit.jupiter.api.Test; +@SuppressWarnings("deprecation") // Tests class which will be made package private class EnvironmentResourceTest { @Test diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java index 059a2781bd..323decbe3f 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java @@ -130,7 +130,8 @@ class NotOnClasspathTest { () -> PropagatorConfiguration.configurePropagators( DefaultConfigProperties.createForTest( - Collections.singletonMap("otel.propagators", "b3")))) + Collections.singletonMap("otel.propagators", "b3")), + (a, config) -> a)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("Unrecognized value for otel.propagators: b3"); } diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfigurationTest.java new file mode 100644 index 0000000000..cea6a5227b --- /dev/null +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfigurationTest.java @@ -0,0 +1,136 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.autoconfigure; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.ContextKey; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import io.opentelemetry.sdk.trace.samplers.SamplingResult; +import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import java.util.Collections; +import java.util.Map; +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.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class OpenTelemetrySdkAutoConfigurationTest { + + private static final ContextKey CONTEXT_KEY = ContextKey.named("animal"); + + @Mock private TextMapPropagator propagator1; + @Mock private TextMapPropagator propagator2; + @Mock private TextMapGetter> getter; + @Mock private Sampler sampler1; + @Mock private Sampler sampler2; + @Mock private SpanExporter spanExporter1; + @Mock private SpanExporter spanExporter2; + + @BeforeEach + void resetGlobal() { + GlobalOpenTelemetry.resetForTest(); + } + + @Test + void customize() { + Context extracted = Context.root().with(CONTEXT_KEY, "bear"); + when(propagator2.extract(any(), any(), any())).thenReturn(extracted); + + when(sampler2.shouldSample(any(), any(), any(), any(), any(), any())) + .thenReturn(SamplingResult.recordAndSample()); + + when(spanExporter2.export(any())).thenReturn(CompletableResultCode.ofSuccess()); + + when(spanExporter2.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); + + AutoConfiguredOpenTelemetrySdkBuilder autoConfiguration = + AutoConfiguredOpenTelemetrySdk.builder() + .addPropagatorCustomizer( + (previous, config) -> { + assertThat(previous).isSameAs(W3CTraceContextPropagator.getInstance()); + return propagator1; + }) + .addPropagatorCustomizer( + (previous, config) -> { + assertThat(previous).isSameAs(propagator1); + return propagator2; + }) + .addResourceCustomizer( + (resource, config) -> + resource.merge(Resource.builder().put("key2", "value2").build())) + .addSamplerCustomizer( + (previous, config) -> { + assertThat(previous).isEqualTo(Sampler.parentBased(Sampler.alwaysOn())); + return sampler1; + }) + .addSamplerCustomizer( + (previous, config) -> { + assertThat(previous).isSameAs(sampler1); + return sampler2; + }) + .addSpanExporterCustomizer( + (previous, config) -> { + assertThat(previous).isSameAs(SpanExporter.composite()); + return spanExporter1; + }) + .addSpanExporterCustomizer( + (previous, config) -> { + assertThat(previous).isSameAs(spanExporter1); + return spanExporter2; + }) + .addPropertiesSupplier(() -> Collections.singletonMap("key", "valueUnused")) + .addPropertiesSupplier(() -> Collections.singletonMap("key", "value")) + .addPropertiesSupplier(() -> Collections.singletonMap("otel-key", "otel-value")) + .addPropertiesSupplier( + () -> Collections.singletonMap("otel.propagators", "tracecontext")) + .addPropertiesSupplier(() -> Collections.singletonMap("otel.metrics.exporter", "none")) + .addPropertiesSupplier(() -> Collections.singletonMap("otel.traces.exporter", "none")) + .addPropertiesSupplier( + () -> Collections.singletonMap("otel.service.name", "test-service")) + .setResultAsGlobal(false); + + GlobalOpenTelemetry.set(OpenTelemetry.noop()); + AutoConfiguredOpenTelemetrySdk autoConfigured = autoConfiguration.build(); + assertThat(autoConfigured.getResource().getAttribute(ResourceAttributes.SERVICE_NAME)) + .isEqualTo("test-service"); + assertThat(autoConfigured.getResource().getAttribute(stringKey("key2"))).isEqualTo("value2"); + + assertThat(autoConfigured.getConfig().getString("key")).isEqualTo("value"); + assertThat(autoConfigured.getConfig().getString("otel.key")).isEqualTo("otel-value"); + + OpenTelemetrySdk sdk = autoConfigured.getOpenTelemetrySdk(); + // Verify setResultAsGlobal respected + assertThat(sdk).isNotSameAs(GlobalOpenTelemetry.get()); + + assertThat( + sdk.getPropagators() + .getTextMapPropagator() + .extract(Context.root(), Collections.emptyMap(), getter)) + .isEqualTo(extracted); + + sdk.getTracerProvider().get("test").spanBuilder("test").startSpan().end(); + + // Ensures the export happened. + sdk.getSdkTracerProvider().shutdown().join(10, TimeUnit.SECONDS); + } +} diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/PropagatorConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/PropagatorConfigurationTest.java index a7ae1344dd..bc09ddb41d 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/PropagatorConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/PropagatorConfigurationTest.java @@ -17,7 +17,7 @@ class PropagatorConfigurationTest { void defaultPropagators() { ContextPropagators contextPropagators = PropagatorConfiguration.configurePropagators( - DefaultConfigProperties.createForTest(Collections.emptyMap())); + DefaultConfigProperties.createForTest(Collections.emptyMap()), (a, unused) -> a); assertThat(contextPropagators.getTextMapPropagator().fields()) .containsExactlyInAnyOrder("traceparent", "tracestate", "baggage"); diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/ResourceTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/ResourceTest.java index 5619ccbc6b..2974833053 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/ResourceTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/ResourceTest.java @@ -5,21 +5,19 @@ package io.opentelemetry.sdk.autoconfigure; -import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import java.util.HashMap; +import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +@SuppressWarnings("deprecation") // Testing class which will be made package-private @ExtendWith(MockitoExtension.class) class ResourceTest { - @Mock ConfigProperties config; @Test void noResourceProviders() { @@ -30,10 +28,13 @@ class ResourceTest { @Test void customConfigResource() { - when(config.getString("otel.service.name")).thenReturn("test-service"); - when(config.getMap("otel.resource.attributes")).thenReturn(singletonMap("food", "cheesecake")); + Map props = new HashMap<>(); + props.put("otel.service.name", "test-service"); + props.put("otel.resource.attributes", "food=cheesecake"); - assertThat(OpenTelemetryResourceAutoConfiguration.configureResource(config)) + assertThat( + OpenTelemetryResourceAutoConfiguration.configureResource( + DefaultConfigProperties.get(props))) .isEqualTo( Resource.getDefault().toBuilder() .put(ResourceAttributes.SERVICE_NAME, "test-service") 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 db8282f4e4..beff9f875c 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 @@ -62,7 +62,10 @@ class TracerProviderConfigurationTest { // are verified in other test sets like testFullConfig. SdkTracerProvider tracerProvider = TracerProviderConfiguration.configureTracerProvider( - resource, DefaultConfigProperties.createForTest(properties)); + resource, + DefaultConfigProperties.createForTest(properties), + (a, unused) -> a, + (a, unused) -> a); try { assertThat(tracerProvider.getSampler()).isEqualTo(Sampler.alwaysOff()); diff --git a/sdk-extensions/autoconfigure/src/testConfigError/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java b/sdk-extensions/autoconfigure/src/testConfigError/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java index 315fc2edbd..5e9cb3c553 100644 --- a/sdk-extensions/autoconfigure/src/testConfigError/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java +++ b/sdk-extensions/autoconfigure/src/testConfigError/java/io/opentelemetry/sdk/autoconfigure/ConfigErrorTest.java @@ -29,7 +29,7 @@ class ConfigErrorTest { @Test @SetSystemProperty(key = "otel.propagators", value = "cat") void invalidPropagator() { - assertThatThrownBy(OpenTelemetrySdkAutoConfiguration::initialize) + assertThatThrownBy(AutoConfiguredOpenTelemetrySdk::initialize) .isInstanceOf(ConfigurationException.class) .hasMessage( "Unrecognized value for otel.propagators: cat. Make sure the artifact " @@ -40,7 +40,7 @@ class ConfigErrorTest { @SetSystemProperty(key = "otel.traces.sampler", value = "traceidratio") @SetSystemProperty(key = "otel.traces.sampler.arg", value = "bar") void invalidTraceIdRatio() { - assertThatThrownBy(OpenTelemetrySdkAutoConfiguration::initialize) + assertThatThrownBy(AutoConfiguredOpenTelemetrySdk::initialize) .isInstanceOf(ConfigurationException.class) .hasMessage("Invalid value for property otel.traces.sampler.arg=bar. Must be a double."); } @@ -49,7 +49,7 @@ class ConfigErrorTest { @SetSystemProperty(key = "otel.traces.sampler", value = "parentbased_traceidratio") @SetSystemProperty(key = "otel.traces.sampler.arg", value = "bar") void invalidTraceIdRatioWithParent() { - assertThatThrownBy(OpenTelemetrySdkAutoConfiguration::initialize) + assertThatThrownBy(AutoConfiguredOpenTelemetrySdk::initialize) .isInstanceOf(ConfigurationException.class) .hasMessage("Invalid value for property otel.traces.sampler.arg=bar. Must be a double."); } @@ -57,7 +57,7 @@ class ConfigErrorTest { @Test @SetSystemProperty(key = "otel.traces.sampler", value = "cat") void invalidSampler() { - assertThatThrownBy(OpenTelemetrySdkAutoConfiguration::initialize) + assertThatThrownBy(AutoConfiguredOpenTelemetrySdk::initialize) .isInstanceOf(ConfigurationException.class) .hasMessage("Unrecognized value for otel.traces.sampler: cat"); } 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 38656f9a5e..3623a268c8 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 @@ -30,7 +30,7 @@ public class ConfigurableSpanExporterTest { DefaultConfigProperties.createForTest( ImmutableMap.of("test.option", "true", "otel.traces.exporter", "testExporter")); Map exportersByName = - SpanExporterConfiguration.configureSpanExporters(config); + SpanExporterConfiguration.configureSpanExporters(config, (a, unused) -> a); assertThat(exportersByName) .hasSize(1) @@ -47,7 +47,8 @@ public class ConfigurableSpanExporterTest { DefaultConfigProperties.createForTest( ImmutableMap.of("otel.traces.exporter", "otlp,otlp,logging")); - assertThatThrownBy(() -> SpanExporterConfiguration.configureSpanExporters(config)) + assertThatThrownBy( + () -> SpanExporterConfiguration.configureSpanExporters(config, (a, unused) -> a)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("otel.traces.exporter contains duplicates: [otlp]"); } @@ -57,7 +58,8 @@ public class ConfigurableSpanExporterTest { ConfigProperties config = DefaultConfigProperties.createForTest(ImmutableMap.of("otel.traces.exporter", "otlp,none")); - assertThatThrownBy(() -> SpanExporterConfiguration.configureSpanExporters(config)) + assertThatThrownBy( + () -> SpanExporterConfiguration.configureSpanExporters(config, (a, unused) -> a)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining("otel.traces.exporter contains none along with other exporters"); } 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 0f01cb5928..24faebc000 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 @@ -173,6 +173,10 @@ class FullConfigTest { .setKey("configured") .setValue(AnyValue.newBuilder().setBoolValue(true).build()) .build(), + KeyValue.newBuilder() + .setKey("wrapped") + .setValue(AnyValue.newBuilder().setIntValue(1).build()) + .build(), KeyValue.newBuilder() .setKey("cat") .setValue(AnyValue.newBuilder().setStringValue("meow").build()) diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ResourceTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ResourceTest.java index 9fdc952126..0886dd7254 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ResourceTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ResourceTest.java @@ -11,6 +11,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; import org.junit.jupiter.api.Test; +@SuppressWarnings("deprecation") // Testing class which will be made package-private class ResourceTest { @Test diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterCustomizer.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterCustomizer.java new file mode 100644 index 0000000000..a2a4426212 --- /dev/null +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterCustomizer.java @@ -0,0 +1,52 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.autoconfigure; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; +import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.trace.data.DelegatingSpanData; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.util.Collection; +import java.util.stream.Collectors; + +public class SpanExporterCustomizer implements AutoConfigurationCustomizerProvider { + @Override + public void customize(AutoConfigurationCustomizer autoConfiguration) { + autoConfiguration.addSpanExporterCustomizer( + (delegate, config) -> + new SpanExporter() { + @Override + public CompletableResultCode export(Collection spans) { + return delegate.export( + spans.stream() + .map( + span -> + new DelegatingSpanData(span) { + @Override + public Attributes getAttributes() { + return span.getAttributes().toBuilder() + .put("wrapped", config.getInt("otel.test.wrapped")) + .build(); + } + }) + .collect(Collectors.toList())); + } + + @Override + public CompletableResultCode flush() { + return delegate.flush(); + } + + @Override + public CompletableResultCode shutdown() { + return delegate.shutdown(); + } + }); + } +} diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider b/sdk-extensions/autoconfigure/src/testFullConfig/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider new file mode 100644 index 0000000000..72613dd854 --- /dev/null +++ b/sdk-extensions/autoconfigure/src/testFullConfig/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider @@ -0,0 +1 @@ +io.opentelemetry.sdk.autoconfigure.SpanExporterCustomizer \ No newline at end of file diff --git a/sdk-extensions/autoconfigure/src/testInitializeRegistersGlobal/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfigurationTest.java b/sdk-extensions/autoconfigure/src/testInitializeRegistersGlobal/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfigurationTest.java index baae8e0293..bcbe0aeb82 100644 --- a/sdk-extensions/autoconfigure/src/testInitializeRegistersGlobal/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/testInitializeRegistersGlobal/java/io/opentelemetry/sdk/autoconfigure/OpenTelemetrySdkAutoConfigurationTest.java @@ -24,7 +24,7 @@ class OpenTelemetrySdkAutoConfigurationTest { @Test void initializeAndGet() { - OpenTelemetrySdk sdk = OpenTelemetrySdkAutoConfiguration.initialize(); + OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); assertThat(GlobalOpenTelemetry.get()) // ObfuscatedOpenTelemetry .extracting("delegate") @@ -33,7 +33,11 @@ class OpenTelemetrySdkAutoConfigurationTest { @Test void initializeAndGet_noGlobal() { - OpenTelemetrySdk sdk = OpenTelemetrySdkAutoConfiguration.initialize(false); + 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 diff --git a/sdk-extensions/autoconfigure/src/testJaeger/java/io/opentelemetry/sdk/autoconfigure/JaegerConfigTest.java b/sdk-extensions/autoconfigure/src/testJaeger/java/io/opentelemetry/sdk/autoconfigure/JaegerConfigTest.java index 7c1b45805b..0f4d443f6b 100644 --- a/sdk-extensions/autoconfigure/src/testJaeger/java/io/opentelemetry/sdk/autoconfigure/JaegerConfigTest.java +++ b/sdk-extensions/autoconfigure/src/testJaeger/java/io/opentelemetry/sdk/autoconfigure/JaegerConfigTest.java @@ -61,7 +61,7 @@ class JaegerConfigTest { System.setProperty("otel.exporter.jaeger.endpoint", endpoint); - OpenTelemetrySdkAutoConfiguration.initialize(); + AutoConfiguredOpenTelemetrySdk.initialize(); GlobalOpenTelemetry.get().getTracer("test").spanBuilder("test").startSpan().end(); diff --git a/sdk-extensions/autoconfigure/src/testPrometheus/java/io/opentelemetry/sdk/autoconfigure/PrometheusTest.java b/sdk-extensions/autoconfigure/src/testPrometheus/java/io/opentelemetry/sdk/autoconfigure/PrometheusTest.java index 4457d400df..818602bf44 100644 --- a/sdk-extensions/autoconfigure/src/testPrometheus/java/io/opentelemetry/sdk/autoconfigure/PrometheusTest.java +++ b/sdk-extensions/autoconfigure/src/testPrometheus/java/io/opentelemetry/sdk/autoconfigure/PrometheusTest.java @@ -33,7 +33,7 @@ class PrometheusTest { } System.setProperty("otel.exporter.prometheus.host", "127.0.0.1"); System.setProperty("otel.exporter.prometheus.port", String.valueOf(port)); - OpenTelemetrySdkAutoConfiguration.initialize(); + AutoConfiguredOpenTelemetrySdk.initialize(); GlobalMeterProvider.get() .get("test") diff --git a/sdk-extensions/autoconfigure/src/testResourceDisabledByEnv/java/io/opentelemetry/sdk/resources/ResourceDisabledByEnvTest.java b/sdk-extensions/autoconfigure/src/testResourceDisabledByEnv/java/io/opentelemetry/sdk/resources/ResourceDisabledByEnvTest.java deleted file mode 100644 index 2e90e774ec..0000000000 --- a/sdk-extensions/autoconfigure/src/testResourceDisabledByEnv/java/io/opentelemetry/sdk/resources/ResourceDisabledByEnvTest.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.resources; - -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.sdk.autoconfigure.OpenTelemetryResourceAutoConfiguration; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import org.junit.jupiter.api.Test; - -class ResourceDisabledByEnvTest { - - @Test - void osAndProcessDisabled() { - Resource resource = OpenTelemetryResourceAutoConfiguration.configureResource(); - - assertThat(resource.getAttribute(ResourceAttributes.OS_TYPE)).isNull(); - assertThat(resource.getAttribute(ResourceAttributes.PROCESS_PID)).isNull(); - assertThat(resource.getAttribute(ResourceAttributes.PROCESS_RUNTIME_NAME)).isNotNull(); - } -} diff --git a/sdk-extensions/autoconfigure/src/testResourceDisabledByProperty/java/io/opentelemetry/sdk/resources/ResourceDisabledByPropertyTest.java b/sdk-extensions/autoconfigure/src/testResourceDisabledByProperty/java/io/opentelemetry/sdk/resources/ResourceDisabledByPropertyTest.java deleted file mode 100644 index 2e3c982f60..0000000000 --- a/sdk-extensions/autoconfigure/src/testResourceDisabledByProperty/java/io/opentelemetry/sdk/resources/ResourceDisabledByPropertyTest.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.resources; - -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.sdk.autoconfigure.OpenTelemetryResourceAutoConfiguration; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import org.junit.jupiter.api.Test; - -class ResourceDisabledByPropertyTest { - - @Test - void osAndProcessDisabled() { - Resource resource = OpenTelemetryResourceAutoConfiguration.configureResource(); - - assertThat(resource.getAttribute(ResourceAttributes.OS_TYPE)).isNull(); - assertThat(resource.getAttribute(ResourceAttributes.PROCESS_PID)).isNull(); - assertThat(resource.getAttribute(ResourceAttributes.PROCESS_RUNTIME_NAME)).isNotNull(); - } -} diff --git a/sdk-extensions/autoconfigure/src/testZipkin/java/io/opentelemetry/sdk/autoconfigure/ZipkinConfigTest.java b/sdk-extensions/autoconfigure/src/testZipkin/java/io/opentelemetry/sdk/autoconfigure/ZipkinConfigTest.java index 24f6ba8a04..58e5046c91 100644 --- a/sdk-extensions/autoconfigure/src/testZipkin/java/io/opentelemetry/sdk/autoconfigure/ZipkinConfigTest.java +++ b/sdk-extensions/autoconfigure/src/testZipkin/java/io/opentelemetry/sdk/autoconfigure/ZipkinConfigTest.java @@ -54,7 +54,7 @@ class ZipkinConfigTest { System.setProperty("otel.exporter.zipkin.endpoint", "http://" + endpoint + "/api/v2/spans"); System.setProperty("otel.exporter.zipkin.timeout", "5s"); - OpenTelemetrySdkAutoConfiguration.initialize(); + AutoConfiguredOpenTelemetrySdk.initialize(); GlobalOpenTelemetry.get().getTracer("test").spanBuilder("test").startSpan().end();