Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,32 @@ private static AutoConfiguredOpenTelemetrySdk getOpenTelemetrySdk(
Class<?> declarativeConfiguration =
Class.forName(
"io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration");

Class<?> contextClass =
Class.forName(
"io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigContext");
Method createContext = contextClass.getDeclaredMethod("create", ComponentLoader.class);
createContext.setAccessible(true);
Object context = createContext.invoke(null, componentLoader);

Method create =
declarativeConfiguration.getMethod(
"create", openTelemetryConfiguration, ComponentLoader.class);
declarativeConfiguration.getDeclaredMethod(
"create", openTelemetryConfiguration, contextClass);
create.setAccessible(true);
OpenTelemetrySdk sdk = (OpenTelemetrySdk) create.invoke(null, model, context);

OpenTelemetrySdk sdk = (OpenTelemetrySdk) create.invoke(null, model, componentLoader);
Class<?> sdkConfigProvider =
Class<?> providerClass =
Class.forName("io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider");
Method createFileConfigProvider =
sdkConfigProvider.getMethod("create", openTelemetryConfiguration, ComponentLoader.class);
ConfigProvider configProvider =
(ConfigProvider) createFileConfigProvider.invoke(null, model, componentLoader);
// Note: can't access file configuration resource without reflection so setting a dummy
// resource
return AutoConfiguredOpenTelemetrySdk.create(sdk, Resource.getDefault(), null, configProvider);
Object provider =
providerClass
.getDeclaredMethod("create", openTelemetryConfiguration, ComponentLoader.class)
.invoke(null, model, componentLoader);

Method getResource = contextClass.getDeclaredMethod("getResource");
getResource.setAccessible(true);
Resource resource = (Resource) getResource.invoke(context);

return AutoConfiguredOpenTelemetrySdk.create(sdk, resource, null, provider);
}

// Visible for testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
Expand Down Expand Up @@ -127,13 +126,13 @@ void configFile_Valid() {
cleanup.addCloseable(autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk());

OpenTelemetrySdk openTelemetrySdk = autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk();
Resource resource = Resource.getDefault().toBuilder().put("service.name", "test").build();
ExtendedOpenTelemetrySdk expectedSdk =
ExtendedOpenTelemetrySdk.create(
OpenTelemetrySdk.builder()
.setTracerProvider(
SdkTracerProvider.builder()
.setResource(
Resource.getDefault().toBuilder().put("service.name", "test").build())
.setResource(resource)
.addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create()))
.build())
.build(),
Expand All @@ -142,7 +141,7 @@ void configFile_Valid() {
assertThat(openTelemetrySdk.toString()).hasToString(expectedSdk.toString());
// AutoConfiguredOpenTelemetrySdk#getResource() is set to a dummy value when configuring from
// file
assertThat(autoConfiguredOpenTelemetrySdk.getResource()).isEqualTo(Resource.getDefault());
assertThat(autoConfiguredOpenTelemetrySdk.getResource()).isEqualTo(resource);
verify(builder, times(1)).shutdownHook(autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk());
assertThat(Runtime.getRuntime().removeShutdownHook(thread)).isTrue();
logCapturer.assertContains("Autoconfiguring from configuration file: " + configFilePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import io.opentelemetry.api.incubator.config.DeclarativeConfigException;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
import io.opentelemetry.sdk.resources.Resource;
import java.io.Closeable;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -24,11 +26,17 @@ class DeclarativeConfigContext {
private final SpiHelper spiHelper;
private final List<Closeable> closeables = new ArrayList<>();
@Nullable private volatile MeterProvider meterProvider;
private Resource resource = Resource.empty();

// Visible for testing
DeclarativeConfigContext(SpiHelper spiHelper) {
this.spiHelper = spiHelper;
}

static DeclarativeConfigContext create(ComponentLoader componentLoader) {
return new DeclarativeConfigContext(SpiHelper.create(componentLoader));
}

/**
* Add the {@code closeable} to the list of closeables to clean up if configuration fails
* exceptionally, and return it.
Expand All @@ -51,6 +59,19 @@ public void setMeterProvider(MeterProvider meterProvider) {
this.meterProvider = meterProvider;
}

Resource getResource() {
// called via reflection from io.opentelemetry.sdk.autoconfigure.IncubatingUtil
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you think this comment may be useful?
On one hand it explains why no one should remove this method, but on the other hand it will be easy to forget to update/remove it when declarative config stuff goes out of incubator.
Maybe instead of this comment it would be better to add a unit test in IncubatingUtilTest that verifies that getResource is actually called.

Copy link
Member Author

Choose a reason for hiding this comment

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

the test is already there - but I get how it can get out of sync

return resource;
Copy link
Member

@jack-berg jack-berg Sep 26, 2025

Choose a reason for hiding this comment

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

Maybe throw an exception if getResource is called before setResource to make it easier to track down ordering issues.

Copy link
Member Author

Choose a reason for hiding this comment

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

good idea - added

}

void setResource(Resource resource) {
this.resource = resource;
}

SpiHelper getSpiHelper() {
return spiHelper;
}

/**
* Find a registered {@link ComponentProvider} with {@link ComponentProvider#getType()} matching
* {@code type}, {@link ComponentProvider#getName()} matching {@code name}, and call {@link
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,14 @@ public static ExtendedOpenTelemetrySdk create(
*/
public static ExtendedOpenTelemetrySdk create(
OpenTelemetryConfigurationModel configurationModel, ComponentLoader componentLoader) {
SpiHelper spiHelper = SpiHelper.create(componentLoader);
return create(configurationModel, DeclarativeConfigContext.create(componentLoader));
}

private static ExtendedOpenTelemetrySdk create(
OpenTelemetryConfigurationModel configurationModel, DeclarativeConfigContext context) {
DeclarativeConfigurationBuilder builder = new DeclarativeConfigurationBuilder();

SpiHelper spiHelper = context.getSpiHelper();
for (DeclarativeConfigurationCustomizerProvider provider :
spiHelper.loadOrdered(DeclarativeConfigurationCustomizerProvider.class)) {
provider.customize(builder);
Expand All @@ -127,7 +131,7 @@ public static ExtendedOpenTelemetrySdk create(
ExtendedOpenTelemetrySdk sdk =
createAndMaybeCleanup(
OpenTelemetryConfigurationFactory.getInstance(),
spiHelper,
context,
builder.customizeModel(configurationModel));
callAutoConfigureListeners(spiHelper, sdk);
return sdk;
Expand Down Expand Up @@ -213,7 +217,7 @@ public static Sampler createSampler(DeclarativeConfigProperties genericSamplerMo
DeclarativeConfigProperties.toMap(yamlDeclarativeConfigProperties), SamplerModel.class);
return createAndMaybeCleanup(
SamplerFactory.getInstance(),
SpiHelper.create(yamlDeclarativeConfigProperties.getComponentLoader()),
DeclarativeConfigContext.create(yamlDeclarativeConfigProperties.getComponentLoader()),
samplerModel);
}

Expand All @@ -226,8 +230,8 @@ private static YamlDeclarativeConfigProperties requireYamlDeclarativeConfigPrope
return (YamlDeclarativeConfigProperties) declarativeConfigProperties;
}

static <M, R> R createAndMaybeCleanup(Factory<M, R> factory, SpiHelper spiHelper, M model) {
DeclarativeConfigContext context = new DeclarativeConfigContext(spiHelper);
static <M, R> R createAndMaybeCleanup(
Factory<M, R> factory, DeclarativeConfigContext context, M model) {
try {
return factory.create(model, context);
} catch (RuntimeException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public ExtendedOpenTelemetrySdk create(
if (model.getResource() != null) {
resource = ResourceFactory.getInstance().create(model.getResource(), context);
}
context.setResource(resource);

if (model.getMeterProvider() != null) {
SdkMeterProvider meterProvider =
Expand Down
Loading