Add AutoConfigurationCustomizer#addPropertiesCustomizer() extension p… (#4608)
* Add AutoConfigurationCustomizer#addPropertiesCustomizer() extension point * jApiCmp * Update sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java Co-authored-by: jack-berg <34418638+jack-berg@users.noreply.github.com> * since Co-authored-by: jack-berg <34418638+jack-berg@users.noreply.github.com>
This commit is contained in:
parent
1d63b2accd
commit
91bd17e09b
|
|
@ -1,4 +1,7 @@
|
|||
Comparing source compatibility of against
|
||||
***! MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer (not serializable)
|
||||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||
+++! NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addPropertiesCustomizer(java.util.function.Function)
|
||||
*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider (not serializable)
|
||||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||
+++ NEW INTERFACE: io.opentelemetry.sdk.autoconfigure.spi.Ordered
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ 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.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/** A builder for customizing OpenTelemetry auto-configuration. */
|
||||
|
|
@ -72,6 +73,21 @@ public interface AutoConfigurationCustomizer {
|
|||
AutoConfigurationCustomizer addPropertiesSupplier(
|
||||
Supplier<Map<String, String>> propertiesSupplier);
|
||||
|
||||
/**
|
||||
* Adds a {@link Function} to invoke the with the {@link ConfigProperties} to allow customization.
|
||||
* The return value of the {@link Function} will be merged into the {@link ConfigProperties}
|
||||
* before it is used for auto-configuration, overwriting the properties that are already there.
|
||||
*
|
||||
* <p>Multiple calls will cause properties to be merged in order, with later ones overwriting
|
||||
* duplicate keys in earlier ones.
|
||||
*
|
||||
* @since 1.17.0
|
||||
*/
|
||||
default AutoConfigurationCustomizer addPropertiesCustomizer(
|
||||
Function<ConfigProperties, Map<String, String>> propertiesCustomizer) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link BiFunction} to invoke the with the {@link SdkTracerProviderBuilder} to allow
|
||||
* customization. The return value of the {@link BiFunction} will replace the passed-in argument.
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import java.util.Optional;
|
|||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
|
@ -77,6 +78,9 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
|
||||
private Supplier<Map<String, String>> propertiesSupplier = Collections::emptyMap;
|
||||
|
||||
private final List<Function<ConfigProperties, Map<String, String>>> propertiesCustomizers =
|
||||
new ArrayList<>();
|
||||
|
||||
private ClassLoader serviceClassLoader =
|
||||
AutoConfiguredOpenTelemetrySdkBuilder.class.getClassLoader();
|
||||
|
||||
|
|
@ -90,7 +94,8 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
|
||||
/**
|
||||
* Sets the {@link ConfigProperties} to use when resolving properties for auto-configuration.
|
||||
* {@link #addPropertiesSupplier(Supplier)} will have no effect if this method is used.
|
||||
* {@link #addPropertiesSupplier(Supplier)} and {@link #addPropertiesCustomizer(Function)} will
|
||||
* have no effect if this method is used.
|
||||
*/
|
||||
AutoConfiguredOpenTelemetrySdkBuilder setConfig(ConfigProperties config) {
|
||||
requireNonNull(config, "config");
|
||||
|
|
@ -191,6 +196,22 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Function} to invoke the with the {@link ConfigProperties} to allow customization.
|
||||
* The return value of the {@link Function} will be merged into the {@link ConfigProperties}
|
||||
* before it is used for auto-configuration, overwriting the properties that are already there.
|
||||
*
|
||||
* <p>Multiple calls will cause properties to be merged in order, with later ones overwriting
|
||||
* duplicate keys in earlier ones.
|
||||
*/
|
||||
@Override
|
||||
public AutoConfiguredOpenTelemetrySdkBuilder addPropertiesCustomizer(
|
||||
Function<ConfigProperties, Map<String, String>> propertiesCustomizer) {
|
||||
requireNonNull(propertiesCustomizer, "propertiesCustomizer");
|
||||
this.propertiesCustomizers.add(propertiesCustomizer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link BiFunction} to invoke the with the {@link SdkMeterProviderBuilder} to allow
|
||||
* customization. The return value of the {@link BiFunction} will replace the passed-in argument.
|
||||
|
|
@ -396,11 +417,20 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
private ConfigProperties getConfig() {
|
||||
ConfigProperties config = this.config;
|
||||
if (config == null) {
|
||||
config = DefaultConfigProperties.get(propertiesSupplier.get());
|
||||
config = computeConfigProperties();
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private ConfigProperties computeConfigProperties() {
|
||||
DefaultConfigProperties properties = DefaultConfigProperties.get(propertiesSupplier.get());
|
||||
for (Function<ConfigProperties, Map<String, String>> customizer : propertiesCustomizers) {
|
||||
Map<String, String> overrides = customizer.apply(properties);
|
||||
properties = DefaultConfigProperties.customize(properties, overrides);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static <I, O1, O2> BiFunction<I, ConfigProperties, O2> mergeCustomizer(
|
||||
BiFunction<? super I, ConfigProperties, ? extends O1> first,
|
||||
BiFunction<? super O1, ConfigProperties, ? extends O2> second) {
|
||||
|
|
|
|||
|
|
@ -36,10 +36,15 @@ final class DefaultConfigProperties implements ConfigProperties {
|
|||
|
||||
private final Map<String, String> config;
|
||||
|
||||
static ConfigProperties get(Map<String, String> defaultProperties) {
|
||||
static DefaultConfigProperties get(Map<String, String> defaultProperties) {
|
||||
return new DefaultConfigProperties(System.getProperties(), System.getenv(), defaultProperties);
|
||||
}
|
||||
|
||||
static DefaultConfigProperties customize(
|
||||
DefaultConfigProperties previousProperties, Map<String, String> overrides) {
|
||||
return new DefaultConfigProperties(previousProperties, overrides);
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
static ConfigProperties createForTest(Map<String, String> properties) {
|
||||
return new DefaultConfigProperties(properties, Collections.emptyMap(), Collections.emptyMap());
|
||||
|
|
@ -59,6 +64,15 @@ final class DefaultConfigProperties implements ConfigProperties {
|
|||
this.config = config;
|
||||
}
|
||||
|
||||
private DefaultConfigProperties(
|
||||
DefaultConfigProperties previousProperties, Map<String, String> overrides) {
|
||||
// previousProperties are already normalized, they can be copied as they are
|
||||
Map<String, String> config = new HashMap<>(previousProperties.config);
|
||||
overrides.forEach((name, value) -> config.put(normalize(name), value));
|
||||
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getString(String name) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
package io.opentelemetry.sdk.autoconfigure;
|
||||
|
||||
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.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
|
|
@ -114,8 +115,7 @@ class AutoConfiguredOpenTelemetrySdkTest {
|
|||
|
||||
OpenTelemetrySdk sdk =
|
||||
builder
|
||||
.addPropertiesSupplier(
|
||||
() -> Collections.singletonMap("otel.propagators", "tracecontext"))
|
||||
.addPropertiesSupplier(() -> singletonMap("otel.propagators", "tracecontext"))
|
||||
.addPropagatorCustomizer(
|
||||
(previous, config) -> {
|
||||
assertThat(previous).isSameAs(W3CTraceContextPropagator.getInstance());
|
||||
|
|
@ -205,12 +205,10 @@ class AutoConfiguredOpenTelemetrySdkTest {
|
|||
void builder_addPropertiesSupplier() {
|
||||
AutoConfiguredOpenTelemetrySdk autoConfigured =
|
||||
builder
|
||||
.addPropertiesSupplier(() -> Collections.singletonMap("key", "valueUnused"))
|
||||
.addPropertiesSupplier(() -> Collections.singletonMap("key", "value"))
|
||||
.addPropertiesSupplier(() -> Collections.singletonMap("otel-key", "otel-value"))
|
||||
.addPropertiesSupplier(
|
||||
() -> Collections.singletonMap("otel.service.name", "test-service"))
|
||||
.setResultAsGlobal(false)
|
||||
.addPropertiesSupplier(() -> singletonMap("key", "valueUnused"))
|
||||
.addPropertiesSupplier(() -> singletonMap("key", "value"))
|
||||
.addPropertiesSupplier(() -> singletonMap("otel-key", "otel-value"))
|
||||
.addPropertiesSupplier(() -> singletonMap("otel.service.name", "test-service"))
|
||||
.build();
|
||||
|
||||
assertThat(autoConfigured.getResource().getAttribute(ResourceAttributes.SERVICE_NAME))
|
||||
|
|
@ -219,6 +217,31 @@ class AutoConfiguredOpenTelemetrySdkTest {
|
|||
assertThat(autoConfigured.getConfig().getString("otel.key")).isEqualTo("otel-value");
|
||||
}
|
||||
|
||||
@Test
|
||||
void builder_addPropertiesCustomizer() {
|
||||
AutoConfiguredOpenTelemetrySdk autoConfigured =
|
||||
builder
|
||||
.addPropertiesSupplier(() -> singletonMap("some-key", "defaultValue"))
|
||||
.addPropertiesSupplier(() -> singletonMap("otel.service.name", "default-service-name"))
|
||||
.addPropertiesCustomizer(
|
||||
config -> {
|
||||
Map<String, String> overrides = new HashMap<>();
|
||||
overrides.put("some-key", "override");
|
||||
overrides.put(
|
||||
"otel.service.name",
|
||||
config.getString("otel.service.name", "").replace("default", "overridden"));
|
||||
return overrides;
|
||||
})
|
||||
.addPropertiesCustomizer(
|
||||
config -> singletonMap("some-key", config.getString("some-key", "") + "-2"))
|
||||
.build();
|
||||
|
||||
assertThat(autoConfigured.getResource().getAttribute(ResourceAttributes.SERVICE_NAME))
|
||||
.isEqualTo("overridden-service-name");
|
||||
assertThat(autoConfigured.getConfig().getString("some-key")).isEqualTo("override-2");
|
||||
assertThat(autoConfigured.getConfig().getString("some.key")).isEqualTo("override-2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void builder_addMeterProviderCustomizer() {
|
||||
Mockito.lenient().when(metricReader.shutdown()).thenReturn(CompletableResultCode.ofSuccess());
|
||||
|
|
@ -324,8 +347,7 @@ class AutoConfiguredOpenTelemetrySdkTest {
|
|||
|
||||
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
|
||||
AutoConfiguredOpenTelemetrySdk.builder()
|
||||
.addPropertiesSupplier(
|
||||
() -> Collections.singletonMap("otel.experimental.sdk.enabled", "false"))
|
||||
.addPropertiesSupplier(() -> singletonMap("otel.experimental.sdk.enabled", "false"))
|
||||
.addTracerProviderCustomizer(traceCustomizer)
|
||||
.addMeterProviderCustomizer(metricCustomizer)
|
||||
.addLogEmitterProviderCustomizer(logCustomizer)
|
||||
|
|
@ -352,9 +374,9 @@ class AutoConfiguredOpenTelemetrySdkTest {
|
|||
})
|
||||
.addResourceCustomizer(
|
||||
(resource, config) -> resource.merge(Resource.builder().put("cow", "moo").build()))
|
||||
.addPropertiesSupplier(() -> Collections.singletonMap("otel.metrics.exporter", "none"))
|
||||
.addPropertiesSupplier(() -> Collections.singletonMap("otel.traces.exporter", "none"))
|
||||
.addPropertiesSupplier(() -> Collections.singletonMap("otel.logs.exporter", "none"))
|
||||
.addPropertiesSupplier(() -> singletonMap("otel.metrics.exporter", "none"))
|
||||
.addPropertiesSupplier(() -> singletonMap("otel.traces.exporter", "none"))
|
||||
.addPropertiesSupplier(() -> singletonMap("otel.logs.exporter", "none"))
|
||||
.setResultAsGlobal(false);
|
||||
|
||||
AutoConfiguredOpenTelemetrySdk autoConfigured = autoConfiguration.build();
|
||||
|
|
|
|||
Loading…
Reference in New Issue