Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -99,6 +99,7 @@ dependencies {

testImplementation("io.opentelemetry:opentelemetry-sdk")
testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
testImplementation("io.opentelemetry:opentelemetry-api-incubator")
testImplementation(project(":instrumentation:resources:library"))
testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi")
testImplementation("io.opentelemetry:opentelemetry-extension-trace-propagators")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,25 @@ class EmbeddedConfigFile {
private EmbeddedConfigFile() {}

static OpenTelemetryConfigurationModel extractModel(ConfigurableEnvironment environment) {
Map<String, String> props = extractSpringProperties(environment);
return convertToOpenTelemetryConfigurationModel(props);
Map<String, Object> props = extractSpringProperties(environment);
Map<String, Object> nested = convertFlatPropsToNested(props);
return MAPPER.convertValue(nested, OpenTelemetryConfigurationModel.class);
}

private static Map<String, String> extractSpringProperties(ConfigurableEnvironment environment) {
private static Map<String, Object> extractSpringProperties(ConfigurableEnvironment environment) {
MutablePropertySources propertySources = environment.getPropertySources();

Map<String, String> props = new HashMap<>();
Map<String, Object> props = new HashMap<>();
for (PropertySource<?> propertySource : propertySources) {
if (propertySource instanceof EnumerablePropertySource<?>) {
for (String propertyName :
((EnumerablePropertySource<?>) propertySource).getPropertyNames()) {
if (propertyName.startsWith("otel.")) {
String property = environment.getProperty(propertyName);
Object property = propertySource.getProperty(propertyName);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This change preserves boolean values across the bridge

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.

Is this needed for this PR?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yeah. the reason it worked before is that all of the spring boot starter config access was done via ConfigProperties which is string based anyways

and I've updated some places in this PR to now access config via Declarative Config API (which ignores properties if they're not the requested type instead of converting them)

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.

spring was using type coercion before - because I thought it was necessary.
I'll play around with this PR a little more to get a better picture.

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.

I figured it out: the wrong config provider was used: trask#101

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

// Resolve ${} placeholders in String values while preserving types for others
if (property instanceof String) {
property = environment.resolvePlaceholders((String) property);
}
if (Objects.equals(property, "")) {
property = null; // spring returns empty string for yaml null
}
Expand Down Expand Up @@ -95,29 +100,18 @@ private static Map<String, String> extractSpringProperties(ConfigurableEnvironme
return props;
}

static OpenTelemetryConfigurationModel convertToOpenTelemetryConfigurationModel(
Map<String, String> flatProps) {
Map<String, Object> nested = convertFlatPropsToNested(flatProps);

return getObjectMapper().convertValue(nested, OpenTelemetryConfigurationModel.class);
}

static ObjectMapper getObjectMapper() {
return MAPPER;
}

/**
* Convert flat property map to nested structure. e.g. "otel.instrumentation.java.list[0]" = "one"
* and "otel.instrumentation.java.list[1]" = "two" becomes: {otel: {instrumentation: {java: {list:
* ["one", "two"]}}}}
*/
@SuppressWarnings("unchecked")
static Map<String, Object> convertFlatPropsToNested(Map<String, String> flatProps) {
static Map<String, Object> convertFlatPropsToNested(Map<String, Object> flatProps) {
Map<String, Object> result = new HashMap<>();

for (Map.Entry<String, String> entry : flatProps.entrySet()) {
for (Map.Entry<String, Object> entry : flatProps.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
Object value = entry.getValue();

// Split the key by dots
String[] parts = key.split("\\.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import static java.util.Objects.requireNonNull;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.incubator.ExtendedOpenTelemetry;
import io.opentelemetry.api.incubator.config.ConfigProvider;
import io.opentelemetry.api.trace.TracerProvider;
import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig;
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
import io.opentelemetry.instrumentation.config.bridge.ConfigPropertiesBackedConfigProvider;
import io.opentelemetry.instrumentation.config.bridge.DeclarativeConfigPropertiesBridgeBuilder;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigDisabled;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigEnabled;
Expand Down Expand Up @@ -125,9 +127,12 @@ public AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk(

@Bean
public OpenTelemetry openTelemetry(
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk,
ConfigProperties otelProperties) {
logStart();
return autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk();
OpenTelemetrySdk openTelemetry = autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk();
ConfigProvider configProvider = ConfigPropertiesBackedConfigProvider.create(otelProperties);
return new SpringOpenTelemetrySdk(openTelemetry, configProvider);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A test failed when I just implemented OpenTelemetry instead of OpenTelemetrySdk

  • OpenTelemetryAutoConfigurationTest.shouldInitializeSdkWhenNotDisabled

I guess it could be considered a breaking change if anyone is relying on it really being an instance of OpenTelemetrySdk, so went with OpenTelemetrySdk instead.

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.

the test was just meant to assert that it's not the noop instance

}

@Bean
Expand Down Expand Up @@ -171,9 +176,11 @@ public OpenTelemetry openTelemetry(
return sdk;
}

// TODO remove once ConfigProperties usage is removed from remaining
// spring boot starter instrumentations
@Bean
public ConfigProvider configProvider(OpenTelemetryConfigurationModel model) {
return SpringConfigProvider.create(model);
public ConfigProvider configProvider(OpenTelemetry openTelemetry) {
return ((ExtendedOpenTelemetry) openTelemetry).getConfigProvider();
}

/**
Expand All @@ -182,12 +189,16 @@ public ConfigProvider configProvider(OpenTelemetryConfigurationModel model) {
* <p>Not using spring boot properties directly, because declarative configuration does not
* integrate with spring boot properties.
*/
// TODO remove once ConfigProperties usage is removed from remaining
// spring boot starter instrumentations
@Bean
public ConfigProperties otelProperties(ConfigProvider configProvider) {
return new DeclarativeConfigPropertiesBridgeBuilder()
.buildFromInstrumentationConfig(configProvider.getInstrumentationConfig());
}

// TODO remove once ConfigProperties usage is removed from remaining
// spring boot starter instrumentations
@Bean
public InstrumentationConfig instrumentationConfig(
ConfigProperties properties, ConfigProvider configProvider) {
Expand Down

This file was deleted.

Loading
Loading