Skip to content
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>{@code path} is the changed declarative configuration path, for example {@code
* .instrumentation/development.general.http} or {@code
* .instrumentation/development.java.methods}.
*
* <p>{@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);
}
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>Subsequent calls have no effect.
*/
void close();
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,28 @@ default DeclarativeConfigProperties getGeneralInstrumentationConfig() {
return getInstrumentationConfig().get("general");
}

/**
* Registers a {@link ConfigChangeListener} for changes to a specific declarative configuration
* path.
*
* <p>Example paths include {@code .instrumentation/development.general.http} and {@code
* .instrumentation/development.java.methods}.
*
* <p>When a watched path changes, {@link ConfigChangeListener#onChange(String,
* DeclarativeConfigProperties)} is invoked with the changed path and updated configuration for
* that path.
*
* <p>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 () -> {};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for a default implementation. This is still experimental so we can add new methods without worrying about compatibility.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. But this default is a safe fallback, I added it for that reason rather than for compatibility. I'm not against removing and implementing it in the implementations, but it's a good default

}

/** Returns a no-op {@link ConfigProvider}. */
static ConfigProvider noop() {
return DeclarativeConfigProperties::empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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();
}
}
Loading