-
Couldn't load subscription status.
- Fork 1k
Support experimental declarative configuration #12265
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
Changes from 3 commits
983515c
a1d69f4
ee9cf67
2fffe26
a2534ba
3e2e6f1
63256f7
e76bbac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,215 @@ | ||||
| /* | ||||
| * Copyright The OpenTelemetry Authors | ||||
| * SPDX-License-Identifier: Apache-2.0 | ||||
| */ | ||||
|
|
||||
| package io.opentelemetry.javaagent.extension; | ||||
|
|
||||
| import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; | ||||
| import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties; | ||||
| import java.time.Duration; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import java.util.function.BiFunction; | ||||
| import javax.annotation.Nullable; | ||||
|
|
||||
| /** | ||||
| * A {@link ConfigProperties} which resolves properties based on {@link StructuredConfigProperties}. | ||||
| * | ||||
| * <p>Only properties starting with "otel.instrumentation." are resolved. Others return null (or | ||||
| * default value if provided). | ||||
| * | ||||
| * <p>To resolve: | ||||
| * | ||||
| * <ul> | ||||
| * <li>"otel.instrumentation" refers to the ".instrumentation.java" node | ||||
| * <li>The portion of the property after "otel.instrumentation." is split into segments based on | ||||
| * ".". | ||||
| * <li>For each N-1 segment, we walk down the tree to find the relevant leaf {@link | ||||
| * StructuredConfigProperties}. | ||||
| * <li>We extract the property from the resolved {@link StructuredConfigProperties} using the last | ||||
| * segment as the property key. | ||||
| * </ul> | ||||
| * | ||||
| * <p>For example, given the following YAML, asking for {@code | ||||
| * ConfigProperties#getString("otel.instrumentation.common.string_key")} yields "value": | ||||
| * | ||||
| * <pre> | ||||
| * instrumentation: | ||||
| * java: | ||||
| * common: | ||||
| * string_key: value | ||||
| * </pre> | ||||
| */ | ||||
| final class StructuredConfigPropertiesBridge implements ConfigProperties { | ||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would make sense to instrumentation-api-incubator so that in can be used in extensions There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasn't sure where to include this. @open-telemetry/java-instrumentation-maintainers is this or There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. javaagent modules can't be used outside the agent - please correct me if I'm wrong @laurit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the current location seems good
@zeitlinger maybe what you really want is open-telemetry/opentelemetry-java#6549? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want to use the bridge in the starter at some point here: opentelemetry-java-instrumentation/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts Line 65 in 428aa28
But maybe that's a next step. |
||||
|
|
||||
| private static final StructuredConfigProperties EMPTY = new EmptyStructuredConfigProperties(); | ||||
|
|
||||
| private final StructuredConfigProperties javaInstrumentation; | ||||
jack-berg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
|
|
||||
| StructuredConfigPropertiesBridge(StructuredConfigProperties rootStructuredConfigProperties) { | ||||
| StructuredConfigProperties instrumentation = | ||||
| rootStructuredConfigProperties.getStructured("instrumentation"); | ||||
| if (instrumentation != null) { | ||||
| StructuredConfigProperties javaInstrumentation = instrumentation.getStructured("java"); | ||||
| this.javaInstrumentation = javaInstrumentation != null ? javaInstrumentation : EMPTY; | ||||
| } else { | ||||
| this.javaInstrumentation = EMPTY; | ||||
| } | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public String getString(String propertyName) { | ||||
| return getPropertyValue(propertyName, StructuredConfigProperties::getString); | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public Boolean getBoolean(String propertyName) { | ||||
| return getPropertyValue(propertyName, StructuredConfigProperties::getBoolean); | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public Integer getInt(String propertyName) { | ||||
| return getPropertyValue(propertyName, StructuredConfigProperties::getInt); | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public Long getLong(String propertyName) { | ||||
| return getPropertyValue(propertyName, StructuredConfigProperties::getLong); | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public Double getDouble(String propertyName) { | ||||
| return getPropertyValue(propertyName, StructuredConfigProperties::getDouble); | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public Duration getDuration(String propertyName) { | ||||
| Long millis = getPropertyValue(propertyName, StructuredConfigProperties::getLong); | ||||
| if (millis == null) { | ||||
| return null; | ||||
| } | ||||
| return Duration.ofMillis(millis); | ||||
| } | ||||
|
Comment on lines
+92
to
+100
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this intentionally scoping down and not handling durations with units like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. All durations in the declarative config schema are integer types assumed to be ms. There is no ability to specify the |
||||
|
|
||||
| @Override | ||||
| public List<String> getList(String propertyName) { | ||||
| List<String> propertyValue = | ||||
| getPropertyValue( | ||||
| propertyName, | ||||
| (properties, lastPart) -> properties.getScalarList(lastPart, String.class)); | ||||
| return propertyValue == null ? Collections.emptyList() : propertyValue; | ||||
| } | ||||
|
|
||||
| @Override | ||||
| public Map<String, String> getMap(String propertyName) { | ||||
| StructuredConfigProperties propertyValue = | ||||
| getPropertyValue(propertyName, StructuredConfigProperties::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, BiFunction<StructuredConfigProperties, String, T> extractor) { | ||||
| if (!property.startsWith("otel.instrumentation.")) { | ||||
jack-berg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
| return null; | ||||
| } | ||||
| String suffix = property.substring("otel.instrumentation.".length()); | ||||
| // Split the remainder of the property on ".", and walk to the N-1 entry | ||||
| String[] segments = suffix.split("\\."); | ||||
| if (segments.length == 0) { | ||||
| return null; | ||||
| } | ||||
| StructuredConfigProperties target = javaInstrumentation; | ||||
| if (segments.length > 1) { | ||||
| for (int i = 0; i < segments.length - 1; i++) { | ||||
| StructuredConfigProperties newTarget = target.getStructured(segments[i]); | ||||
| if (newTarget == null) { | ||||
| target = EMPTY; | ||||
| break; | ||||
| } | ||||
| target = newTarget; | ||||
| } | ||||
| } | ||||
| String lastPart = segments[segments.length - 1]; | ||||
| return extractor.apply(target, lastPart); | ||||
| } | ||||
|
|
||||
| private static class EmptyStructuredConfigProperties implements StructuredConfigProperties { | ||||
| @Nullable | ||||
| @Override | ||||
| public String getString(String s) { | ||||
| return null; | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public Boolean getBoolean(String s) { | ||||
| return null; | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public Integer getInt(String s) { | ||||
| return null; | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public Long getLong(String s) { | ||||
| return null; | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public Double getDouble(String s) { | ||||
| return null; | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public <T> List<T> getScalarList(String s, Class<T> aClass) { | ||||
| return null; | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public StructuredConfigProperties getStructured(String s) { | ||||
| return null; | ||||
| } | ||||
|
|
||||
| @Nullable | ||||
| @Override | ||||
| public List<StructuredConfigProperties> getStructuredList(String s) { | ||||
| return null; | ||||
| } | ||||
|
|
||||
| @Override | ||||
| public Set<String> getPropertyKeys() { | ||||
| return Collections.emptySet(); | ||||
| } | ||||
| } | ||||
| } | ||||
Uh oh!
There was an error while loading. Please reload this page.