Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@

package io.opentelemetry.instrumentation.config.bridge;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.api.incubator.config.ConfigProvider;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import java.util.HashMap;
import java.util.Map;

/**
* A {@link ConfigProvider} implementation backed by {@link ConfigProperties}.
Expand All @@ -20,13 +23,33 @@ public final class ConfigPropertiesBackedConfigProvider implements ConfigProvide
private final DeclarativeConfigProperties instrumentationConfig;

public static ConfigProvider create(ConfigProperties configProperties) {
return new ConfigPropertiesBackedConfigProvider(configProperties);
return new ConfigPropertiesBackedConfigProvider(
ConfigPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(
configProperties));
}

private ConfigPropertiesBackedConfigProvider(ConfigProperties configProperties) {
this.instrumentationConfig =
ConfigPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(
configProperties);
public static Builder builder() {
return new Builder();
}

private ConfigPropertiesBackedConfigProvider(DeclarativeConfigProperties instrumentationConfig) {
this.instrumentationConfig = instrumentationConfig;
}

public static final class Builder {
private final Map<String, String> mappings = new HashMap<>();

@CanIgnoreReturnValue
public Builder addMapping(String declarativeProperty, String configProperty) {
mappings.put(declarativeProperty, configProperty);
return this;
}

public ConfigProvider build(ConfigProperties configProperties) {
return new ConfigPropertiesBackedConfigProvider(
ConfigPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(
configProperties, mappings));
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package io.opentelemetry.instrumentation.config.bridge;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;

import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
Expand Down Expand Up @@ -97,16 +98,26 @@ public final class ConfigPropertiesBackedDeclarativeConfigProperties

private final ConfigProperties configProperties;
private final List<String> path;
private final Map<String, String> mappings;

public static DeclarativeConfigProperties createInstrumentationConfig(
ConfigProperties configProperties) {
return new ConfigPropertiesBackedDeclarativeConfigProperties(configProperties, emptyList());
return createInstrumentationConfig(configProperties, emptyMap());
}

public static DeclarativeConfigProperties createInstrumentationConfig(
Comment thread
aviralgarg05 marked this conversation as resolved.
ConfigProperties configProperties, Map<String, String> mappings) {
Map<String, String> mergedMappings = new HashMap<>(SPECIAL_MAPPINGS);
mergedMappings.putAll(mappings);
return new ConfigPropertiesBackedDeclarativeConfigProperties(
configProperties, emptyList(), mergedMappings);
}

private ConfigPropertiesBackedDeclarativeConfigProperties(
ConfigProperties configProperties, List<String> path) {
ConfigProperties configProperties, List<String> path, Map<String, String> mappings) {
this.configProperties = configProperties;
this.path = path;
this.mappings = mappings;
}

@Nullable
Expand Down Expand Up @@ -165,7 +176,8 @@ public Double getDouble(String name) {
public DeclarativeConfigProperties getStructured(String name) {
List<String> newPath = new ArrayList<>(path);
newPath.add(name);
return new ConfigPropertiesBackedDeclarativeConfigProperties(configProperties, newPath);
return new ConfigPropertiesBackedDeclarativeConfigProperties(
configProperties, newPath, mappings);
}

@Nullable
Expand Down Expand Up @@ -211,7 +223,7 @@ private String resolvePropertyKey(String name) {
String fullPath = pathWithName(name);

// Check explicit property mappings first
String mappedKey = SPECIAL_MAPPINGS.get(fullPath);
String mappedKey = mappings.get(fullPath);
if (mappedKey != null) {
return mappedKey;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.config.bridge;

import static org.assertj.core.api.Assertions.assertThat;

import io.opentelemetry.api.incubator.config.ConfigProvider;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;

class ConfigPropertiesBackedConfigProviderTest {
@Test
void testBuilderWithMappings() {
Map<String, String> properties = new HashMap<>();
properties.put("my.custom.property", "custom-value");

// ConfigProperties has "my.custom.property"
// We want to map declarative "my.declarative.prop" to "my.custom.property"

ConfigProvider provider =
ConfigPropertiesBackedConfigProvider.builder()
.addMapping("my.declarative.prop", "my.custom.property")
.build(DefaultConfigProperties.createFromMap(properties));

DeclarativeConfigProperties config = provider.getInstrumentationConfig();

// DeclarativeConfigProperties structure lookup
// pathWithName("my.declarative.prop") should map to "my.custom.property"
// However, structure is hierarchical.
// getStructured("my").getStructured("declarative").getString("prop") ->
// "my.declarative.prop"

assertThat(config.getStructured("my").getStructured("declarative").getString("prop"))
.isEqualTo("custom-value");
}

@Test
void testCreateUsesDefaults() {
// Verify that create() still supports the default mappings (e.g.
// otel.instrumentation...)
// e.g. "java.common.http.known_methods" ->
// "otel.instrumentation.http.known-methods"

Map<String, String> properties = new HashMap<>();
properties.put("otel.instrumentation.http.known-methods", "GET,POST");

ConfigProvider provider =
ConfigPropertiesBackedConfigProvider.create(
DefaultConfigProperties.createFromMap(properties));

DeclarativeConfigProperties config = provider.getInstrumentationConfig();

assertThat(
config
.getStructured("java")
.getStructured("common")
.getStructured("http")
.getString("known_methods"))
.isEqualTo("GET,POST");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,28 @@ void testGeneralHttpListMapping() {
.containsExactly("header1", "header2");
}

@Test
void testCustomMappingsIncludeSpecialMappings() {
Map<String, String> properties = new HashMap<>();
properties.put("otel.custom.enabled", "true");
properties.put("otel.instrumentation.http.client.capture-request-headers", "header1,header2");
Map<String, String> customMappings = new HashMap<>();
customMappings.put("java.custom.enabled", "otel.custom.enabled");

DeclarativeConfigProperties config =
ConfigPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(
DefaultConfigProperties.createFromMap(properties), customMappings);

assertThat(config.getStructured("java").getStructured("custom").getBoolean("enabled")).isTrue();
assertThat(
config
.getStructured("general")
.getStructured("http")
.getStructured("client")
.getScalarList("request_captured_headers", String.class))
.containsExactly("header1", "header2");
}

@Test
void testJavaCommonServicePeerMapping() {
DeclarativeConfigProperties config =
Expand Down
Loading