diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/ExtendedOpenTelemetry.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/ExtendedOpenTelemetry.java index 6509e4f4865..74883fa2302 100644 --- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/ExtendedOpenTelemetry.java +++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/ExtendedOpenTelemetry.java @@ -7,6 +7,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.incubator.config.ConfigProvider; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; /** Extension to {@link OpenTelemetry} with experimental APIs. */ public interface ExtendedOpenTelemetry extends OpenTelemetry { @@ -14,4 +15,41 @@ public interface ExtendedOpenTelemetry extends OpenTelemetry { default ConfigProvider getConfigProvider() { return ConfigProvider.noop(); } + + /** + * Returns the {@link DeclarativeConfigProperties} for a specific instrumentation by name. If no + * configuration is available for the given name, an empty {@link DeclarativeConfigProperties} is + * returned. + * + *
For example, {@code getInstrumentationConfig("foo")} returns the node: + * + *
{@code
+ * instrumentation/development:
+ * java:
+ * foo:
+ * }
+ *
+ * @param name the name of the instrumentation
+ * @return the {@link DeclarativeConfigProperties} for the given instrumentation name
+ */
+ default DeclarativeConfigProperties getInstrumentationConfig(String name) {
+ return getConfigProvider().getInstrumentationConfig(name);
+ }
+
+ /**
+ * Returns the {@link DeclarativeConfigProperties} for general instrumentation configuration.
+ *
+ * {@code
+ * instrumentation/development:
+ * general:
+ * }
+ *
+ * If the general configuration is not available, an empty {@link DeclarativeConfigProperties} + * is returned. + * + * @return the {@link DeclarativeConfigProperties} for the general instrumentation configuration + */ + default DeclarativeConfigProperties getGeneralInstrumentationConfig() { + return getConfigProvider().getGeneralInstrumentationConfig(); + } } diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigProvider.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigProvider.java index 70717e76e40..dcf6c7bd082 100644 --- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigProvider.java +++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigProvider.java @@ -28,6 +28,43 @@ public interface ConfigProvider { */ DeclarativeConfigProperties getInstrumentationConfig(); + /** + * Returns the {@link DeclarativeConfigProperties} for a specific instrumentation by name. If no + * configuration is available for the given name, an empty {@link DeclarativeConfigProperties} is + * returned. + * + *
For example, {@code getInstrumentationConfig("foo")} returns the node: + * + *
{@code
+ * instrumentation/development:
+ * java:
+ * foo:
+ * }
+ *
+ * @param name the name of the instrumentation
+ * @return the {@link DeclarativeConfigProperties} for the given instrumentation name
+ */
+ default DeclarativeConfigProperties getInstrumentationConfig(String name) {
+ return getInstrumentationConfig().get("java").get(name);
+ }
+
+ /**
+ * Returns the {@link DeclarativeConfigProperties} for general instrumentation configuration.
+ *
+ * {@code
+ * instrumentation/development:
+ * general:
+ * }
+ *
+ * If the general configuration is not available, an empty {@link DeclarativeConfigProperties} + * is returned. + * + * @return the {@link DeclarativeConfigProperties} for the general instrumentation configuration + */ + default DeclarativeConfigProperties getGeneralInstrumentationConfig() { + return getInstrumentationConfig().get("general"); + } + /** Returns a no-op {@link ConfigProvider}. */ static ConfigProvider noop() { return DeclarativeConfigProperties::empty; diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/ConfigProviderTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/ConfigProviderTest.java index 9c9e4bf41e1..b5fdca1cdf6 100644 --- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/ConfigProviderTest.java +++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/ConfigProviderTest.java @@ -17,4 +17,12 @@ void noopEquality() { ConfigProvider noop = ConfigProvider.noop(); assertThat(ConfigProvider.noop()).isSameAs(noop); } + + @Test + void instrumentationConfigFallback() { + ConfigProvider configProvider = ConfigProvider.noop(); + assertThat(configProvider.getInstrumentationConfig()).isNotNull(); + assertThat(configProvider.getInstrumentationConfig("servlet")).isNotNull(); + assertThat(configProvider.getGeneralInstrumentationConfig()).isNotNull(); + } } diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/ExtendedOpenTelemetryTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/ExtendedOpenTelemetryTest.java index 651eae4bc14..b8ff8ce9289 100644 --- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/ExtendedOpenTelemetryTest.java +++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/ExtendedOpenTelemetryTest.java @@ -6,9 +6,12 @@ package io.opentelemetry.api.incubator; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.ConfigProvider; import io.opentelemetry.api.incubator.logs.ExtendedDefaultLoggerProvider; import io.opentelemetry.api.incubator.logs.ExtendedLogger; import io.opentelemetry.api.incubator.metrics.ExtendedDefaultMeterProvider; @@ -22,8 +25,12 @@ import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.extension.incubator.ExtendedOpenTelemetrySdk; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -70,4 +77,50 @@ private static void assertIsExtended(OpenTelemetry openTelemetry) { assertThat(openTelemetry.getLogsBridge().get("test")).isInstanceOf(ExtendedLogger.class); assertThat(openTelemetry.getTracer("test")).isInstanceOf(ExtendedTracer.class); } + + @Test + void instrumentationConfig() { + String configYaml = + "instrumentation/development:\n" + + " general:\n" + + " http:\n" + + " client:\n" + + " request_captured_headers:\n" + + " - client-request-header1\n" + + " - client-request-header2\n" + + " java:\n" + + " example:\n" + + " property: \"value\""; + + OpenTelemetryConfigurationModel configuration = + DeclarativeConfiguration.parse( + new ByteArrayInputStream(configYaml.getBytes(StandardCharsets.UTF_8))); + SdkConfigProvider configProvider = SdkConfigProvider.create(configuration); + ExtendedOpenTelemetry openTelemetry = + ExtendedOpenTelemetrySdk.create(OpenTelemetrySdk.builder().build(), configProvider); + + // shortcuts to get specific instrumentation config + assertThat(openTelemetry.getInstrumentationConfig("example").getString("property")) + .isEqualTo("value"); + assertThat( + openTelemetry + .getGeneralInstrumentationConfig() + .get("http") + .get("client") + .getScalarList("request_captured_headers", String.class)) + .isEqualTo(Arrays.asList("client-request-header1", "client-request-header2")); + } + + @Test + void instrumentationConfigFallback() { + ConfigProvider configProvider = ConfigProvider.noop(); + // cannot create ExtendedOpenTelemetry with noop ConfigProvider right now, + // but will be possible once stable API is available + ExtendedOpenTelemetry openTelemetry = spy(ExtendedOpenTelemetry.class); + when(openTelemetry.getConfigProvider()).thenReturn(configProvider); + + assertThat(configProvider.getInstrumentationConfig()).isNotNull(); + assertThat(openTelemetry.getInstrumentationConfig("servlet")).isNotNull(); + assertThat(openTelemetry.getGeneralInstrumentationConfig()).isNotNull(); + } } diff --git a/sdk-extensions/autoconfigure/src/testIncubating/java/io/opentelemetry/sdk/autoconfigure/DeclarativeConfigurationTest.java b/sdk-extensions/autoconfigure/src/testIncubating/java/io/opentelemetry/sdk/autoconfigure/DeclarativeConfigurationTest.java index 88bdb322b26..3eb7f3914c5 100644 --- a/sdk-extensions/autoconfigure/src/testIncubating/java/io/opentelemetry/sdk/autoconfigure/DeclarativeConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/testIncubating/java/io/opentelemetry/sdk/autoconfigure/DeclarativeConfigurationTest.java @@ -224,5 +224,16 @@ void configFile_ConfigProvider() { assertThat(InstrumentationConfigUtil.javaInstrumentationConfig(globalConfigProvider, "example")) .isNotNull() .satisfies(exampleConfig -> assertThat(exampleConfig.getString("key")).isEqualTo("value")); + + // shortcuts to get specific instrumentation config + assertThat(globalConfigProvider.getInstrumentationConfig("example").getString("key")) + .isEqualTo("value"); + assertThat( + globalConfigProvider + .getGeneralInstrumentationConfig() + .get("http") + .get("client") + .getScalarList("request_captured_headers", String.class)) + .isEqualTo(Arrays.asList("Content-Type", "Accept")); } }