diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigChangeListener.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigChangeListener.java new file mode 100644 index 00000000000..44833713f8a --- /dev/null +++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigChangeListener.java @@ -0,0 +1,26 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.api.incubator.config; + +/** Listener notified when declarative configuration changes. */ +@FunctionalInterface +public interface ConfigChangeListener { + + /** + * Called when the watched path changes. + * + *
{@code path} is the changed declarative configuration path, for example {@code + * .instrumentation/development.general.http} or {@code + * .instrumentation/development.java.methods}. + * + *
{@code newConfig} is never null. If the watched node is unset or cleared, {@code newConfig} + * is {@link DeclarativeConfigProperties#empty()}. + * + * @param path the declarative configuration path that changed + * @param newConfig the updated configuration for the changed path + */ + void onChange(String path, DeclarativeConfigProperties newConfig); +} diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigChangeRegistration.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigChangeRegistration.java new file mode 100644 index 00000000000..6e499ba11ad --- /dev/null +++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigChangeRegistration.java @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.api.incubator.config; + +/** Registration handle returned by {@link ConfigProvider#addConfigChangeListener}. */ +@FunctionalInterface +public interface ConfigChangeRegistration { + + /** + * Unregister the listener associated with this registration. + * + *
Subsequent calls have no effect. + */ + void close(); +} 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 dcf6c7bd082..8617ce6f7ca 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 @@ -65,6 +65,28 @@ default DeclarativeConfigProperties getGeneralInstrumentationConfig() { return getInstrumentationConfig().get("general"); } + /** + * Registers a {@link ConfigChangeListener} for changes to a specific declarative configuration + * path. + * + *
Example paths include {@code .instrumentation/development.general.http} and {@code + * .instrumentation/development.java.methods}. + * + *
When a watched path changes, {@link ConfigChangeListener#onChange(String, + * DeclarativeConfigProperties)} is invoked with the changed path and updated configuration for + * that path. + * + *
The default implementation performs no registration and returns a no-op handle. + * + * @param path the declarative configuration path to watch + * @param listener the listener to notify when the watched path changes + * @return a {@link ConfigChangeRegistration} that can be closed to unregister the listener + */ + default ConfigChangeRegistration addConfigChangeListener( + String path, ConfigChangeListener listener) { + return () -> {}; + } + /** 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 b5fdca1cdf6..43aa3fd0ba0 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 @@ -6,7 +6,9 @@ package io.opentelemetry.api.incubator; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import io.opentelemetry.api.incubator.config.ConfigChangeRegistration; import io.opentelemetry.api.incubator.config.ConfigProvider; import org.junit.jupiter.api.Test; @@ -24,5 +26,9 @@ void instrumentationConfigFallback() { assertThat(configProvider.getInstrumentationConfig()).isNotNull(); assertThat(configProvider.getInstrumentationConfig("servlet")).isNotNull(); assertThat(configProvider.getGeneralInstrumentationConfig()).isNotNull(); + ConfigChangeRegistration listenerRegistration = + configProvider.addConfigChangeListener( + ".instrumentation/development.java.servlet", (path, newConfig) -> {}); + assertThatCode(listenerRegistration::close).doesNotThrowAnyException(); } }