Skip to content

declarative config: early init and property mapping #14184

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 78 commits into from
Aug 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
b2459f0
use _ instead of - in declarative config
zeitlinger Jul 4, 2025
ecae37d
map "common-enabled"
zeitlinger Jul 4, 2025
db2ca43
use yaml file
zeitlinger Jul 4, 2025
9e0b8bf
agent properties, part 1
zeitlinger Jul 4, 2025
55de38c
early init config
zeitlinger Jul 4, 2025
71bfd1a
early init config
zeitlinger Jul 4, 2025
4f8b4fc
don't pass model to create the SDK - we need to parse the file twice …
zeitlinger Jul 4, 2025
75deea8
map agent enabled
zeitlinger Jul 4, 2025
457d86a
map agent props
zeitlinger Jul 4, 2025
13c12ec
map agent props
zeitlinger Jul 4, 2025
c3d022f
fix
zeitlinger Jul 4, 2025
b1073cc
fix
zeitlinger Jul 4, 2025
6b47a3a
fix
zeitlinger Jul 4, 2025
8813861
fix
zeitlinger Jul 5, 2025
0e49ec3
map general props
zeitlinger Jul 5, 2025
99097c9
map agent props
zeitlinger Jul 5, 2025
eb5c6ac
map agent props
zeitlinger Jul 6, 2025
178f4b2
create sdk from previously read config model
zeitlinger Jul 6, 2025
4bc273d
create sdk from previously read config model
zeitlinger Jul 6, 2025
e713b98
map otel.javaagent.debug
zeitlinger Jul 6, 2025
56d4fa9
format
zeitlinger Jul 6, 2025
d137784
format
zeitlinger Jul 6, 2025
a0fbf8a
set test exporters
zeitlinger Jul 6, 2025
d947fa0
use extension classloader
zeitlinger Jul 6, 2025
3eea10d
format
zeitlinger Jul 7, 2025
dd70dd8
inline method
zeitlinger Jul 7, 2025
d89426c
set global config provider
zeitlinger Jul 7, 2025
5976575
add more tests
zeitlinger Jul 7, 2025
33903a9
cleanup
zeitlinger Jul 8, 2025
97677b4
buffer errors
zeitlinger Jul 8, 2025
b64859d
avoid reflection
zeitlinger Jul 8, 2025
fc04546
avoid reflection
zeitlinger Jul 8, 2025
751589a
format
zeitlinger Jul 8, 2025
1561407
buffer errors
zeitlinger Jul 8, 2025
bc7165f
revert to using system props for early init with declarative config t…
zeitlinger Jul 9, 2025
2794334
revert to using system props for early init with declarative config t…
zeitlinger Jul 9, 2025
948a3cd
revert to using system props for early init with declarative config t…
zeitlinger Jul 9, 2025
9491956
fix rebase
zeitlinger Jul 10, 2025
fe275b2
decide if declarative config file is loaded later - because distros m…
zeitlinger Jul 11, 2025
cf9cb1d
rename class
zeitlinger Jul 15, 2025
7c24dde
format
zeitlinger Jul 15, 2025
5245018
./gradlew spotlessApply
otelbot[bot] Jul 16, 2025
e1a5d28
format
zeitlinger Jul 16, 2025
35b5796
fix import
zeitlinger Jul 16, 2025
fa3d2af
format
zeitlinger Jul 16, 2025
2a28136
improve handling of general properties, signal if declarative config …
zeitlinger Jul 17, 2025
4b4d861
improve handling of general properties, signal if declarative config …
zeitlinger Jul 17, 2025
2e12d2b
improve handling of general properties, signal if declarative config …
zeitlinger Jul 17, 2025
392b7b5
remove unneeded rule
zeitlinger Jul 18, 2025
6fc47d7
use unified config bridge
zeitlinger Jul 18, 2025
2e0edb8
use unified config bridge
zeitlinger Jul 18, 2025
771fbe3
use unified config bridge
zeitlinger Jul 18, 2025
5fdaa07
pr feedback
zeitlinger Jul 22, 2025
af32418
fix rebase
zeitlinger Jul 22, 2025
6e27481
fix rebase
zeitlinger Jul 22, 2025
16fa7ef
use builder pattern
zeitlinger Jul 22, 2025
d6e0837
pr review
zeitlinger Jul 23, 2025
5cc52cf
pr review
zeitlinger Jul 24, 2025
215cc1f
rename builder
zeitlinger Jul 24, 2025
f677777
remove methods that are only needed by contrib
zeitlinger Jul 24, 2025
0625767
remove methods that are only needed by contrib
zeitlinger Jul 24, 2025
a738ec5
pr review
zeitlinger Jul 24, 2025
91d61c4
Revert "pr review"
zeitlinger Jul 24, 2025
cc96814
pr review
zeitlinger Jul 24, 2025
2524eee
pr review
zeitlinger Jul 24, 2025
60d8ea9
pr review
zeitlinger Aug 4, 2025
76a6453
pr review
zeitlinger Aug 4, 2025
a657fe3
pr review
zeitlinger Aug 4, 2025
8c24983
pr review
zeitlinger Aug 4, 2025
3ad6361
pr review
zeitlinger Aug 4, 2025
1214f5a
pr review
zeitlinger Aug 4, 2025
8ef63f4
pr review
zeitlinger Aug 11, 2025
9c4abde
pr review
zeitlinger Aug 11, 2025
2db5b76
typo was fixed
zeitlinger Aug 11, 2025
48980a4
pr feedback
zeitlinger Aug 12, 2025
fb4f3dc
add isDeclarative
zeitlinger Aug 12, 2025
413ec6d
pr feedback
zeitlinger Aug 13, 2025
c61393e
split common-enabled translation until sorted out
zeitlinger Aug 14, 2025
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 @@ -7,13 +7,17 @@

import static java.util.Collections.emptyMap;

import io.opentelemetry.api.incubator.config.ConfigProvider;
import io.opentelemetry.api.incubator.config.InstrumentationConfigUtil;
import io.opentelemetry.instrumentation.api.incubator.log.LoggingContextConstants;
import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceResolver;
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
Expand All @@ -39,16 +43,32 @@ public final class CommonConfig {
public CommonConfig(InstrumentationConfig config) {
peerServiceResolver =
PeerServiceResolver.create(
config.getMap("otel.instrumentation.common.peer-service-mapping", emptyMap()));
getFromConfigProviderOrFallback(
config,
InstrumentationConfigUtil::peerServiceMapping,
() ->
config.getMap("otel.instrumentation.common.peer-service-mapping", emptyMap())));

clientRequestHeaders =
config.getList("otel.instrumentation.http.client.capture-request-headers");
getFromConfigProviderOrFallback(
config,
InstrumentationConfigUtil::httpClientRequestCapturedHeaders,
() -> config.getList("otel.instrumentation.http.client.capture-request-headers"));
clientResponseHeaders =
config.getList("otel.instrumentation.http.client.capture-response-headers");
getFromConfigProviderOrFallback(
config,
InstrumentationConfigUtil::httpClientResponseCapturedHeaders,
() -> config.getList("otel.instrumentation.http.client.capture-response-headers"));
serverRequestHeaders =
config.getList("otel.instrumentation.http.server.capture-request-headers");
getFromConfigProviderOrFallback(
config,
InstrumentationConfigUtil::httpServerRequestCapturedHeaders,
() -> config.getList("otel.instrumentation.http.server.capture-request-headers"));
serverResponseHeaders =
config.getList("otel.instrumentation.http.server.capture-response-headers");
getFromConfigProviderOrFallback(
config,
InstrumentationConfigUtil::httpServerResponseCapturedHeaders,
() -> config.getList("otel.instrumentation.http.server.capture-response-headers"));
knownHttpRequestMethods =
new HashSet<>(
config.getList(
Expand Down Expand Up @@ -130,4 +150,15 @@ public String getSpanIdKey() {
public String getTraceFlagsKey() {
return loggingTraceFlagsKey;
}

private static <T> T getFromConfigProviderOrFallback(
InstrumentationConfig config,
Function<ConfigProvider, T> getFromConfigProvider,
Supplier<T> fallback) {
ConfigProvider configProvider = config.getConfigProvider();
if (configProvider != null) {
return getFromConfigProvider.apply(configProvider);
}
return fallback.get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import static java.util.Collections.emptyList;

import io.opentelemetry.api.incubator.config.ConfigProvider;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import java.time.Duration;
import java.util.List;
Expand Down Expand Up @@ -109,17 +110,30 @@ default List<String> getList(String name) {
*/
Map<String, String> getMap(String name, Map<String, String> defaultValue);

/** Returns {@code true} if declarative configuration is used in this configuration. */
boolean isDeclarative();

/**
* Returns a {@link DeclarativeConfigProperties} for the given instrumentation name, or {@code
* null} if no declarative configuration is available for that instrumentation.
* Returns a {@link DeclarativeConfigProperties} for the given node name, which is usually an
* instrumentation name
*
* <p>Call {@link #isDeclarative()} first to check if declarative configuration is used.
*
* <p>Declarative configuration is used to configure instrumentation properties in a declarative
* way, such as through YAML or JSON files.
*
* @param instrumentationName the name of the instrumentation
* @return the declarative configuration properties for the given instrumentation name, or {@code
* null} if not available
* @param node the name of the instrumentation (e.g. "log4j"), the vendor name (e.g. "google"), or
* "common" for common Java settings that don't apply to other languages.
* @return the declarative configuration properties for the given node name
* @throws IllegalStateException if {@link #isDeclarative()} returns {@code false}
*/
DeclarativeConfigProperties getDeclarativeConfig(String node);

/**
* Returns the {@link ConfigProvider} if declarative configuration is used.
*
* @return the {@link ConfigProvider} or {@code null} if no provider is available
*/
@Nullable
DeclarativeConfigProperties getDeclarativeConfig(String instrumentationName);
ConfigProvider getConfigProvider();
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
import io.opentelemetry.instrumentation.jmx.engine.MetricConfiguration;
import io.opentelemetry.instrumentation.jmx.yaml.RuleParser;
import io.opentelemetry.javaagent.extension.AgentListener;
import io.opentelemetry.javaagent.extension.internal.ConfigPropertiesUtil;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import java.io.InputStream;
import java.nio.file.Files;
Expand All @@ -29,7 +29,7 @@ public class JmxMetricInsightInstaller implements AgentListener {

@Override
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
ConfigProperties config = ConfigPropertiesUtil.resolveConfigProperties(autoConfiguredSdk);
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredSdk);

if (config.getBoolean("otel.jmx.enabled", true)) {
JmxMetricInsight service =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import static java.util.Collections.singletonMap;

import com.google.auto.service.AutoService;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig;
import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
Expand All @@ -34,10 +34,11 @@ public MethodInstrumentationModule() {
}

private static List<TypeInstrumentation> createInstrumentations() {
DeclarativeConfigProperties methods =
AgentInstrumentationConfig.get().getDeclarativeConfig("methods");
InstrumentationConfig config = AgentInstrumentationConfig.get();
List<TypeInstrumentation> list =
methods != null ? MethodsConfig.parseDeclarativeConfig(methods) : parseConfigProperties();
config.isDeclarative()
? MethodsConfig.parseDeclarativeConfig(config.getDeclarativeConfig("methods"))
: parseConfigProperties();
// ensure that there is at least one instrumentation so that muzzle reference collection could
// work
if (list.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.AgentListener;
import io.opentelemetry.javaagent.extension.internal.ConfigPropertiesUtil;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import java.lang.reflect.Method;

Expand All @@ -21,7 +21,7 @@ public class OshiMetricsInstaller implements AgentListener {

@Override
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
ConfigProperties config = ConfigPropertiesUtil.resolveConfigProperties(autoConfiguredSdk);
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredSdk);

boolean defaultEnabled = config.getBoolean("otel.instrumentation.common.default-enabled", true);
if (!config.getBoolean("otel.instrumentation.oshi.enabled", defaultEnabled)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder;
import io.opentelemetry.javaagent.extension.internal.ConfigPropertiesUtil;
import io.opentelemetry.javaagent.tooling.BeforeAgentListener;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import java.lang.instrument.Instrumentation;

Expand All @@ -19,8 +19,7 @@ public class JarAnalyzerInstaller implements BeforeAgentListener {

@Override
public void beforeAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
ConfigProperties config =
ConfigPropertiesUtil.resolveConfigProperties(autoConfiguredOpenTelemetrySdk);
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk);

boolean enabled =
config.getBoolean("otel.instrumentation.runtime-telemetry.package-emitter.enabled", false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties;

import io.opentelemetry.api.incubator.config.ConfigProvider;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
Expand Down Expand Up @@ -110,10 +111,21 @@ public Map<String, String> getMap(String name, Map<String, String> defaultValue)
}
}

@Override
public boolean isDeclarative() {
return false;
}

@Override
public DeclarativeConfigProperties getDeclarativeConfig(String node) {
throw new IllegalStateException(
"Declarative configuration is not supported in spring boot autoconfigure yet");
}

@Nullable
@Override
public DeclarativeConfigProperties getDeclarativeConfig(String instrumentationName) {
// create a spring boot bridge for DeclarativeConfigProperties
public ConfigProvider getConfigProvider() {
// declarative config support will be added in the future
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package io.opentelemetry.javaagent.bootstrap.internal;

import io.opentelemetry.api.incubator.config.ConfigProvider;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig;
import java.time.Duration;
Expand Down Expand Up @@ -60,9 +61,20 @@ public Map<String, String> getMap(String name, Map<String, String> defaultValue)
return defaultValue;
}

@Override
public boolean isDeclarative() {
return false;
}

@Override
public DeclarativeConfigProperties getDeclarativeConfig(String node) {
throw new IllegalStateException(
"Declarative configuration is not supported in the empty instrumentation config");
}

@Nullable
@Override
public DeclarativeConfigProperties getDeclarativeConfig(String instrumentationName) {
public ConfigProvider getConfigProvider() {
return null;
}
}

This file was deleted.

Loading
Loading