Skip to content

add config model customizer #7118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 21, 2025
Merged
Show file tree
Hide file tree
Changes from 7 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 @@ -108,10 +108,19 @@ public static OpenTelemetrySdk create(OpenTelemetryConfigurationModel configurat
*/
public static OpenTelemetrySdk create(
OpenTelemetryConfigurationModel configurationModel, ComponentLoader componentLoader) {
SpiHelper spiHelper = SpiHelper.create(componentLoader);

DeclarativeConfigurationBuilder builder = new DeclarativeConfigurationBuilder();

for (DeclarativeConfigurationCustomizerProvider provider :
spiHelper.loadOrdered(DeclarativeConfigurationCustomizerProvider.class)) {
provider.customize(builder);
}

return createAndMaybeCleanup(
OpenTelemetryConfigurationFactory.getInstance(),
SpiHelper.create(componentLoader),
configurationModel);
spiHelper,
builder.customizeModel(configurationModel));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.extension.incubator.fileconfig;

import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
import java.util.function.Function;

/** Builder for the declarative configuration. */
public class DeclarativeConfigurationBuilder implements DeclarativeConfigurationCustomizer {
private Function<OpenTelemetryConfigurationModel, OpenTelemetryConfigurationModel>
modelCustomizer = Function.identity();

@Override
public void addModelCustomizer(
Function<OpenTelemetryConfigurationModel, OpenTelemetryConfigurationModel> customizer) {
modelCustomizer = mergeCustomizer(modelCustomizer, customizer);
}

private static <I, O1, O2> Function<I, O2> mergeCustomizer(
Function<? super I, ? extends O1> first, Function<? super O1, ? extends O2> second) {
return (I configured) -> {
O1 firstResult = first.apply(configured);
return second.apply(firstResult);
Copy link
Member

Choose a reason for hiding this comment

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

In the future, we might consider adding opt-in logging to print the out change in the model after each stage of customization, but I'm happy to come back to that type of thing later. This is a good start!

Copy link
Member Author

Choose a reason for hiding this comment

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

let's leave that as a next step then

};
}

/** Customize the configuration model. */
public OpenTelemetryConfigurationModel customizeModel(
OpenTelemetryConfigurationModel configurationModel) {
return modelCustomizer.apply(configurationModel);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.extension.incubator.fileconfig;

import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
import java.util.function.Function;

/** A service provider interface (SPI) for customizing declarative configuration. */
public interface DeclarativeConfigurationCustomizer {
/**
* Method invoked when configuring the SDK to allow further customization of the declarative
* configuration.
*
* @param customizer the customizer to add
*/
void addModelCustomizer(
Function<OpenTelemetryConfigurationModel, OpenTelemetryConfigurationModel> customizer);
Copy link
Member

Choose a reason for hiding this comment

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

Just realizing that this is going to be a problematic contract from a packaging standpoint..

  • Currently, the SPI lives in opentelemetry-sdk-extension-incubator
  • In the future, we'll want to move it to opentelemetry-sdk-extension-autoconfigure-spi with the rest of the SPIs
  • That leaves a thorny question for where OpenTelemetryConfigurationModel and the rest of the data model lives. First guess would be opentelemetry-sdk-extension-autoconfigure, but that creates a dependency cycle. They could live in opentelemetry-sdk-extension-autoconfigure-spi, or opentelemetry-sdk, or opentelemetry-sdk-common, or some new opentelemetry-sdk-config package.

Idk, let's cross that bridge when we get there.

}
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.sdk.extension.incubator.fileconfig;

import io.opentelemetry.sdk.autoconfigure.spi.Ordered;

/** A service provider interface (SPI) for customizing declarative configuration. */
public interface DeclarativeConfigurationCustomizerProvider extends Ordered {
/**
* Method invoked when configuring the SDK to allow further customization of the declarative
*
* @param customizer the customizer to add
*/
void customize(DeclarativeConfigurationCustomizer customizer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
import io.github.netmikey.logunit.api.LogCapturer;
import io.opentelemetry.api.incubator.config.DeclarativeConfigException;
import io.opentelemetry.internal.testing.CleanupExtension;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
Expand All @@ -22,6 +27,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.cert.CertificateEncodingException;
import java.util.Collections;
import java.util.Objects;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand Down Expand Up @@ -61,7 +67,7 @@ void parseAndCreate_Examples(@TempDir Path tempDir)
tempDir, "clientCertificate.cert", clientTls.certificate().getEncoded());

File examplesDir = new File(System.getenv("CONFIG_EXAMPLE_DIR"));
assertThat(examplesDir.isDirectory()).isTrue();
assertThat(examplesDir).isDirectory();

for (File example : Objects.requireNonNull(examplesDir.listFiles())) {
// Skip anchors.yaml because support for merge (i.e. "<<: *anchor") was explicitly removed in
Expand Down Expand Up @@ -151,4 +157,32 @@ void parseAndCreate_EmptyComponentProviderConfig() {
new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))))
.doesNotThrowAnyException();
}

@Test
void create_ModelCustomizer() {
OpenTelemetryConfigurationModel model = new OpenTelemetryConfigurationModel();
model.withFileFormat("0.3");
model.withTracerProvider(
new TracerProviderModel()
.withProcessors(
Collections.singletonList(
new SpanProcessorModel().withAdditionalProperty("test", null))));
OpenTelemetrySdk sdk =
DeclarativeConfiguration.create(
model,
// customizer is TestDeclarativeConfigurationCustomizerProvider
SpiHelper.serviceComponentLoader(
DeclarativeConfigurationCreateTest.class.getClassLoader()));
assertThat(sdk.toString())
.contains(
"resource=Resource{schemaUrl=null, attributes={"
+ "color=\"blue\", "
+ "foo=\"bar\", "
+ "order=\"second\", "
+ "service.name=\"unknown_service:java\", "
+ "shape=\"square\", "
+ "telemetry.sdk.language=\"java\", "
+ "telemetry.sdk.name=\"opentelemetry\", "
+ "telemetry.sdk.version=\"");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.opentelemetry.sdk.extension.incubator.fileconfig;

import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AttributeNameValueModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ResourceModel;

import java.util.ArrayList;
import java.util.List;

public class TestDeclarativeConfigurationCustomizerProvider
implements DeclarativeConfigurationCustomizerProvider {
@Override
public void customize(DeclarativeConfigurationCustomizer customizer) {
customizer.addModelCustomizer(
model -> {
ResourceModel resource = model.getResource();
if (resource == null) {
resource = new ResourceModel();
model.withResource(resource);
}
List<AttributeNameValueModel> attributes = resource.getAttributes();
if (attributes == null) {
attributes = new ArrayList<>();
resource.withAttributes(attributes);
}
attributes.add(
new AttributeNameValueModel()
.withName("foo")
.withType(AttributeNameValueModel.Type.STRING)
.withValue("bar"));
attributes.add(
new AttributeNameValueModel()
.withName("color")
.withType(AttributeNameValueModel.Type.STRING)
.withValue("blue"));
return model;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.opentelemetry.sdk.extension.incubator.fileconfig.TestDeclarativeConfigurationCustomizerProvider
Loading