Skip to content
Draft
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 @@ -13,7 +13,7 @@ public static String propertyYamlPath(String propertyName) {
}

static String yamlPath(String property) {
String[] segments = DeclarativeConfigPropertiesBridge.getSegments(property);
String[] segments = DeclarativeConfigPropertiesApiBridge.getSegments(property);
if (segments.length == 0) {
throw new IllegalArgumentException("Invalid property: " + property);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.config.bridge;

import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty;

import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import javax.annotation.Nullable;

public class DeclarativeConfigPropertiesApiBridge {
private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation.";
protected final DeclarativeConfigProperties baseNode;
// lookup order matters - we choose the first match
protected final Map<String, String> mappings;
protected final Map<String, Object> overrideValues;

public DeclarativeConfigPropertiesApiBridge(
DeclarativeConfigProperties baseNode,
Map<String, String> mappings,
Map<String, Object> overrideValues) {
this.baseNode = Objects.requireNonNull(baseNode);
this.mappings = mappings;
this.overrideValues = overrideValues;
}

@Nullable
public String getString(String propertyName) {
return getPropertyValue(propertyName, String.class, DeclarativeConfigProperties::getString);
}

@Nullable
public Boolean getBoolean(String propertyName) {
return getPropertyValue(propertyName, Boolean.class, DeclarativeConfigProperties::getBoolean);
}

@Nullable
public Integer getInt(String propertyName) {
return getPropertyValue(propertyName, Integer.class, DeclarativeConfigProperties::getInt);
}

@Nullable
public Long getLong(String propertyName) {
return getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong);
}

@Nullable
public Double getDouble(String propertyName) {
return getPropertyValue(propertyName, Double.class, DeclarativeConfigProperties::getDouble);
}

@Nullable
public Duration getDuration(String propertyName) {
Long millis = getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong);
if (millis == null) {
return null;
}
return Duration.ofMillis(millis);
}

@SuppressWarnings("unchecked")
public List<String> getList(String propertyName) {
List<String> propertyValue =
getPropertyValue(
propertyName,
List.class,
(properties, lastPart) -> properties.getScalarList(lastPart, String.class));
return propertyValue == null ? Collections.emptyList() : propertyValue;
}

@SuppressWarnings("unchecked")
public Map<String, String> getMap(String propertyName) {
DeclarativeConfigProperties propertyValue =
getPropertyValue(
propertyName,
DeclarativeConfigProperties.class,
DeclarativeConfigProperties::getStructured);
if (propertyValue == null) {
return Collections.emptyMap();
}
Map<String, String> result = new HashMap<>();
propertyValue
.getPropertyKeys()
.forEach(
key -> {
String value = propertyValue.getString(key);
if (value == null) {
return;
}
result.put(key, value);
});
return Collections.unmodifiableMap(result);
}

@Nullable
private <T> T getPropertyValue(
String property,
Class<T> clazz,
BiFunction<DeclarativeConfigProperties, String, T> extractor) {
T override = clazz.cast(overrideValues.get(property));
if (override != null) {
return override;
}

String[] segments = getSegments(translateProperty(property));
if (segments.length == 0) {
return null;
}

// Extract the value by walking to the N-1 entry
DeclarativeConfigProperties target = baseNode;
if (segments.length > 1) {
for (int i = 0; i < segments.length - 1; i++) {
target = target.getStructured(segments[i], empty());
}
}
String lastPart = segments[segments.length - 1];

return extractor.apply(target, lastPart);
}

static String[] getSegments(String property) {
if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) {
property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length());
}
// Split the remainder of the property on "."
return property.replace('-', '_').split("\\.");
}

private String translateProperty(String property) {
for (Map.Entry<String, String> entry : mappings.entrySet()) {
if (property.startsWith(entry.getKey())) {
return entry.getValue() + property.substring(entry.getKey().length());
}
}
return property;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,9 @@

package io.opentelemetry.instrumentation.config.bridge;

import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty;

import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import javax.annotation.Nullable;

/**
* A {@link ConfigProperties} which resolves properties based on {@link
Expand Down Expand Up @@ -47,142 +38,13 @@
* string_key: value
* </pre>
*/
final class DeclarativeConfigPropertiesBridge implements ConfigProperties {

private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation.";

private final DeclarativeConfigProperties baseNode;

// lookup order matters - we choose the first match
private final Map<String, String> mappings;
private final Map<String, Object> overrideValues;
final class DeclarativeConfigPropertiesBridge extends DeclarativeConfigPropertiesApiBridge
implements ConfigProperties {

DeclarativeConfigPropertiesBridge(
DeclarativeConfigProperties baseNode,
Map<String, String> mappings,
Map<String, Object> overrideValues) {
this.baseNode = Objects.requireNonNull(baseNode);
this.mappings = mappings;
this.overrideValues = overrideValues;
}

@Nullable
@Override
public String getString(String propertyName) {
return getPropertyValue(propertyName, String.class, DeclarativeConfigProperties::getString);
}

@Nullable
@Override
public Boolean getBoolean(String propertyName) {
return getPropertyValue(propertyName, Boolean.class, DeclarativeConfigProperties::getBoolean);
}

@Nullable
@Override
public Integer getInt(String propertyName) {
return getPropertyValue(propertyName, Integer.class, DeclarativeConfigProperties::getInt);
}

@Nullable
@Override
public Long getLong(String propertyName) {
return getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong);
}

@Nullable
@Override
public Double getDouble(String propertyName) {
return getPropertyValue(propertyName, Double.class, DeclarativeConfigProperties::getDouble);
}

@Nullable
@Override
public Duration getDuration(String propertyName) {
Long millis = getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong);
if (millis == null) {
return null;
}
return Duration.ofMillis(millis);
}

@SuppressWarnings("unchecked")
@Override
public List<String> getList(String propertyName) {
List<String> propertyValue =
getPropertyValue(
propertyName,
List.class,
(properties, lastPart) -> properties.getScalarList(lastPart, String.class));
return propertyValue == null ? Collections.emptyList() : propertyValue;
}

@SuppressWarnings("unchecked")
@Override
public Map<String, String> getMap(String propertyName) {
DeclarativeConfigProperties propertyValue =
getPropertyValue(
propertyName,
DeclarativeConfigProperties.class,
DeclarativeConfigProperties::getStructured);
if (propertyValue == null) {
return Collections.emptyMap();
}
Map<String, String> result = new HashMap<>();
propertyValue
.getPropertyKeys()
.forEach(
key -> {
String value = propertyValue.getString(key);
if (value == null) {
return;
}
result.put(key, value);
});
return Collections.unmodifiableMap(result);
}

@Nullable
private <T> T getPropertyValue(
String property,
Class<T> clazz,
BiFunction<DeclarativeConfigProperties, String, T> extractor) {
T override = clazz.cast(overrideValues.get(property));
if (override != null) {
return override;
}

String[] segments = getSegments(translateProperty(property));
if (segments.length == 0) {
return null;
}

// Extract the value by walking to the N-1 entry
DeclarativeConfigProperties target = baseNode;
if (segments.length > 1) {
for (int i = 0; i < segments.length - 1; i++) {
target = target.getStructured(segments[i], empty());
}
}
String lastPart = segments[segments.length - 1];

return extractor.apply(target, lastPart);
}

static String[] getSegments(String property) {
if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) {
property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length());
}
// Split the remainder of the property on "."
return property.replace('-', '_').split("\\.");
}

private String translateProperty(String property) {
for (Map.Entry<String, String> entry : mappings.entrySet()) {
if (property.startsWith(entry.getKey())) {
return entry.getValue() + property.substring(entry.getKey().length());
}
}
return property;
super(baseNode, mappings, overrideValues);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ public ConfigProperties build(@Nullable DeclarativeConfigProperties node) {
node == null ? empty() : node, mappings, overrideValues);
}

public DeclarativeConfigPropertiesApiBridge buildApiBridge(
@Nullable DeclarativeConfigProperties node) {
return new DeclarativeConfigPropertiesApiBridge(
node == null ? empty() : node, mappings, overrideValues);
}

/**
* Build {@link ConfigProperties} from the {@link DeclarativeConfigProperties} provided by the
* instrumentation configuration.
Expand All @@ -105,4 +111,10 @@ public ConfigProperties buildFromInstrumentationConfig(
return build(
instrumentationConfig == null ? null : instrumentationConfig.getStructured("java"));
}

public DeclarativeConfigPropertiesApiBridge buildApiBridgeFromInstrumentationConfig(
@Nullable DeclarativeConfigProperties instrumentationConfig) {
return buildApiBridge(
instrumentationConfig == null ? null : instrumentationConfig.getStructured("java"));
}
}
3 changes: 3 additions & 0 deletions instrumentation-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ dependencies {
api("io.opentelemetry:opentelemetry-api")
implementation("io.opentelemetry:opentelemetry-api-incubator")
implementation("io.opentelemetry.semconv:opentelemetry-semconv")
implementation(project(":declarative-config-bridge")) {
exclude(group = "io.opentelemetry", module = "opentelemetry-sdk-extension-autoconfigure-spi")
}

compileOnly("com.google.auto.value:auto-value-annotations")
annotationProcessor("com.google.auto.value:auto-value")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.context.propagation.TextMapSetter;
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
import io.opentelemetry.instrumentation.api.internal.ApiConfigProperties;
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
import io.opentelemetry.instrumentation.api.internal.Experimental;
import io.opentelemetry.instrumentation.api.internal.InstrumenterBuilderAccess;
Expand Down Expand Up @@ -49,11 +49,6 @@ public final class InstrumenterBuilder<REQUEST, RESPONSE> {

private static final Logger logger = Logger.getLogger(InstrumenterBuilder.class.getName());

private static final SpanSuppressionStrategy spanSuppressionStrategy =
SpanSuppressionStrategy.fromConfig(
ConfigPropertiesUtil.getString(
"otel.instrumentation.experimental.span-suppression-strategy"));

final OpenTelemetry openTelemetry;
final String instrumentationName;
SpanNameExtractor<? super REQUEST> spanNameExtractor;
Expand Down Expand Up @@ -374,7 +369,10 @@ private String getSchemaUrl() {

SpanSuppressor buildSpanSuppressor() {
return new SpanSuppressors.ByContextKey(
spanSuppressionStrategy.create(getSpanKeysFromAttributesExtractors()));
SpanSuppressionStrategy.fromConfig(
new ApiConfigProperties(openTelemetry)
.getString("otel.instrumentation.experimental.span-suppression-strategy"))
.create(getSpanKeysFromAttributesExtractors()));
}

private Set<SpanKey> getSpanKeysFromAttributesExtractors() {
Expand Down
Loading
Loading