From d847267d23a5f9c64313a86425f875612baa3340 Mon Sep 17 00:00:00 2001 From: Abhilash Garapati Date: Fri, 12 Dec 2025 01:09:53 +0530 Subject: [PATCH 01/40] Apply spotless formatting and finalize span-suppression-strategy rename --- .../api/instrumenter/InstrumenterBuilder.java | 23 ++++++++++++++++--- .../camel-2.20/javaagent/build.gradle.kts | 2 +- .../javaagent/tooling/AgentInstaller.java | 3 ++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java index 422d357349a3..4edc0f616db4 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java @@ -49,10 +49,27 @@ public final class InstrumenterBuilder { private static final Logger logger = Logger.getLogger(InstrumenterBuilder.class.getName()); - private static final SpanSuppressionStrategy spanSuppressionStrategy = - SpanSuppressionStrategy.fromConfig( + private static final SpanSuppressionStrategy spanSuppressionStrategy; + + static { + String value = + ConfigPropertiesUtil.getString( + "otel.instrumentation.common.experimental.span-suppression-strategy"); + + if (value == null) { + value = ConfigPropertiesUtil.getString( - "otel.instrumentation.experimental.span-suppression-strategy")); + "otel.instrumentation.experimental.span-suppression-strategy"); + + if (value != null) { + logger.warning( + "Using deprecated config: otel.instrumentation.experimental.span-suppression-strategy. " + + "Use otel.instrumentation.common.experimental.span-suppression-strategy instead."); + } + } + + spanSuppressionStrategy = SpanSuppressionStrategy.fromConfig(value); + } final OpenTelemetry openTelemetry; final String instrumentationName; diff --git a/instrumentation/camel-2.20/javaagent/build.gradle.kts b/instrumentation/camel-2.20/javaagent/build.gradle.kts index b1166690fa58..9880343bb340 100644 --- a/instrumentation/camel-2.20/javaagent/build.gradle.kts +++ b/instrumentation/camel-2.20/javaagent/build.gradle.kts @@ -74,7 +74,7 @@ tasks { jvmArgs("-Dotel.instrumentation.aws-sdk.experimental-span-attributes=true") // TODO: fix camel instrumentation so that it uses semantic attributes extractors - jvmArgs("-Dotel.instrumentation.experimental.span-suppression-strategy=span-kind") + jvmArgs("-Dotel.instrumentation.common.experimental.span-suppression-strategy=span-kind") // required on jdk17 jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java index 400bd5922ea3..3d15d1d3004f 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java @@ -292,7 +292,8 @@ private static void installEarlyInstrumentation( } private static void copyNecessaryConfigToSystemProperties(ConfigProperties config) { - for (String property : asList("otel.instrumentation.experimental.span-suppression-strategy")) { + for (String property : + asList("otel.instrumentation.common.experimental.span-suppression-strategy")) { String value = config.getString(property); if (value != null) { System.setProperty(property, value); From 64ccedffe99747f85f5e967952c8cc576926b500 Mon Sep 17 00:00:00 2001 From: Abhilash Garapati Date: Fri, 12 Dec 2025 01:32:35 +0530 Subject: [PATCH 02/40] Apply backward-compatible span suppression config rename in AgentInstaller --- .../io/opentelemetry/javaagent/tooling/AgentInstaller.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java index 3d15d1d3004f..54618e4660e2 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java @@ -292,8 +292,7 @@ private static void installEarlyInstrumentation( } private static void copyNecessaryConfigToSystemProperties(ConfigProperties config) { - for (String property : - asList("otel.instrumentation.common.experimental.span-suppression-strategy")) { + for (String property : asList("otel.instrumentation.common.experimental.span-suppression-strategy")) { String value = config.getString(property); if (value != null) { System.setProperty(property, value); From 7913784a1449737d7f68309ceb1e453c78bea03b Mon Sep 17 00:00:00 2001 From: Abhilash Garapati Date: Fri, 12 Dec 2025 01:46:21 +0530 Subject: [PATCH 03/40] Apply spotless formatting --- .../io/opentelemetry/javaagent/tooling/AgentInstaller.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java index 54618e4660e2..3d15d1d3004f 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java @@ -292,7 +292,8 @@ private static void installEarlyInstrumentation( } private static void copyNecessaryConfigToSystemProperties(ConfigProperties config) { - for (String property : asList("otel.instrumentation.common.experimental.span-suppression-strategy")) { + for (String property : + asList("otel.instrumentation.common.experimental.span-suppression-strategy")) { String value = config.getString(property); if (value != null) { System.setProperty(property, value); From 5848fb446757c858f325812b75669a87a52bb545 Mon Sep 17 00:00:00 2001 From: Abhilash-Garapati Date: Fri, 12 Dec 2025 16:40:28 +0530 Subject: [PATCH 04/40] Add DeprecatedConfigProperties and apply backward-compatible config rename --- .../internal/DeprecatedConfigProperties.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/DeprecatedConfigProperties.java diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/DeprecatedConfigProperties.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/DeprecatedConfigProperties.java new file mode 100644 index 000000000000..9e2cf4cbf3cb --- /dev/null +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/DeprecatedConfigProperties.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.internal; + +import static java.util.Collections.emptyList; +import static java.util.logging.Level.WARNING; + +import java.util.List; +import java.util.logging.Logger; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +@SuppressWarnings("unused") +public final class DeprecatedConfigProperties { + + private static final Logger logger = Logger.getLogger(DeprecatedConfigProperties.class.getName()); + + public static boolean getBoolean( + String deprecatedPropertyName, String newPropertyName, boolean defaultValue) { + + warnIfUsed(deprecatedPropertyName, newPropertyName); + + boolean value = ConfigPropertiesUtil.getBoolean(deprecatedPropertyName, defaultValue); + return ConfigPropertiesUtil.getBoolean(newPropertyName, value); + } + + public static List getList(String deprecatedPropertyName, String newPropertyName) { + + warnIfUsed(deprecatedPropertyName, newPropertyName); + + List value = ConfigPropertiesUtil.getList(deprecatedPropertyName, emptyList()); + return ConfigPropertiesUtil.getList(newPropertyName, value); + } + + private static void warnIfUsed(String deprecatedPropertyName, String newPropertyName) { + if (ConfigPropertiesUtil.getString(deprecatedPropertyName) != null) { + logger.log( + WARNING, + "Deprecated property \"{0}\" was used; use the \"{1}\" property instead", + new Object[] {deprecatedPropertyName, newPropertyName}); + } + } + + private DeprecatedConfigProperties() {} +} From 90a729508eb26b47d59329bc41044e71bdbbe2e9 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 15 Dec 2025 16:43:04 +0100 Subject: [PATCH 05/40] use DeclarativeConfigUtil for library config usage --- CHANGELOG.md | 6 + docs/advanced-configuration-options.md | 6 +- .../opentelemetry-instrumentation-api.txt | 5 +- .../build.gradle.kts | 8 + ...tiesBackedDeclarativeConfigProperties.java | 180 ++++++++++++++++++ ...BackedDeclarativeConfigPropertiesTest.java | 164 ++++++++++++++++ .../api/instrumenter/InstrumenterBuilder.java | 68 ++++--- .../api/internal/ConfigPropertiesUtil.java | 55 +++--- .../api/internal/ConfigUtil.java | 81 ++++++++ .../internal/ConfigPropertiesUtilTest.java | 17 +- .../autoconfigure/TracingRequestHandler.java | 39 ++-- .../awssdk/v2_2/AwsSdkSingletons.java | 25 +-- .../v2_2/autoconfigure/AwsSdkSingletons.java | 28 +-- .../AbstractAwsSdkTelemetryFactory.java | 51 ----- .../v2_2/internal/AwsSdkTelemetryFactory.java | 49 +++++ .../jdbc/OpenTelemetryDriver.java | 32 ++-- .../internal/JdbcInstrumenterFactory.java | 33 ++-- .../v2_6/TracingConsumerInterceptor.java | 35 +++- .../v2_6/TracingProducerInterceptor.java | 26 ++- .../OpenTelemetryContextDataProvider.java | 10 +- .../v2_17/internal/ContextDataKeys.java | 23 ++- .../servlet-common/bootstrap/build.gradle.kts | 4 + .../servlet/ExperimentalSnippetHolder.java | 31 ++- .../AbstractTestContainerManager.java | 4 +- 24 files changed, 745 insertions(+), 235 deletions(-) create mode 100644 instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java create mode 100644 instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java create mode 100644 instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigUtil.java delete mode 100644 instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AbstractAwsSdkTelemetryFactory.java create mode 100644 instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java diff --git a/CHANGELOG.md b/CHANGELOG.md index ccb7a7d3abc5..87b50ea01989 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ ### ⚠️ Breaking Changes +- Rename `otel.experimental.javascript-snippet` to + `otel.instrumentation.servlet.experimental.javascript-snippet` to follow naming conventions + ([#15339](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/15339)) + +### ⚠️ Breaking Changes + - ActiveMQ Classic JMX metrics: rename attributes and metrics to align with semantic conventions (see PR description for specifics) ([#14996](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/14996)) diff --git a/docs/advanced-configuration-options.md b/docs/advanced-configuration-options.md index 537253406497..4ae0e075c5d1 100644 --- a/docs/advanced-configuration-options.md +++ b/docs/advanced-configuration-options.md @@ -45,9 +45,9 @@ This feature is designed for integrating client-side monitoring. We plan to integrate OpenTelemetry's own client-side monitoring solution by default once it's available (see the [browser instrumentation proposal](https://github.com/open-telemetry/community/blob/main/projects/browser-phase-1.md)). -| System property | Environment variable | Purpose | -|--------------------------------------|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| otel.experimental.javascript-snippet | OTEL_EXPERIMENTAL_JAVASCRIPT_SNIPPET | Experimental setting to inject a JavaScript snippet into HTML responses after the opening `` tag. The value should be a complete JavaScript snippet including `"` | +| System property | Environment variable | Purpose | +|----------------------------------------------------------------|----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `otel.instrumentation.servlet.experimental.javascript-snippet` | `OTEL_INSTRUMENTATION_SERVLET_EXPERIMENTAL_JAVASCRIPT_SNIPPET` | Experimental setting to inject a JavaScript snippet into HTML responses after the opening `` tag. The value should be a complete JavaScript snippet including `"` | **Important notes:** diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt index dda7a3ca5e05..787b54ffc48a 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt @@ -1,2 +1,5 @@ Comparing source compatibility of opentelemetry-instrumentation-api-2.24.0-SNAPSHOT.jar against opentelemetry-instrumentation-api-2.23.0.jar -No changes. \ No newline at end of file +*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + GENERIC TEMPLATES: === REQUEST:java.lang.Object, === RESPONSE:java.lang.Object + +++ NEW METHOD: PUBLIC(+) STATIC(+) boolean isDeclarativeConfig(io.opentelemetry.api.OpenTelemetry) diff --git a/instrumentation-api-incubator/build.gradle.kts b/instrumentation-api-incubator/build.gradle.kts index 3db18fcaf65c..f970c702aaf6 100644 --- a/instrumentation-api-incubator/build.gradle.kts +++ b/instrumentation-api-incubator/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-sdk") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating") + testImplementation("org.junit-pioneer:junit-pioneer") } val jflexSourceDir = layout.projectDirectory.dir("src/main/jflex") @@ -98,4 +99,11 @@ tasks { check { dependsOn(testStableSemconv, testBothSemconv) } + + withType().configureEach { + // required on jdk17 for junit pioneer + jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") + jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED") + jvmArgs("-XX:+IgnoreUnrecognizedVMOptions") + } } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java new file mode 100644 index 000000000000..33c1a5dbd9af --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java @@ -0,0 +1,180 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.config.internal; + +import static java.util.Collections.emptySet; + +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.common.ComponentLoader; +import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import javax.annotation.Nullable; + +/** + * Implementation of {@link DeclarativeConfigProperties} backed by system properties and + * environmental variables. + * + *

It tracks the navigation path and only resolves to system properties at the leaf node when a + * value is actually requested. + */ +final class SystemPropertiesBackedDeclarativeConfigProperties + implements DeclarativeConfigProperties { + + private final List path; + + public static DeclarativeConfigProperties createInstrumentationConfig() { + return new SystemPropertiesBackedDeclarativeConfigProperties(Collections.emptyList()); + } + + private SystemPropertiesBackedDeclarativeConfigProperties(List path) { + this.path = path; + } + + @Nullable + @Override + public String getString(String name) { + String fullPath = pathWithName(name); + return ConfigPropertiesUtil.getString(toPropertyKey(fullPath)); + } + + @Nullable + @Override + public Boolean getBoolean(String name) { + String value = getString(name); + return value == null ? null : Boolean.parseBoolean(value); + } + + @Nullable + @Override + public Integer getInt(String name) { + String strValue = getString(name); + if (strValue == null) { + return null; + } + try { + return Integer.parseInt(strValue); + } catch (NumberFormatException ignored) { + return null; + } + } + + @Nullable + @Override + public Long getLong(String name) { + String strValue = getString(name); + if (strValue == null) { + return null; + } + try { + return Long.getLong(strValue); + } catch (NumberFormatException ignored) { + return null; + } + } + + @Nullable + @Override + public Double getDouble(String name) { + String strValue = getString(name); + if (strValue == null) { + return null; + } + try { + return Double.parseDouble(strValue); + } catch (NumberFormatException ignored) { + return null; + } + } + + /** + * Important: this method should return null if there is no structured child with the given name, + * but unfortunately that is not implementable on top of ConfigProperties. + * + *

This will be misleading if anyone is comparing the return value to null. + */ + @Override + public DeclarativeConfigProperties getStructured(String name) { + List newPath = new ArrayList<>(path); + newPath.add(name); + return new SystemPropertiesBackedDeclarativeConfigProperties(newPath); + } + + @Nullable + @Override + @SuppressWarnings("unchecked") // Safe because T is known to be String via scalarType check + public List getScalarList(String name, Class scalarType) { + if (scalarType != String.class) { + return null; + } + String value = getString(name); + return value == null ? null : (List) filterBlanksAndNulls(value.split(",")); + } + + @Nullable + @Override + public List getStructuredList(String name) { + return null; + } + + @Override + public Set getPropertyKeys() { + // this is not supported when using system properties based configuration + return emptySet(); + } + + @Override + public ComponentLoader getComponentLoader() { + throw new UnsupportedOperationException(); + } + + private String pathWithName(String name) { + if (path.isEmpty()) { + return name; + } + return String.join(".", path) + "." + name; + } + + private static String toPropertyKey(String fullPath) { + String translatedPath = translatePath(fullPath); + // Standard mapping + return "otel.instrumentation." + translatedPath; + } + + private static String translatePath(String path) { + StringBuilder result = new StringBuilder(); + for (String segment : path.split("\\.")) { + // Skip "java" segment - it doesn't exist in system properties + if ("java".equals(segment)) { + continue; + } + if (result.length() > 0) { + result.append("."); + } + result.append(translateName(segment)); + } + return result.toString(); + } + + private static String translateName(String name) { + if (name.endsWith("/development")) { + return "experimental." + + name.substring(0, name.length() - "/development".length()).replace('_', '-'); + } + return name.replace('_', '-'); + } + + private static List filterBlanksAndNulls(String[] values) { + return Arrays.stream(values) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .collect(Collectors.toList()); + } +} diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java new file mode 100644 index 000000000000..64a60d759b41 --- /dev/null +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java @@ -0,0 +1,164 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.config.internal; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import java.util.List; +import java.util.stream.Stream; +import javax.annotation.Nullable; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junitpioneer.jupiter.SetEnvironmentVariable; +import org.junitpioneer.jupiter.SetSystemProperty; + +class SystemPropertiesBackedDeclarativeConfigPropertiesTest { + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_STRING", value = "env_value") + @SetSystemProperty(key = "otel.instrumentation.test.property.string", value = "sys_value") + @Test + void getString_systemProperty() { + assertString("sys_value"); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_STRING", value = "env_value") + @Test + void getString_environmentVariable() { + assertString("env_value"); + } + + @Test + void getString_none() { + assertString(null); + } + + private static void assertString(@Nullable String expected) { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getString("string")) + .isEqualTo(expected); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_BOOLEAN", value = "false") + @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "true") + @Test + void getBoolean_systemProperty() { + assertBoolean(true); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_BOOLEAN", value = "true") + @Test + void getBoolean_environmentVariable() { + assertBoolean(true); + } + + @Test + void getBoolean_none() { + assertBoolean(null); + } + + private static void assertBoolean(@Nullable Boolean expected) { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getBoolean("boolean")) + .isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("booleanValuesProvider") + @SuppressWarnings("unused") + void getBoolean_invalidValue(String value, @Nullable Boolean expected) { + // This test verifies behavior with invalid boolean values via system properties + assertThat(expected).isNull(); + } + + static Stream booleanValuesProvider() { + return Stream.of( + Arguments.of("invalid", null), Arguments.of("123", null), Arguments.of("", null)); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_LIST", value = "a,b,c") + @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = "x,y,z") + @Test + void getList_systemProperty() { + assertList(asList("x", "y", "z")); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_LIST", value = "a,b,c") + @Test + void getList_environmentVariable() { + assertList(asList("a", "b", "c")); + } + + @Test + void getList_none() { + assertList(null); + } + + private static void assertList(@Nullable List expected) { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getScalarList("list", String.class)) + .isEqualTo(expected); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = "a,b,c") + @Test + void getList_multipleValues() { + assertList(asList("a", "b", "c")); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = "single") + @Test + void getList_singleValue() { + assertList(singletonList("single")); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = "") + @Test + void getList_emptyString() { + assertList(emptyList()); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = " a , b , c ") + @Test + void getList_withWhitespace() { + assertList(asList("a", "b", "c")); + } + + @Test + void getList_unsupportedType() { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getScalarList("list", Integer.class)) + .isNull(); + } +} diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java index 4edc0f616db4..2c8ce9782188 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java @@ -5,11 +5,14 @@ package io.opentelemetry.instrumentation.api.instrumenter; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static java.util.Objects.requireNonNull; import static java.util.logging.Level.WARNING; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.ExtendedOpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.metrics.MeterBuilder; import io.opentelemetry.api.trace.SpanKind; @@ -48,28 +51,7 @@ public final class InstrumenterBuilder { private static final Logger logger = Logger.getLogger(InstrumenterBuilder.class.getName()); - - private static final SpanSuppressionStrategy spanSuppressionStrategy; - - static { - String value = - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.experimental.span-suppression-strategy"); - - if (value == null) { - value = - ConfigPropertiesUtil.getString( - "otel.instrumentation.experimental.span-suppression-strategy"); - - if (value != null) { - logger.warning( - "Using deprecated config: otel.instrumentation.experimental.span-suppression-strategy. " - + "Use otel.instrumentation.common.experimental.span-suppression-strategy instead."); - } - } - - spanSuppressionStrategy = SpanSuppressionStrategy.fromConfig(value); - } + private static final boolean supportsDeclarativeConfig = supportsDeclarativeConfig(); final OpenTelemetry openTelemetry; final String instrumentationName; @@ -93,6 +75,20 @@ public final class InstrumenterBuilder { boolean propagateOperationListenersToOnEnd = false; boolean enabled = true; + private static boolean supportsDeclarativeConfig() { + try { + Class.forName("io.opentelemetry.api.incubator.ExtendedOpenTelemetry"); + return true; + } catch (ClassNotFoundException e) { + // The incubator module is not available. + // This only happens in OpenTelemetry API instrumentation tests, where an older version of + // OpenTelemetry API is used that does not have ExtendedOpenTelemetry. + // Having the incubator module without ExtendedOpenTelemetry class should still return false + // for those tests to avoid a ClassNotFoundException. + return false; + } + } + static { Experimental.internalAddOperationListenerAttributesExtractor( (builder, operationListenerAttributesExtractor) -> @@ -391,7 +387,28 @@ private String getSchemaUrl() { SpanSuppressor buildSpanSuppressor() { return new SpanSuppressors.ByContextKey( - spanSuppressionStrategy.create(getSpanKeysFromAttributesExtractors())); + SpanSuppressionStrategy.fromConfig(getSpanSuppressionStrategy()) + .create(getSpanKeysFromAttributesExtractors())); + } + + @Nullable + private String getSpanSuppressionStrategy() { + // otel.instrumentation.experimental.* doesn't fit the usual pattern of configuration properties + // for instrumentations, so we need to handle both declarative and non-declarative configs here + if (isDeclarativeConfig(openTelemetry)) { + DeclarativeConfigProperties instrumentationConfig = + ((ExtendedOpenTelemetry) openTelemetry).getConfigProvider().getInstrumentationConfig(); + if (instrumentationConfig == null) { + return null; + } + return instrumentationConfig + .getStructured("java", empty()) + .getStructured("common", empty()) + .getString("span_suppression_strategy/development"); + } else { + return ConfigPropertiesUtil.getString( + "otel.instrumentation.experimental.span-suppression-strategy"); + } } private Set getSpanKeysFromAttributesExtractors() { @@ -471,6 +488,11 @@ public void setSpanStatusExtractorCustomizer( } } + /** Returns true if the given OpenTelemetry instance supports Declarative Config. */ + public static boolean isDeclarativeConfig(OpenTelemetry openTelemetry) { + return supportsDeclarativeConfig && openTelemetry instanceof ExtendedOpenTelemetry; + } + private interface InstrumenterConstructor { Instrumenter create(InstrumenterBuilder builder); diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java index 862cd6b13588..46a3b98f2b0c 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java @@ -5,10 +5,6 @@ package io.opentelemetry.instrumentation.api.internal; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.stream.Collectors; import javax.annotation.Nullable; /** @@ -17,11 +13,25 @@ */ public final class ConfigPropertiesUtil { + /** + * Returns the boolean value of the given property name from system properties and environment + * variables. + * + *

It's recommended to use {@link io.opentelemetry.api.incubator.config.ConfigProvider} instead + * to support Declarative Config. + */ public static boolean getBoolean(String propertyName, boolean defaultValue) { String strValue = getString(propertyName); return strValue == null ? defaultValue : Boolean.parseBoolean(strValue); } + /** + * Returns the int value of the given property name from system properties and environment + * variables. + * + *

It's recommended to use {@link io.opentelemetry.api.incubator.config.ConfigProvider} instead + * to support Declarative Config. + */ public static int getInt(String propertyName, int defaultValue) { String strValue = getString(propertyName); if (strValue == null) { @@ -34,37 +44,16 @@ public static int getInt(String propertyName, int defaultValue) { } } + /** + * Returns the string value of the given property name from system properties and environment + * variables. + * + *

It's recommended to use {@link io.opentelemetry.api.incubator.config.ConfigProvider} instead + * to support Declarative Config. + */ @Nullable public static String getString(String propertyName) { - String value = System.getProperty(propertyName); - if (value != null) { - return value; - } - return System.getenv(toEnvVarName(propertyName)); - } - - public static String getString(String propertyName, String defaultValue) { - String strValue = getString(propertyName); - return strValue == null ? defaultValue : strValue; - } - - public static List getList(String propertyName, List defaultValue) { - String value = getString(propertyName); - if (value == null) { - return defaultValue; - } - return filterBlanksAndNulls(value.split(",")); - } - - private static List filterBlanksAndNulls(String[] values) { - return Arrays.stream(values) - .map(String::trim) - .filter(s -> !s.isEmpty()) - .collect(Collectors.toList()); - } - - private static String toEnvVarName(String propertyName) { - return propertyName.toUpperCase(Locale.ROOT).replace('-', '_').replace('.', '_'); + return ConfigUtil.getString(ConfigUtil.normalizePropertyKey(propertyName)); } private ConfigPropertiesUtil() {} diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigUtil.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigUtil.java new file mode 100644 index 000000000000..6dc734e1d9e4 --- /dev/null +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigUtil.java @@ -0,0 +1,81 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.internal; + +import java.util.ConcurrentModificationException; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import javax.annotation.Nullable; + +/** + * Configuration utilities. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + * + *

Copied from SDK + * because some tests target an SDK version where this class does not exist. + */ +final class ConfigUtil { + + private ConfigUtil() {} + + /** + * Returns a copy of system properties which is safe to iterate over. + * + *

In java 8 and android environments, iterating through system properties may trigger {@link + * ConcurrentModificationException}. This method ensures callers can iterate safely without risk + * of exception. See https://github.com/open-telemetry/opentelemetry-java/issues/6732 for details. + */ + static Properties safeSystemProperties() { + return (Properties) System.getProperties().clone(); + } + + /** + * Return the system property or environment variable for the {@code key}. + * + *

Normalize the {@code key} using {@link #normalizePropertyKey(String)}. Match to system + * property keys also normalized with {@link #normalizePropertyKey(String)}. Match to environment + * variable keys normalized with {@link #normalizeEnvironmentVariableKey(String)}. System + * properties take priority over environment variables. + * + * @param key the property key + * @return the system property if not null, or the environment variable if not null, or {@code + * null} + */ + @Nullable + static String getString(String key) { + String normalizedKey = normalizePropertyKey(key); + + for (Map.Entry entry : safeSystemProperties().entrySet()) { + if (normalizedKey.equals(normalizePropertyKey(entry.getKey().toString()))) { + return entry.getValue().toString(); + } + } + + for (Map.Entry entry : System.getenv().entrySet()) { + if (normalizedKey.equals(normalizeEnvironmentVariableKey(entry.getKey()))) { + return entry.getValue(); + } + } + + return null; + } + + /** + * Normalize an environment variable key by converting to lower case and replacing "_" with ".". + */ + static String normalizeEnvironmentVariableKey(String key) { + return key.toLowerCase(Locale.ROOT).replace("_", "."); + } + + /** Normalize a property key by converting to lower case and replacing "-" with ".". */ + static String normalizePropertyKey(String key) { + return key.toLowerCase(Locale.ROOT).replace("-", "."); + } +} diff --git a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtilTest.java b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtilTest.java index 8a496322b6e0..29e5082fd009 100644 --- a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtilTest.java +++ b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtilTest.java @@ -55,21 +55,26 @@ void getInt_invalidNumber() { assertThat(ConfigPropertiesUtil.getInt("test.property.int", -1)).isEqualTo(-1); } - @SetEnvironmentVariable(key = "TEST_PROPERTY_BOOLEAN", value = "false") - @SetSystemProperty(key = "test.property.boolean", value = "true") + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_BOOLEAN", value = "false") + @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "true") @Test void getBoolean_systemProperty() { - assertThat(ConfigPropertiesUtil.getBoolean("test.property.boolean", false)).isTrue(); + assertBoolean(true); } - @SetEnvironmentVariable(key = "TEST_PROPERTY_BOOLEAN", value = "true") + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_BOOLEAN", value = "true") @Test void getBoolean_environmentVariable() { - assertThat(ConfigPropertiesUtil.getBoolean("test.property.boolean", false)).isTrue(); + assertBoolean(true); } @Test void getBoolean_none() { - assertThat(ConfigPropertiesUtil.getBoolean("test.property.boolean", false)).isFalse(); + assertBoolean(false); + } + + private static void assertBoolean(boolean expected) { + assertThat(ConfigPropertiesUtil.getBoolean("otel.instrumentation.test.property.boolean", false)) + .isEqualTo(expected); } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java index a68b240b1b0d..24887689769a 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.awssdk.v1_11.autoconfigure; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static java.util.Collections.emptyList; import com.amazonaws.AmazonWebServiceRequest; @@ -12,27 +13,37 @@ import com.amazonaws.Response; import com.amazonaws.handlers.RequestHandler2; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.awssdk.v1_11.AwsSdkTelemetry; +import java.util.Optional; /** * A {@link RequestHandler2} for use as an SPI by the AWS SDK to automatically trace all requests. */ public class TracingRequestHandler extends RequestHandler2 { - private static final RequestHandler2 DELEGATE = - AwsSdkTelemetry.builder(GlobalOpenTelemetry.get()) - .setCaptureExperimentalSpanAttributes( - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.aws-sdk.experimental-span-attributes", false)) - .setMessagingReceiveTelemetryEnabled( - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.messaging.experimental.receive-telemetry.enabled", false)) - .setCapturedHeaders( - ConfigPropertiesUtil.getList( - "otel.instrumentation.messaging.experimental.capture-headers", emptyList())) - .build() - .newRequestHandler(); + private static final RequestHandler2 DELEGATE = buildDelegate(GlobalOpenTelemetry.get()); + + private static RequestHandler2 buildDelegate(OpenTelemetry openTelemetry) { + DeclarativeConfigProperties java = + DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()); + DeclarativeConfigProperties awsSdk = java.getStructured("aws_sdk", empty()); + + return AwsSdkTelemetry.builder(openTelemetry) + .setCaptureExperimentalSpanAttributes( + awsSdk.getBoolean("span_attributes/development", false)) + .setMessagingReceiveTelemetryEnabled( + awsSdk.getBoolean("messaging.receive_telemetry/development", false)) + .setCapturedHeaders( + Optional.ofNullable( + java.getStructured("messaging", empty()) + .getScalarList("capture_headers/development", String.class)) + .orElse(emptyList())) + .build() + .newRequestHandler(); + } @Override public void beforeRequest(Request request) { diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java index 7f377f766c7f..f2fbbbbcd9b2 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java @@ -6,36 +6,15 @@ package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; -import io.opentelemetry.instrumentation.awssdk.v2_2.internal.AbstractAwsSdkTelemetryFactory; -import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; -import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import java.util.List; +import io.opentelemetry.instrumentation.awssdk.v2_2.internal.AwsSdkTelemetryFactory; public final class AwsSdkSingletons { - private static final AwsSdkTelemetry TELEMETRY = new AwsSdkTelemetryFactory().telemetry(); + private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.telemetry(); public static AwsSdkTelemetry telemetry() { return TELEMETRY; } - private static class AwsSdkTelemetryFactory extends AbstractAwsSdkTelemetryFactory { - - @Override - protected List getCapturedHeaders() { - return ExperimentalConfig.get().getMessagingHeaders(); - } - - @Override - protected boolean messagingReceiveTelemetryEnabled() { - return ExperimentalConfig.get().messagingReceiveInstrumentationEnabled(); - } - - @Override - protected boolean getBoolean(String name, boolean defaultValue) { - return AgentInstrumentationConfig.get().getBoolean(name, defaultValue); - } - } - private AwsSdkSingletons() {} } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java index c11d4dfc658a..565b08e048ac 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java @@ -5,40 +5,16 @@ package io.opentelemetry.instrumentation.awssdk.v2_2.autoconfigure; -import static java.util.Collections.emptyList; - -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; -import io.opentelemetry.instrumentation.awssdk.v2_2.internal.AbstractAwsSdkTelemetryFactory; -import java.util.List; +import io.opentelemetry.instrumentation.awssdk.v2_2.internal.AwsSdkTelemetryFactory; public final class AwsSdkSingletons { - private static final AwsSdkTelemetry TELEMETRY = new AwsSdkTelemetryFactory().telemetry(); + private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.telemetry(); public static AwsSdkTelemetry telemetry() { return TELEMETRY; } - private static class AwsSdkTelemetryFactory extends AbstractAwsSdkTelemetryFactory { - - @Override - protected List getCapturedHeaders() { - return ConfigPropertiesUtil.getList( - "otel.instrumentation.messaging.experimental.capture-headers", emptyList()); - } - - @Override - protected boolean messagingReceiveTelemetryEnabled() { - return ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.messaging.experimental.receive-telemetry.enabled", false); - } - - @Override - protected boolean getBoolean(String name, boolean defaultValue) { - return ConfigPropertiesUtil.getBoolean(name, defaultValue); - } - } - private AwsSdkSingletons() {} } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AbstractAwsSdkTelemetryFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AbstractAwsSdkTelemetryFactory.java deleted file mode 100644 index 490c5038519a..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AbstractAwsSdkTelemetryFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.awssdk.v2_2.internal; - -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; -import java.util.List; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public abstract class AbstractAwsSdkTelemetryFactory { - protected abstract List getCapturedHeaders(); - - private boolean captureExperimentalSpanAttributes() { - return getBoolean("otel.instrumentation.aws-sdk.experimental-span-attributes", false); - } - - protected abstract boolean messagingReceiveTelemetryEnabled(); - - private boolean useMessagingPropagator() { - return getBoolean( - "otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging", false); - } - - private boolean recordIndividualHttpError() { - return getBoolean( - "otel.instrumentation.aws-sdk.experimental-record-individual-http-error", false); - } - - private boolean genaiCaptureMessageContent() { - return getBoolean("otel.instrumentation.genai.capture-message-content", false); - } - - protected abstract boolean getBoolean(String name, boolean defaultValue); - - public AwsSdkTelemetry telemetry() { - return AwsSdkTelemetry.builder(GlobalOpenTelemetry.get()) - .setCapturedHeaders(getCapturedHeaders()) - .setCaptureExperimentalSpanAttributes(captureExperimentalSpanAttributes()) - .setMessagingReceiveTelemetryEnabled(messagingReceiveTelemetryEnabled()) - .setUseConfiguredPropagatorForMessaging(useMessagingPropagator()) - .setRecordIndividualHttpError(recordIndividualHttpError()) - .setGenaiCaptureMessageContent(genaiCaptureMessageContent()) - .build(); - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java new file mode 100644 index 000000000000..7d0632b60590 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2.internal; + +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; +import static java.util.Collections.emptyList; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; +import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class AwsSdkTelemetryFactory { + + public static AwsSdkTelemetry telemetry() { + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + DeclarativeConfigProperties java = + DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()); + DeclarativeConfigProperties awsSdk = java.getStructured("aws_sdk", empty()); + DeclarativeConfigProperties messaging = java.getStructured("messaging", empty()); + + return AwsSdkTelemetry.builder(openTelemetry) + .setCapturedHeaders( + messaging.getScalarList("capture_headers/development", String.class, emptyList())) + .setCaptureExperimentalSpanAttributes( + awsSdk.getBoolean("span_attributes/development", false)) + .setMessagingReceiveTelemetryEnabled( + messaging + .getStructured("receive_telemetry/development", empty()) + .getBoolean("enabled", false)) + .setUseConfiguredPropagatorForMessaging( + awsSdk.getBoolean("use_propagator_for_messaging/development", false)) + .setRecordIndividualHttpError( + awsSdk.getBoolean("record_individual_http_error/development", false)) + .setGenaiCaptureMessageContent( + java.getStructured("genai", empty()).getBoolean("capture_message_content", false)) + .build(); + } + + private AwsSdkTelemetryFactory() {} +} diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java index 617da2b99f03..20dfa314ee3f 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java @@ -20,12 +20,14 @@ package io.opentelemetry.instrumentation.jdbc; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static io.opentelemetry.instrumentation.jdbc.internal.JdbcInstrumenterFactory.INSTRUMENTATION_NAME; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.SqlCommenter; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; import io.opentelemetry.instrumentation.jdbc.internal.DbRequest; import io.opentelemetry.instrumentation.jdbc.internal.JdbcConnectionUrlParser; @@ -63,14 +65,22 @@ public final class OpenTelemetryDriver implements Driver { private static final AtomicBoolean REGISTERED = new AtomicBoolean(); private static final List DRIVER_CANDIDATES = new CopyOnWriteArrayList<>(); - private static final SqlCommenter sqlCommenter = - SqlCommenter.builder() - .setEnabled( - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled", - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.common.experimental.db-sqlcommenter.enabled", false))) - .build(); + private static SqlCommenter getSqlCommenter(OpenTelemetry openTelemetry) { + DeclarativeConfigProperties java = + DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()); + + boolean defaultValue = + java.getStructured("common", empty()) + .getStructured("db_sqlcommenter/development", empty()) + .getBoolean("enabled", false); + + return SqlCommenter.builder() + .setEnabled( + java.getStructured("jdbc", empty()) + .getStructured("sqlcommenter/development", empty()) + .getBoolean("enabled", defaultValue)) + .build(); + } static { try { @@ -256,7 +266,7 @@ public Connection connect(String url, Properties info) throws SQLException { Instrumenter statementInstrumenter = JdbcInstrumenterFactory.createStatementInstrumenter(openTelemetry); - boolean captureQueryParameters = JdbcInstrumenterFactory.captureQueryParameters(); + boolean captureQueryParameters = JdbcInstrumenterFactory.captureQueryParameters(openTelemetry); Instrumenter transactionInstrumenter = JdbcInstrumenterFactory.createTransactionInstrumenter(openTelemetry); @@ -266,7 +276,7 @@ public Connection connect(String url, Properties info) throws SQLException { statementInstrumenter, transactionInstrumenter, captureQueryParameters, - sqlCommenter); + getSqlCommenter(openTelemetry)); } @Override diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java index 9748181d713e..fe6d1547523b 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java @@ -5,9 +5,11 @@ package io.opentelemetry.instrumentation.jdbc.internal; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static java.util.Collections.emptyList; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -16,7 +18,6 @@ import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.jdbc.internal.dbinfo.DbInfo; import java.util.List; import javax.sql.DataSource; @@ -28,25 +29,26 @@ public final class JdbcInstrumenterFactory { public static final String INSTRUMENTATION_NAME = "io.opentelemetry.jdbc"; - public static boolean captureQueryParameters() { - return ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.jdbc.experimental.capture-query-parameters", false); + public static boolean captureQueryParameters(OpenTelemetry openTelemetry) { + return DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()) + .getStructured("jdbc", empty()) + .getBoolean("capture_query_parameters/development", false); } public static Instrumenter createStatementInstrumenter( OpenTelemetry openTelemetry) { - return createStatementInstrumenter(openTelemetry, captureQueryParameters()); + return createStatementInstrumenter(openTelemetry, captureQueryParameters(openTelemetry)); } static Instrumenter createStatementInstrumenter( OpenTelemetry openTelemetry, boolean captureQueryParameters) { + boolean statementSanitizationEnabled = + DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()) + .getStructured("common", empty()) + .getStructured("db_statement_sanitizer", empty()) + .getBoolean("enabled", true); return createStatementInstrumenter( - openTelemetry, - emptyList(), - true, - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.common.db-statement-sanitizer.enabled", true), - captureQueryParameters); + openTelemetry, emptyList(), true, statementSanitizationEnabled, captureQueryParameters); } public static Instrumenter createStatementInstrumenter( @@ -92,10 +94,11 @@ public static Instrumenter createDataSourceInstrumenter( public static Instrumenter createTransactionInstrumenter( OpenTelemetry openTelemetry) { - return createTransactionInstrumenter( - openTelemetry, - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.jdbc.experimental.transaction.enabled", false)); + boolean enabled = + DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()) + .getStructured("jdbc", empty()) + .getBoolean("transaction/development", false); + return createTransactionInstrumenter(openTelemetry, enabled); } public static Instrumenter createTransactionInstrumenter( diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java index 96c040074088..49857a92fc29 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java @@ -5,17 +5,21 @@ package io.opentelemetry.instrumentation.kafkaclients.v2_6; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static java.util.Collections.emptyList; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.internal.Timer; import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContext; import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContextUtil; import java.util.Map; import java.util.Objects; +import java.util.Optional; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerInterceptor; import org.apache.kafka.clients.consumer.ConsumerRecords; @@ -32,15 +36,26 @@ @Deprecated public class TracingConsumerInterceptor implements ConsumerInterceptor { - private static final KafkaTelemetry telemetry = - KafkaTelemetry.builder(GlobalOpenTelemetry.get()) - .setMessagingReceiveInstrumentationEnabled( - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.messaging.experimental.receive-telemetry.enabled", false)) - .setCapturedHeaders( - ConfigPropertiesUtil.getList( - "otel.instrumentation.messaging.experimental.capture-headers", emptyList())) - .build(); + private static final KafkaTelemetry telemetry; + + static { + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + DeclarativeConfigProperties messaging = + DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()) + .getStructured("messaging", empty()); + + telemetry = + KafkaTelemetry.builder(openTelemetry) + .setMessagingReceiveInstrumentationEnabled( + messaging + .getStructured("receive_telemetry/development", empty()) + .getBoolean("enabled", false)) + .setCapturedHeaders( + Optional.ofNullable( + messaging.getScalarList("capture_headers/development", String.class)) + .orElse(emptyList())) + .build(); + } private String consumerGroup; private String clientId; diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingProducerInterceptor.java b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingProducerInterceptor.java index 007e1df51d4b..a599d115349a 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingProducerInterceptor.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingProducerInterceptor.java @@ -5,13 +5,16 @@ package io.opentelemetry.instrumentation.kafkaclients.v2_6; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static java.util.Collections.emptyList; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import java.util.Map; import java.util.Objects; +import java.util.Optional; import javax.annotation.Nullable; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerInterceptor; @@ -28,12 +31,21 @@ @Deprecated public class TracingProducerInterceptor implements ProducerInterceptor { - private static final KafkaTelemetry telemetry = - KafkaTelemetry.builder(GlobalOpenTelemetry.get()) - .setCapturedHeaders( - ConfigPropertiesUtil.getList( - "otel.instrumentation.messaging.experimental.capture-headers", emptyList())) - .build(); + private static final KafkaTelemetry telemetry; + + static { + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + + telemetry = + KafkaTelemetry.builder(openTelemetry) + .setCapturedHeaders( + Optional.ofNullable( + DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()) + .getStructured("messaging", empty()) + .getScalarList("capture_headers/development", String.class)) + .orElse(emptyList())) + .build(); + } @Nullable private String clientId; diff --git a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java index 57024ded7c3c..c92178095dc9 100644 --- a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java +++ b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java @@ -5,12 +5,15 @@ package io.opentelemetry.instrumentation.log4j.contextdata.v2_17; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; + +import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.baggage.Baggage; import io.opentelemetry.api.baggage.BaggageEntry; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.log4j.contextdata.v2_17.internal.ContextDataKeys; import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder; import java.util.Collections; @@ -25,7 +28,10 @@ */ public class OpenTelemetryContextDataProvider implements ContextDataProvider { private static final boolean BAGGAGE_ENABLED = - ConfigPropertiesUtil.getBoolean("otel.instrumentation.log4j-context-data.add-baggage", false); + DeclarativeConfigUtil.getStructured(GlobalOpenTelemetry.get(), "java", empty()) + .getStructured("log4j_context_data", empty()) + .getBoolean("add_baggage", false); + private static final boolean configuredResourceAttributeAccessible = isConfiguredResourceAttributeAccessible(); private static final Map staticContextData = getStaticContextData(); diff --git a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/internal/ContextDataKeys.java b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/internal/ContextDataKeys.java index a57da53ba61c..043b7e5499b0 100644 --- a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/internal/ContextDataKeys.java +++ b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/internal/ContextDataKeys.java @@ -5,8 +5,12 @@ package io.opentelemetry.instrumentation.log4j.contextdata.v2_17.internal; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.log.LoggingContextConstants; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at @@ -14,14 +18,19 @@ */ public final class ContextDataKeys { public static final String TRACE_ID_KEY = - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.logging.trace-id", LoggingContextConstants.TRACE_ID); + getLogging().getString("trace_id", LoggingContextConstants.TRACE_ID); + public static final String SPAN_ID_KEY = - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.logging.span-id", LoggingContextConstants.SPAN_ID); + getLogging().getString("span_id", LoggingContextConstants.SPAN_ID); + public static final String TRACE_FLAGS_KEY = - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.logging.trace-flags", LoggingContextConstants.TRACE_FLAGS); + getLogging().getString("trace_flags", LoggingContextConstants.TRACE_FLAGS); + + private static DeclarativeConfigProperties getLogging() { + return DeclarativeConfigUtil.getStructured(GlobalOpenTelemetry.get(), "java", empty()) + .getStructured("common", empty()) + .getStructured("logging", empty()); + } private ContextDataKeys() {} } diff --git a/instrumentation/servlet/servlet-common/bootstrap/build.gradle.kts b/instrumentation/servlet/servlet-common/bootstrap/build.gradle.kts index 072a96df450f..bfbb14f92c87 100644 --- a/instrumentation/servlet/servlet-common/bootstrap/build.gradle.kts +++ b/instrumentation/servlet/servlet-common/bootstrap/build.gradle.kts @@ -1,3 +1,7 @@ plugins { id("otel.javaagent-bootstrap") } + +dependencies { + compileOnly(project(":instrumentation-api-incubator")) +} diff --git a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java index ebfc41e7b72b..351a7ffd78de 100644 --- a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java +++ b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java @@ -5,15 +5,42 @@ package io.opentelemetry.javaagent.bootstrap.servlet; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; +import static java.util.logging.Level.WARNING; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; +import java.util.logging.Logger; public class ExperimentalSnippetHolder { + private static final Logger logger = Logger.getLogger(ExperimentalSnippetHolder.class.getName()); + + private static final String DEPRECATED_PROPERTY_NAME = "otel.experimental.javascript-snippet"; + private static final String NEW_PROPERTY_NAME = + "otel.instrumentation.servlet.experimental.javascript-snippet"; + private static volatile String snippet = getSnippetSetting(); private static String getSnippetSetting() { - String result = ConfigPropertiesUtil.getString("otel.experimental.javascript-snippet"); - return result == null ? "" : result; + String snippet = + DeclarativeConfigUtil.getStructured(GlobalOpenTelemetry.get(), "java", empty()) + .getStructured("servlet", empty()) + .getString("javascript-snippet/development", null); + // Can remove deprecated fallback in 2.24.0 + if (snippet != null) { + return snippet; + } + String deprecatedValue = ConfigPropertiesUtil.getString(DEPRECATED_PROPERTY_NAME); + if (deprecatedValue != null) { + logger.log( + WARNING, + "Deprecated property \"{0}\" was used; use the \"{1}\" property instead", + new Object[] {DEPRECATED_PROPERTY_NAME, NEW_PROPERTY_NAME}); + return deprecatedValue; + } + return ""; } public static void setSnippet(String newValue) { diff --git a/smoke-tests/src/main/java/io/opentelemetry/smoketest/AbstractTestContainerManager.java b/smoke-tests/src/main/java/io/opentelemetry/smoketest/AbstractTestContainerManager.java index 985c4381138a..8342151bb4c5 100644 --- a/smoke-tests/src/main/java/io/opentelemetry/smoketest/AbstractTestContainerManager.java +++ b/smoke-tests/src/main/java/io/opentelemetry/smoketest/AbstractTestContainerManager.java @@ -45,7 +45,9 @@ protected Map getAgentEnvironment( environment.put("OTEL_RESOURCE_ATTRIBUTES", "service.name=smoke-test"); } environment.put("OTEL_JAVAAGENT_DEBUG", "true"); - environment.put("OTEL_EXPERIMENTAL_JAVASCRIPT_SNIPPET", ""); + environment.put( + "OTEL_INSTRUMENTATION_SERVLET_EXPERIMENTAL_JAVASCRIPT_SNIPPET", + ""); environment.put("OTEL_INSTRUMENTATION_RUNTIME_TELEMETRY_PACKAGE_EMITTER_ENABLED", "true"); return environment; } From 9bdca32c54bb76deaea8d1a6a1cd931ee495245e Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 16 Dec 2025 08:59:48 +0100 Subject: [PATCH 06/40] use DeclarativeConfigUtil for library config usage --- .../current_vs_latest/opentelemetry-instrumentation-api.txt | 5 +---- .../api/instrumenter/InstrumenterBuilder.java | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt index 787b54ffc48a..dda7a3ca5e05 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt @@ -1,5 +1,2 @@ Comparing source compatibility of opentelemetry-instrumentation-api-2.24.0-SNAPSHOT.jar against opentelemetry-instrumentation-api-2.23.0.jar -*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder (not serializable) - === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 - GENERIC TEMPLATES: === REQUEST:java.lang.Object, === RESPONSE:java.lang.Object - +++ NEW METHOD: PUBLIC(+) STATIC(+) boolean isDeclarativeConfig(io.opentelemetry.api.OpenTelemetry) +No changes. \ No newline at end of file diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java index 2c8ce9782188..1cae6b78a1a5 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java @@ -489,7 +489,7 @@ public void setSpanStatusExtractorCustomizer( } /** Returns true if the given OpenTelemetry instance supports Declarative Config. */ - public static boolean isDeclarativeConfig(OpenTelemetry openTelemetry) { + private static boolean isDeclarativeConfig(OpenTelemetry openTelemetry) { return supportsDeclarativeConfig && openTelemetry instanceof ExtendedOpenTelemetry; } From e8dbab4374733a67d3c378eb77f5c1c0337c6444 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 16 Dec 2025 09:26:31 +0100 Subject: [PATCH 07/40] use DeclarativeConfigUtil for library config usage --- ...tiesBackedDeclarativeConfigProperties.java | 2 +- ...BackedDeclarativeConfigPropertiesTest.java | 350 ++++++++++++++++++ 2 files changed, 351 insertions(+), 1 deletion(-) diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java index 33c1a5dbd9af..576c3d948283 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java @@ -74,7 +74,7 @@ public Long getLong(String name) { return null; } try { - return Long.getLong(strValue); + return Long.parseLong(strValue); } catch (NumberFormatException ignored) { return null; } diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java index 64a60d759b41..8d895982f21b 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java @@ -161,4 +161,354 @@ void getList_unsupportedType() { .getScalarList("list", Integer.class)) .isNull(); } + + @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = ",,a,,b,,") + @Test + void getList_multipleCommas() { + assertList(asList("a", "b")); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = " ") + @Test + void getList_onlyWhitespace() { + assertList(emptyList()); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_INT", value = "100") + @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "200") + @Test + void getInt_systemProperty() { + assertInt(200); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_INT", value = "100") + @Test + void getInt_environmentVariable() { + assertInt(100); + } + + @Test + void getInt_none() { + assertInt(null); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "0") + @Test + void getInt_zero() { + assertInt(0); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "-42") + @Test + void getInt_negative() { + assertInt(-42); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "2147483647") + @Test + void getInt_maxValue() { + assertInt(Integer.MAX_VALUE); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "-2147483648") + @Test + void getInt_minValue() { + assertInt(Integer.MIN_VALUE); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "invalid") + @Test + void getInt_invalidValue() { + assertInt(null); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "12.34") + @Test + void getInt_decimalValue() { + assertInt(null); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "") + @Test + void getInt_emptyString() { + assertInt(null); + } + + private static void assertInt(@Nullable Integer expected) { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getInt("int")) + .isEqualTo(expected); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_LONG", value = "100") + @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "200") + @Test + void getLong_systemProperty() { + assertLong(200L); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_LONG", value = "100") + @Test + void getLong_environmentVariable() { + assertLong(100L); + } + + @Test + void getLong_none() { + assertLong(null); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "0") + @Test + void getLong_zero() { + assertLong(0L); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "-42") + @Test + void getLong_negative() { + assertLong(-42L); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "9223372036854775807") + @Test + void getLong_maxValue() { + assertLong(Long.MAX_VALUE); + } + + @SetSystemProperty( + key = "otel.instrumentation.test.property.long", + value = "-9223372036854775808") + @Test + void getLong_minValue() { + assertLong(Long.MIN_VALUE); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "invalid") + @Test + void getLong_invalidValue() { + assertLong(null); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "") + @Test + void getLong_emptyString() { + assertLong(null); + } + + private static void assertLong(@Nullable Long expected) { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getLong("long")) + .isEqualTo(expected); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_DOUBLE", value = "1.5") + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "2.5") + @Test + void getDouble_systemProperty() { + assertDouble(2.5); + } + + @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_DOUBLE", value = "1.5") + @Test + void getDouble_environmentVariable() { + assertDouble(1.5); + } + + @Test + void getDouble_none() { + assertDouble(null); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "0.0") + @Test + void getDouble_zero() { + assertDouble(0.0); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "-42.5") + @Test + void getDouble_negative() { + assertDouble(-42.5); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "42") + @Test + void getDouble_integerValue() { + assertDouble(42.0); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "1.23e10") + @Test + void getDouble_scientificNotation() { + assertDouble(1.23e10); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "Infinity") + @Test + void getDouble_infinity() { + assertDouble(Double.POSITIVE_INFINITY); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "-Infinity") + @Test + void getDouble_negativeInfinity() { + assertDouble(Double.NEGATIVE_INFINITY); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "NaN") + @Test + void getDouble_nan() { + assertThat( + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig() + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getDouble("double")) + .isNaN(); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "invalid") + @Test + void getDouble_invalidValue() { + assertDouble(null); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "") + @Test + void getDouble_emptyString() { + assertDouble(null); + } + + private static void assertDouble(@Nullable Double expected) { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getDouble("double")) + .isEqualTo(expected); + } + + @Test + void getStructuredList_returnsNull() { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getStructuredList("list")) + .isNull(); + } + + @Test + void getPropertyKeys_returnsEmptySet() { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat(config.getPropertyKeys()).isEmpty(); + } + + @SetSystemProperty( + key = "otel.instrumentation.experimental.test-feature.property", + value = "experimental_value") + @Test + void getStructured_developmentSuffix() { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test_feature/development") + .getString("property")) + .isEqualTo("experimental_value"); + } + + @SetSystemProperty(key = "otel.instrumentation.test-feature.property", value = "dash_value") + @Test + void getStructured_underscoreToDash() { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test_feature") + .getString("property")) + .isEqualTo("dash_value"); + } + + @SetSystemProperty(key = "otel.instrumentation.nested.path.property", value = "nested_value") + @Test + void getStructured_nestedPath() { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("nested") + .getStructured("path") + .getString("property")) + .isEqualTo("nested_value"); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.string", value = "") + @Test + void getString_emptyString() { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getString("string")) + .isEmpty(); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.string", value = " whitespace ") + @Test + void getString_withWhitespace() { + DeclarativeConfigProperties config = + SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + assertThat( + config + .getStructured("java") + .getStructured("test") + .getStructured("property") + .getString("string")) + .isEqualTo(" whitespace "); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "false") + @Test + void getBoolean_false() { + assertBoolean(false); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "TRUE") + @Test + void getBoolean_uppercase() { + assertBoolean(true); + } + + @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "False") + @Test + void getBoolean_mixedCase() { + assertBoolean(false); + } } From f49d942f16c1b63e382a77f7ea65962f009210e9 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 16 Dec 2025 09:32:12 +0100 Subject: [PATCH 08/40] fix --- CHANGELOG.md | 4 ++-- .../v1_11/autoconfigure/TracingRequestHandler.java | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87b50ea01989..c7746e597d26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,14 @@ ## Unreleased -## Version 2.23.0 (2025-12-13) - ### ⚠️ Breaking Changes - Rename `otel.experimental.javascript-snippet` to `otel.instrumentation.servlet.experimental.javascript-snippet` to follow naming conventions ([#15339](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/15339)) +## Version 2.23.0 (2025-12-13) + ### ⚠️ Breaking Changes - ActiveMQ Classic JMX metrics: rename attributes and metrics to align diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java index 24887689769a..3a0c818ed135 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java @@ -30,16 +30,17 @@ private static RequestHandler2 buildDelegate(OpenTelemetry openTelemetry) { DeclarativeConfigProperties java = DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()); DeclarativeConfigProperties awsSdk = java.getStructured("aws_sdk", empty()); - + DeclarativeConfigProperties messaging = java.getStructured("messaging", empty()); return AwsSdkTelemetry.builder(openTelemetry) .setCaptureExperimentalSpanAttributes( awsSdk.getBoolean("span_attributes/development", false)) .setMessagingReceiveTelemetryEnabled( - awsSdk.getBoolean("messaging.receive_telemetry/development", false)) + messaging + .getStructured("receive_telemetry/development", empty()) + .getBoolean("enabled", false)) .setCapturedHeaders( Optional.ofNullable( - java.getStructured("messaging", empty()) - .getScalarList("capture_headers/development", String.class)) + messaging.getScalarList("capture_headers/development", String.class)) .orElse(emptyList())) .build() .newRequestHandler(); From fbb4477b596aab0318a3902c1045ca81cf8c39a9 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 16 Dec 2025 10:00:25 +0100 Subject: [PATCH 09/40] fix --- .../DeprecatedConfigProperties.java | 29 +++++++++++ .../api/instrumenter/InstrumenterBuilder.java | 33 +++++++++--- .../internal/DeprecatedConfigProperties.java | 50 ------------------- 3 files changed, 56 insertions(+), 56 deletions(-) create mode 100644 instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java delete mode 100644 instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/DeprecatedConfigProperties.java diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java new file mode 100644 index 000000000000..1e99d67037e1 --- /dev/null +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.instrumenter; + +import static java.util.logging.Level.WARNING; + +import java.util.logging.Logger; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +@SuppressWarnings("unused") +final class DeprecatedConfigProperties { + + private static final Logger logger = Logger.getLogger(DeprecatedConfigProperties.class.getName()); + + static void warnDeprecatedKeyUsed(String deprecatedPropertyName, String newPropertyName) { + logger.log( + WARNING, + "Deprecated property \"{0}\" was used; use the \"{1}\" property instead", + new Object[] {deprecatedPropertyName, newPropertyName}); + } + + private DeprecatedConfigProperties() {} +} diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java index 1cae6b78a1a5..332a173951fc 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.api.instrumenter; import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; +import static io.opentelemetry.instrumentation.api.instrumenter.DeprecatedConfigProperties.warnDeprecatedKeyUsed; import static java.util.Objects.requireNonNull; import static java.util.logging.Level.WARNING; @@ -393,21 +394,37 @@ SpanSuppressor buildSpanSuppressor() { @Nullable private String getSpanSuppressionStrategy() { + String key = "otel.instrumentation.common.experimental.span-suppression-strategy"; + String deprecatedKey = "otel.instrumentation.experimental.span-suppression-strategy"; // otel.instrumentation.experimental.* doesn't fit the usual pattern of configuration properties // for instrumentations, so we need to handle both declarative and non-declarative configs here - if (isDeclarativeConfig(openTelemetry)) { + if (maybeDeclarativeConfig(openTelemetry)) { DeclarativeConfigProperties instrumentationConfig = ((ExtendedOpenTelemetry) openTelemetry).getConfigProvider().getInstrumentationConfig(); if (instrumentationConfig == null) { return null; } + String value = + instrumentationConfig + .getStructured("java", empty()) + .getStructured("common", empty()) + .getString("span_suppression_strategy/development"); + if (value != null) { + return value; + } + warnDeprecatedKeyUsed(deprecatedKey, key); + return instrumentationConfig .getStructured("java", empty()) - .getStructured("common", empty()) .getString("span_suppression_strategy/development"); } else { - return ConfigPropertiesUtil.getString( - "otel.instrumentation.experimental.span-suppression-strategy"); + String value = ConfigPropertiesUtil.getString(key); + if (value != null) { + return value; + } + warnDeprecatedKeyUsed(deprecatedKey, key); + + return ConfigPropertiesUtil.getString(deprecatedKey); } } @@ -488,8 +505,12 @@ public void setSpanStatusExtractorCustomizer( } } - /** Returns true if the given OpenTelemetry instance supports Declarative Config. */ - private static boolean isDeclarativeConfig(OpenTelemetry openTelemetry) { + /** + * Returns true if the current classpath supports declarative config and the instance may support + * declarative config (the agent implements ExtendedOpenTelemetry even when declarative config + * isn't used). + */ + private static boolean maybeDeclarativeConfig(OpenTelemetry openTelemetry) { return supportsDeclarativeConfig && openTelemetry instanceof ExtendedOpenTelemetry; } diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/DeprecatedConfigProperties.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/DeprecatedConfigProperties.java deleted file mode 100644 index 9e2cf4cbf3cb..000000000000 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/DeprecatedConfigProperties.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.api.internal; - -import static java.util.Collections.emptyList; -import static java.util.logging.Level.WARNING; - -import java.util.List; -import java.util.logging.Logger; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -@SuppressWarnings("unused") -public final class DeprecatedConfigProperties { - - private static final Logger logger = Logger.getLogger(DeprecatedConfigProperties.class.getName()); - - public static boolean getBoolean( - String deprecatedPropertyName, String newPropertyName, boolean defaultValue) { - - warnIfUsed(deprecatedPropertyName, newPropertyName); - - boolean value = ConfigPropertiesUtil.getBoolean(deprecatedPropertyName, defaultValue); - return ConfigPropertiesUtil.getBoolean(newPropertyName, value); - } - - public static List getList(String deprecatedPropertyName, String newPropertyName) { - - warnIfUsed(deprecatedPropertyName, newPropertyName); - - List value = ConfigPropertiesUtil.getList(deprecatedPropertyName, emptyList()); - return ConfigPropertiesUtil.getList(newPropertyName, value); - } - - private static void warnIfUsed(String deprecatedPropertyName, String newPropertyName) { - if (ConfigPropertiesUtil.getString(deprecatedPropertyName) != null) { - logger.log( - WARNING, - "Deprecated property \"{0}\" was used; use the \"{1}\" property instead", - new Object[] {deprecatedPropertyName, newPropertyName}); - } - } - - private DeprecatedConfigProperties() {} -} From 15b9f2639eb2e7c741635d13c6166bf9e9ab8883 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 16 Dec 2025 10:10:43 +0100 Subject: [PATCH 10/40] fix --- ...stemPropertiesBackedDeclarativeConfigPropertiesTest.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java index 8d895982f21b..18f45e1f669e 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java @@ -444,11 +444,7 @@ void getStructured_developmentSuffix() { void getStructured_underscoreToDash() { DeclarativeConfigProperties config = SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test_feature") - .getString("property")) + assertThat(config.getStructured("java").getStructured("test_feature").getString("property")) .isEqualTo("dash_value"); } From ea460af74de832c180880ed074846347b3787b4d Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 16 Dec 2025 10:29:00 +0100 Subject: [PATCH 11/40] fix --- .../DeprecatedConfigProperties.java | 16 +++++++++- .../api/instrumenter/InstrumenterBuilder.java | 32 ++++++++----------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java index 1e99d67037e1..04ce8ece2ec9 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java @@ -8,6 +8,7 @@ import static java.util.logging.Level.WARNING; import java.util.logging.Logger; +import javax.annotation.Nullable; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at @@ -18,11 +19,24 @@ final class DeprecatedConfigProperties { private static final Logger logger = Logger.getLogger(DeprecatedConfigProperties.class.getName()); - static void warnDeprecatedKeyUsed(String deprecatedPropertyName, String newPropertyName) { + static String warnIfUsed( + String deprecatedPropertyName, + @Nullable String deprecatedPropertyValue, + String newPropertyName, + @Nullable String newPropertyValue) { + if (newPropertyValue != null) { + return newPropertyValue; + } + + if (deprecatedPropertyValue == null) { + return null; + } + logger.log( WARNING, "Deprecated property \"{0}\" was used; use the \"{1}\" property instead", new Object[] {deprecatedPropertyName, newPropertyName}); + return deprecatedPropertyValue; } private DeprecatedConfigProperties() {} diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java index 332a173951fc..b8830dc2ed22 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java @@ -6,7 +6,7 @@ package io.opentelemetry.instrumentation.api.instrumenter; import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; -import static io.opentelemetry.instrumentation.api.instrumenter.DeprecatedConfigProperties.warnDeprecatedKeyUsed; +import static io.opentelemetry.instrumentation.api.instrumenter.DeprecatedConfigProperties.warnIfUsed; import static java.util.Objects.requireNonNull; import static java.util.logging.Level.WARNING; @@ -404,27 +404,23 @@ private String getSpanSuppressionStrategy() { if (instrumentationConfig == null) { return null; } - String value = + + return warnIfUsed( + deprecatedKey, + instrumentationConfig + .getStructured("java", empty()) + .getString("span_suppression_strategy/development"), + key, instrumentationConfig .getStructured("java", empty()) .getStructured("common", empty()) - .getString("span_suppression_strategy/development"); - if (value != null) { - return value; - } - warnDeprecatedKeyUsed(deprecatedKey, key); - - return instrumentationConfig - .getStructured("java", empty()) - .getString("span_suppression_strategy/development"); + .getString("span_suppression_strategy/development")); } else { - String value = ConfigPropertiesUtil.getString(key); - if (value != null) { - return value; - } - warnDeprecatedKeyUsed(deprecatedKey, key); - - return ConfigPropertiesUtil.getString(deprecatedKey); + return warnIfUsed( + deprecatedKey, + ConfigPropertiesUtil.getString(deprecatedKey), + key, + ConfigPropertiesUtil.getString(key)); } } From 3862072a1c82aa0b96fdd3e1369e44d145220cb2 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 16 Dec 2025 11:07:12 +0100 Subject: [PATCH 12/40] fix --- .../api/instrumenter/DeprecatedConfigProperties.java | 1 + .../api/instrumenter/InstrumenterBuilder.java | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java index 04ce8ece2ec9..90c9e03c2744 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java @@ -19,6 +19,7 @@ final class DeprecatedConfigProperties { private static final Logger logger = Logger.getLogger(DeprecatedConfigProperties.class.getName()); + @Nullable static String warnIfUsed( String deprecatedPropertyName, @Nullable String deprecatedPropertyValue, diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java index b8830dc2ed22..5b95eb2bce4f 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java @@ -6,7 +6,6 @@ package io.opentelemetry.instrumentation.api.instrumenter; import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; -import static io.opentelemetry.instrumentation.api.instrumenter.DeprecatedConfigProperties.warnIfUsed; import static java.util.Objects.requireNonNull; import static java.util.logging.Level.WARNING; @@ -396,8 +395,7 @@ SpanSuppressor buildSpanSuppressor() { private String getSpanSuppressionStrategy() { String key = "otel.instrumentation.common.experimental.span-suppression-strategy"; String deprecatedKey = "otel.instrumentation.experimental.span-suppression-strategy"; - // otel.instrumentation.experimental.* doesn't fit the usual pattern of configuration properties - // for instrumentations, so we need to handle both declarative and non-declarative configs here + // we cannot use DeclarativeConfigUtil here because it's not available in instrumentation-api if (maybeDeclarativeConfig(openTelemetry)) { DeclarativeConfigProperties instrumentationConfig = ((ExtendedOpenTelemetry) openTelemetry).getConfigProvider().getInstrumentationConfig(); @@ -405,7 +403,7 @@ private String getSpanSuppressionStrategy() { return null; } - return warnIfUsed( + return DeprecatedConfigProperties.warnIfUsed( deprecatedKey, instrumentationConfig .getStructured("java", empty()) @@ -416,7 +414,7 @@ private String getSpanSuppressionStrategy() { .getStructured("common", empty()) .getString("span_suppression_strategy/development")); } else { - return warnIfUsed( + return DeprecatedConfigProperties.warnIfUsed( deprecatedKey, ConfigPropertiesUtil.getString(deprecatedKey), key, From da3cffb4bd72f71c7d2e99eefe4faf594f79e3d9 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 18 Dec 2025 14:09:35 +0100 Subject: [PATCH 13/40] rename to LibraryConfigUtil to make a clear distinction to DeclarativeConfigUtil --- .../config/internal/LibraryConfigUtil.java | 50 +++++++++++++++++++ ...tiesBackedDeclarativeConfigProperties.java | 2 +- .../autoconfigure/TracingRequestHandler.java | 18 +++---- .../v2_2/internal/AwsSdkTelemetryFactory.java | 20 ++++---- .../jdbc/OpenTelemetryDriver.java | 15 ++---- .../internal/JdbcInstrumenterFactory.java | 14 ++---- .../v2_6/TracingConsumerInterceptor.java | 14 ++---- .../v2_6/TracingProducerInterceptor.java | 11 ++-- .../OpenTelemetryContextDataProvider.java | 8 ++- .../v2_17/internal/ContextDataKeys.java | 9 ++-- .../servlet/ExperimentalSnippetHolder.java | 6 +-- 11 files changed, 94 insertions(+), 73 deletions(-) create mode 100644 instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LibraryConfigUtil.java diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LibraryConfigUtil.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LibraryConfigUtil.java new file mode 100644 index 000000000000..45827b388376 --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LibraryConfigUtil.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.config.internal; + +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.ExtendedOpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class LibraryConfigUtil { + + /** + * Retrieves structured configuration for the given instrumentation name. If no configuration is + * found, the provided default value is returned. + * + *

The configuration is retrieved from the provided OpenTelemetry instance. If the instance + * implements {@link ExtendedOpenTelemetry}, the configuration is fetched from its config + * provider. Otherwise, the configuration is obtained from system properties or environment + * variables. + * + *

This method is only intended to be used for library instrumentation. For agent + * instrumentation, use {} + * + * @param openTelemetry the OpenTelemetry instance + * @param name the name of the instrumentation + * @return the structured configuration for the given instrumentation name or the default value + */ + public static ExtendedDeclarativeConfigProperties getJavaInstrumentationConfig( + OpenTelemetry openTelemetry, String name) { + + DeclarativeConfigProperties instrumentationConfig = + openTelemetry instanceof ExtendedOpenTelemetry + ? ((ExtendedOpenTelemetry) openTelemetry).getConfigProvider().getInstrumentationConfig() + : SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); + if (instrumentationConfig == null) { + return new ExtendedDeclarativeConfigProperties(empty()); + } + return new ExtendedDeclarativeConfigProperties(instrumentationConfig).get("java").get(name); + } + + private LibraryConfigUtil() {} +} diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java index 576c3d948283..bfd6846dcf49 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java @@ -30,7 +30,7 @@ final class SystemPropertiesBackedDeclarativeConfigProperties private final List path; - public static DeclarativeConfigProperties createInstrumentationConfig() { + static DeclarativeConfigProperties createInstrumentationConfig() { return new SystemPropertiesBackedDeclarativeConfigProperties(Collections.emptyList()); } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java index 3a0c818ed135..d223fe0ab60f 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java @@ -5,7 +5,6 @@ package io.opentelemetry.instrumentation.awssdk.v1_11.autoconfigure; -import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static java.util.Collections.emptyList; import com.amazonaws.AmazonWebServiceRequest; @@ -14,8 +13,8 @@ import com.amazonaws.handlers.RequestHandler2; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; import io.opentelemetry.instrumentation.awssdk.v1_11.AwsSdkTelemetry; import java.util.Optional; @@ -27,17 +26,14 @@ public class TracingRequestHandler extends RequestHandler2 { private static final RequestHandler2 DELEGATE = buildDelegate(GlobalOpenTelemetry.get()); private static RequestHandler2 buildDelegate(OpenTelemetry openTelemetry) { - DeclarativeConfigProperties java = - DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()); - DeclarativeConfigProperties awsSdk = java.getStructured("aws_sdk", empty()); - DeclarativeConfigProperties messaging = java.getStructured("messaging", empty()); + ExtendedDeclarativeConfigProperties messaging = + LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "messaging"); return AwsSdkTelemetry.builder(openTelemetry) .setCaptureExperimentalSpanAttributes( - awsSdk.getBoolean("span_attributes/development", false)) + LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "aws_sdk") + .getBoolean("span_attributes/development", false)) .setMessagingReceiveTelemetryEnabled( - messaging - .getStructured("receive_telemetry/development", empty()) - .getBoolean("enabled", false)) + messaging.get("receive_telemetry/development").getBoolean("enabled", false)) .setCapturedHeaders( Optional.ofNullable( messaging.getScalarList("capture_headers/development", String.class)) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java index 7d0632b60590..17e824ce0c7c 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java @@ -5,13 +5,12 @@ package io.opentelemetry.instrumentation.awssdk.v2_2.internal; -import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static java.util.Collections.emptyList; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; /** @@ -22,10 +21,10 @@ public final class AwsSdkTelemetryFactory { public static AwsSdkTelemetry telemetry() { OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); - DeclarativeConfigProperties java = - DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()); - DeclarativeConfigProperties awsSdk = java.getStructured("aws_sdk", empty()); - DeclarativeConfigProperties messaging = java.getStructured("messaging", empty()); + ExtendedDeclarativeConfigProperties awsSdk = + LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "aws_sdk"); + ExtendedDeclarativeConfigProperties messaging = + LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "messaging"); return AwsSdkTelemetry.builder(openTelemetry) .setCapturedHeaders( @@ -33,15 +32,14 @@ public static AwsSdkTelemetry telemetry() { .setCaptureExperimentalSpanAttributes( awsSdk.getBoolean("span_attributes/development", false)) .setMessagingReceiveTelemetryEnabled( - messaging - .getStructured("receive_telemetry/development", empty()) - .getBoolean("enabled", false)) + messaging.get("receive_telemetry/development").getBoolean("enabled", false)) .setUseConfiguredPropagatorForMessaging( awsSdk.getBoolean("use_propagator_for_messaging/development", false)) .setRecordIndividualHttpError( awsSdk.getBoolean("record_individual_http_error/development", false)) .setGenaiCaptureMessageContent( - java.getStructured("genai", empty()).getBoolean("capture_message_content", false)) + LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "genai") + .getBoolean("capture_message_content", false)) .build(); } diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java index 20dfa314ee3f..655c173f8755 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java @@ -20,12 +20,10 @@ package io.opentelemetry.instrumentation.jdbc; -import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static io.opentelemetry.instrumentation.jdbc.internal.JdbcInstrumenterFactory.INSTRUMENTATION_NAME; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.SqlCommenter; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; @@ -66,18 +64,15 @@ public final class OpenTelemetryDriver implements Driver { private static final List DRIVER_CANDIDATES = new CopyOnWriteArrayList<>(); private static SqlCommenter getSqlCommenter(OpenTelemetry openTelemetry) { - DeclarativeConfigProperties java = - DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()); - boolean defaultValue = - java.getStructured("common", empty()) - .getStructured("db_sqlcommenter/development", empty()) + LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "common") + .get("db_sqlcommenter/development") .getBoolean("enabled", false); return SqlCommenter.builder() .setEnabled( - java.getStructured("jdbc", empty()) - .getStructured("sqlcommenter/development", empty()) + LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") + .get("sqlcommenter/development") .getBoolean("enabled", defaultValue)) .build(); } diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java index fe6d1547523b..9b6863b1d4f0 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java @@ -5,11 +5,10 @@ package io.opentelemetry.instrumentation.jdbc.internal; -import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static java.util.Collections.emptyList; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -30,8 +29,7 @@ public final class JdbcInstrumenterFactory { public static final String INSTRUMENTATION_NAME = "io.opentelemetry.jdbc"; public static boolean captureQueryParameters(OpenTelemetry openTelemetry) { - return DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()) - .getStructured("jdbc", empty()) + return LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") .getBoolean("capture_query_parameters/development", false); } @@ -43,9 +41,8 @@ public static Instrumenter createStatementInstrumenter( static Instrumenter createStatementInstrumenter( OpenTelemetry openTelemetry, boolean captureQueryParameters) { boolean statementSanitizationEnabled = - DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()) - .getStructured("common", empty()) - .getStructured("db_statement_sanitizer", empty()) + LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "common") + .get("db_statement_sanitizer") .getBoolean("enabled", true); return createStatementInstrumenter( openTelemetry, emptyList(), true, statementSanitizationEnabled, captureQueryParameters); @@ -95,8 +92,7 @@ public static Instrumenter createDataSourceInstrumenter( public static Instrumenter createTransactionInstrumenter( OpenTelemetry openTelemetry) { boolean enabled = - DeclarativeConfigUtil.getStructured(openTelemetry, "java", empty()) - .getStructured("jdbc", empty()) + LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") .getBoolean("transaction/development", false); return createTransactionInstrumenter(openTelemetry, enabled); } diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java index 49857a92fc29..100ef7937b55 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java @@ -5,15 +5,14 @@ package io.opentelemetry.instrumentation.kafkaclients.v2_6; -import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static java.util.Collections.emptyList; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; import io.opentelemetry.instrumentation.api.internal.Timer; import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContext; import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContextUtil; @@ -40,16 +39,13 @@ public class TracingConsumerInterceptor implements ConsumerInterceptor implements ProducerInterceptor Date: Sat, 20 Dec 2025 10:15:20 +0100 Subject: [PATCH 14/40] fix --- .../javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java index 6bc97a2337db..ef59bd9d7d3c 100644 --- a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java +++ b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java @@ -25,7 +25,6 @@ public class ExperimentalSnippetHolder { private static String getSnippetSetting() { String snippet = DeclarativeConfigUtil.get(GlobalOpenTelemetry.get()) - .get("java") .get("servlet") .getString("javascript-snippet/development", null); // Can remove deprecated fallback in 2.24.0 From e410d80f58ff98b8b619ebb94a5fba5ffd92bd64 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sat, 20 Dec 2025 10:17:12 +0100 Subject: [PATCH 15/40] fix --- .../javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java index ef59bd9d7d3c..ae002f4fce98 100644 --- a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java +++ b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java @@ -26,7 +26,7 @@ private static String getSnippetSetting() { String snippet = DeclarativeConfigUtil.get(GlobalOpenTelemetry.get()) .get("servlet") - .getString("javascript-snippet/development", null); + .getString("javascript_snippet/development", null); // Can remove deprecated fallback in 2.24.0 if (snippet != null) { return snippet; From bfd1ad1ac814136d4e4a92be37bdf565a87543b4 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sun, 21 Dec 2025 00:09:26 +0100 Subject: [PATCH 16/40] pr review --- ...Util.java => LegacyLibraryConfigUtil.java} | 20 +++++++++++++------ .../autoconfigure/TracingRequestHandler.java | 6 +++--- .../v2_2/internal/AwsSdkTelemetryFactory.java | 8 ++++---- .../jdbc/OpenTelemetryDriver.java | 6 +++--- .../internal/JdbcInstrumenterFactory.java | 8 ++++---- .../v2_6/TracingConsumerInterceptor.java | 4 ++-- .../v2_6/TracingProducerInterceptor.java | 4 ++-- .../OpenTelemetryContextDataProvider.java | 4 ++-- .../v2_17/internal/ContextDataKeys.java | 4 ++-- 9 files changed, 36 insertions(+), 28 deletions(-) rename instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/{LibraryConfigUtil.java => LegacyLibraryConfigUtil.java} (67%) diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LibraryConfigUtil.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LegacyLibraryConfigUtil.java similarity index 67% rename from instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LibraryConfigUtil.java rename to instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LegacyLibraryConfigUtil.java index 45827b388376..fe86ed74ae8f 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LibraryConfigUtil.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LegacyLibraryConfigUtil.java @@ -12,10 +12,17 @@ import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; /** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. + * Configuration utility methods for library instrumentations that support both declarative + * configuration and system properties / environment variables. + * + *

This class is only intended to be used for existing library instrumentations to not break + * backwards compatibility. New library instrumentations should directly use declarative + * configuration APIs via {@link DeclarativeConfigUtil}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. */ -public final class LibraryConfigUtil { +public final class LegacyLibraryConfigUtil { /** * Retrieves structured configuration for the given instrumentation name. If no configuration is @@ -26,8 +33,9 @@ public final class LibraryConfigUtil { * provider. Otherwise, the configuration is obtained from system properties or environment * variables. * - *

This method is only intended to be used for library instrumentation. For agent - * instrumentation, use {} + *

This method is only intended to be used for existing library instrumentations to not break + * backwards compatibility. New library instrumentations should directly use declarative + * configuration APIs via {@link DeclarativeConfigUtil}. * * @param openTelemetry the OpenTelemetry instance * @param name the name of the instrumentation @@ -46,5 +54,5 @@ public static ExtendedDeclarativeConfigProperties getJavaInstrumentationConfig( return new ExtendedDeclarativeConfigProperties(instrumentationConfig).get("java").get(name); } - private LibraryConfigUtil() {} + private LegacyLibraryConfigUtil() {} } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java index d223fe0ab60f..8e00316be3a7 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java @@ -14,7 +14,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; import io.opentelemetry.instrumentation.awssdk.v1_11.AwsSdkTelemetry; import java.util.Optional; @@ -27,10 +27,10 @@ public class TracingRequestHandler extends RequestHandler2 { private static RequestHandler2 buildDelegate(OpenTelemetry openTelemetry) { ExtendedDeclarativeConfigProperties messaging = - LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "messaging"); + LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "messaging"); return AwsSdkTelemetry.builder(openTelemetry) .setCaptureExperimentalSpanAttributes( - LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "aws_sdk") + LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "aws_sdk") .getBoolean("span_attributes/development", false)) .setMessagingReceiveTelemetryEnabled( messaging.get("receive_telemetry/development").getBoolean("enabled", false)) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java index 17e824ce0c7c..6b1fd7ed71d1 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java @@ -10,7 +10,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; /** @@ -22,9 +22,9 @@ public final class AwsSdkTelemetryFactory { public static AwsSdkTelemetry telemetry() { OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); ExtendedDeclarativeConfigProperties awsSdk = - LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "aws_sdk"); + LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "aws_sdk"); ExtendedDeclarativeConfigProperties messaging = - LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "messaging"); + LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "messaging"); return AwsSdkTelemetry.builder(openTelemetry) .setCapturedHeaders( @@ -38,7 +38,7 @@ public static AwsSdkTelemetry telemetry() { .setRecordIndividualHttpError( awsSdk.getBoolean("record_individual_http_error/development", false)) .setGenaiCaptureMessageContent( - LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "genai") + LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "genai") .getBoolean("capture_message_content", false)) .build(); } diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java index 655c173f8755..b5890b188d62 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java @@ -23,7 +23,7 @@ import static io.opentelemetry.instrumentation.jdbc.internal.JdbcInstrumenterFactory.INSTRUMENTATION_NAME; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.SqlCommenter; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; @@ -65,13 +65,13 @@ public final class OpenTelemetryDriver implements Driver { private static SqlCommenter getSqlCommenter(OpenTelemetry openTelemetry) { boolean defaultValue = - LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "common") + LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "common") .get("db_sqlcommenter/development") .getBoolean("enabled", false); return SqlCommenter.builder() .setEnabled( - LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") + LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") .get("sqlcommenter/development") .getBoolean("enabled", defaultValue)) .build(); diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java index 9b6863b1d4f0..b7e1c1de3029 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java @@ -8,7 +8,7 @@ import static java.util.Collections.emptyList; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -29,7 +29,7 @@ public final class JdbcInstrumenterFactory { public static final String INSTRUMENTATION_NAME = "io.opentelemetry.jdbc"; public static boolean captureQueryParameters(OpenTelemetry openTelemetry) { - return LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") + return LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") .getBoolean("capture_query_parameters/development", false); } @@ -41,7 +41,7 @@ public static Instrumenter createStatementInstrumenter( static Instrumenter createStatementInstrumenter( OpenTelemetry openTelemetry, boolean captureQueryParameters) { boolean statementSanitizationEnabled = - LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "common") + LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "common") .get("db_statement_sanitizer") .getBoolean("enabled", true); return createStatementInstrumenter( @@ -92,7 +92,7 @@ public static Instrumenter createDataSourceInstrumenter( public static Instrumenter createTransactionInstrumenter( OpenTelemetry openTelemetry) { boolean enabled = - LibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") + LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") .getBoolean("transaction/development", false); return createTransactionInstrumenter(openTelemetry, enabled); } diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java index 100ef7937b55..af29be863611 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java @@ -12,7 +12,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LibraryConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; import io.opentelemetry.instrumentation.api.internal.Timer; import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContext; import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContextUtil; @@ -40,7 +40,7 @@ public class TracingConsumerInterceptor implements ConsumerInterceptor implements ProducerInterceptor Date: Mon, 22 Dec 2025 07:18:51 +0100 Subject: [PATCH 17/40] use explicit fallback instead of LegacyLibraryConfigUtil.java --- .../build.gradle.kts | 8 - .../internal/LegacyLibraryConfigUtil.java | 58 -- ...tiesBackedDeclarativeConfigProperties.java | 180 ------- ...BackedDeclarativeConfigPropertiesTest.java | 510 ------------------ .../api/internal/ConfigPropertiesUtil.java | 49 +- .../api/internal/ConfigUtil.java | 81 --- .../internal/ConfigPropertiesUtilTest.java | 17 +- .../autoconfigure/TracingRequestHandler.java | 25 +- .../v2_2/internal/AwsSdkTelemetryFactory.java | 49 +- .../jdbc/OpenTelemetryDriver.java | 40 +- .../internal/JdbcInstrumenterFactory.java | 24 +- .../v2_6/TracingConsumerInterceptor.java | 18 +- .../v2_6/TracingProducerInterceptor.java | 13 +- .../OpenTelemetryContextDataProvider.java | 10 +- .../v2_17/internal/ContextDataKeys.java | 25 +- .../servlet/ExperimentalSnippetHolder.java | 30 +- 16 files changed, 211 insertions(+), 926 deletions(-) delete mode 100644 instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LegacyLibraryConfigUtil.java delete mode 100644 instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java delete mode 100644 instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java delete mode 100644 instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigUtil.java diff --git a/instrumentation-api-incubator/build.gradle.kts b/instrumentation-api-incubator/build.gradle.kts index f970c702aaf6..3db18fcaf65c 100644 --- a/instrumentation-api-incubator/build.gradle.kts +++ b/instrumentation-api-incubator/build.gradle.kts @@ -24,7 +24,6 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-sdk") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating") - testImplementation("org.junit-pioneer:junit-pioneer") } val jflexSourceDir = layout.projectDirectory.dir("src/main/jflex") @@ -99,11 +98,4 @@ tasks { check { dependsOn(testStableSemconv, testBothSemconv) } - - withType().configureEach { - // required on jdk17 for junit pioneer - jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") - jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED") - jvmArgs("-XX:+IgnoreUnrecognizedVMOptions") - } } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LegacyLibraryConfigUtil.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LegacyLibraryConfigUtil.java deleted file mode 100644 index fe86ed74ae8f..000000000000 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/LegacyLibraryConfigUtil.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.api.incubator.config.internal; - -import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.ExtendedOpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; - -/** - * Configuration utility methods for library instrumentations that support both declarative - * configuration and system properties / environment variables. - * - *

This class is only intended to be used for existing library instrumentations to not break - * backwards compatibility. New library instrumentations should directly use declarative - * configuration APIs via {@link DeclarativeConfigUtil}. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public final class LegacyLibraryConfigUtil { - - /** - * Retrieves structured configuration for the given instrumentation name. If no configuration is - * found, the provided default value is returned. - * - *

The configuration is retrieved from the provided OpenTelemetry instance. If the instance - * implements {@link ExtendedOpenTelemetry}, the configuration is fetched from its config - * provider. Otherwise, the configuration is obtained from system properties or environment - * variables. - * - *

This method is only intended to be used for existing library instrumentations to not break - * backwards compatibility. New library instrumentations should directly use declarative - * configuration APIs via {@link DeclarativeConfigUtil}. - * - * @param openTelemetry the OpenTelemetry instance - * @param name the name of the instrumentation - * @return the structured configuration for the given instrumentation name or the default value - */ - public static ExtendedDeclarativeConfigProperties getJavaInstrumentationConfig( - OpenTelemetry openTelemetry, String name) { - - DeclarativeConfigProperties instrumentationConfig = - openTelemetry instanceof ExtendedOpenTelemetry - ? ((ExtendedOpenTelemetry) openTelemetry).getConfigProvider().getInstrumentationConfig() - : SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - if (instrumentationConfig == null) { - return new ExtendedDeclarativeConfigProperties(empty()); - } - return new ExtendedDeclarativeConfigProperties(instrumentationConfig).get("java").get(name); - } - - private LegacyLibraryConfigUtil() {} -} diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java deleted file mode 100644 index bfd6846dcf49..000000000000 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigProperties.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.api.incubator.config.internal; - -import static java.util.Collections.emptySet; - -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.common.ComponentLoader; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import javax.annotation.Nullable; - -/** - * Implementation of {@link DeclarativeConfigProperties} backed by system properties and - * environmental variables. - * - *

It tracks the navigation path and only resolves to system properties at the leaf node when a - * value is actually requested. - */ -final class SystemPropertiesBackedDeclarativeConfigProperties - implements DeclarativeConfigProperties { - - private final List path; - - static DeclarativeConfigProperties createInstrumentationConfig() { - return new SystemPropertiesBackedDeclarativeConfigProperties(Collections.emptyList()); - } - - private SystemPropertiesBackedDeclarativeConfigProperties(List path) { - this.path = path; - } - - @Nullable - @Override - public String getString(String name) { - String fullPath = pathWithName(name); - return ConfigPropertiesUtil.getString(toPropertyKey(fullPath)); - } - - @Nullable - @Override - public Boolean getBoolean(String name) { - String value = getString(name); - return value == null ? null : Boolean.parseBoolean(value); - } - - @Nullable - @Override - public Integer getInt(String name) { - String strValue = getString(name); - if (strValue == null) { - return null; - } - try { - return Integer.parseInt(strValue); - } catch (NumberFormatException ignored) { - return null; - } - } - - @Nullable - @Override - public Long getLong(String name) { - String strValue = getString(name); - if (strValue == null) { - return null; - } - try { - return Long.parseLong(strValue); - } catch (NumberFormatException ignored) { - return null; - } - } - - @Nullable - @Override - public Double getDouble(String name) { - String strValue = getString(name); - if (strValue == null) { - return null; - } - try { - return Double.parseDouble(strValue); - } catch (NumberFormatException ignored) { - return null; - } - } - - /** - * Important: this method should return null if there is no structured child with the given name, - * but unfortunately that is not implementable on top of ConfigProperties. - * - *

This will be misleading if anyone is comparing the return value to null. - */ - @Override - public DeclarativeConfigProperties getStructured(String name) { - List newPath = new ArrayList<>(path); - newPath.add(name); - return new SystemPropertiesBackedDeclarativeConfigProperties(newPath); - } - - @Nullable - @Override - @SuppressWarnings("unchecked") // Safe because T is known to be String via scalarType check - public List getScalarList(String name, Class scalarType) { - if (scalarType != String.class) { - return null; - } - String value = getString(name); - return value == null ? null : (List) filterBlanksAndNulls(value.split(",")); - } - - @Nullable - @Override - public List getStructuredList(String name) { - return null; - } - - @Override - public Set getPropertyKeys() { - // this is not supported when using system properties based configuration - return emptySet(); - } - - @Override - public ComponentLoader getComponentLoader() { - throw new UnsupportedOperationException(); - } - - private String pathWithName(String name) { - if (path.isEmpty()) { - return name; - } - return String.join(".", path) + "." + name; - } - - private static String toPropertyKey(String fullPath) { - String translatedPath = translatePath(fullPath); - // Standard mapping - return "otel.instrumentation." + translatedPath; - } - - private static String translatePath(String path) { - StringBuilder result = new StringBuilder(); - for (String segment : path.split("\\.")) { - // Skip "java" segment - it doesn't exist in system properties - if ("java".equals(segment)) { - continue; - } - if (result.length() > 0) { - result.append("."); - } - result.append(translateName(segment)); - } - return result.toString(); - } - - private static String translateName(String name) { - if (name.endsWith("/development")) { - return "experimental." - + name.substring(0, name.length() - "/development".length()).replace('_', '-'); - } - return name.replace('_', '-'); - } - - private static List filterBlanksAndNulls(String[] values) { - return Arrays.stream(values) - .map(String::trim) - .filter(s -> !s.isEmpty()) - .collect(Collectors.toList()); - } -} diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java deleted file mode 100644 index 18f45e1f669e..000000000000 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/config/internal/SystemPropertiesBackedDeclarativeConfigPropertiesTest.java +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.api.incubator.config.internal; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import java.util.List; -import java.util.stream.Stream; -import javax.annotation.Nullable; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.junitpioneer.jupiter.SetEnvironmentVariable; -import org.junitpioneer.jupiter.SetSystemProperty; - -class SystemPropertiesBackedDeclarativeConfigPropertiesTest { - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_STRING", value = "env_value") - @SetSystemProperty(key = "otel.instrumentation.test.property.string", value = "sys_value") - @Test - void getString_systemProperty() { - assertString("sys_value"); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_STRING", value = "env_value") - @Test - void getString_environmentVariable() { - assertString("env_value"); - } - - @Test - void getString_none() { - assertString(null); - } - - private static void assertString(@Nullable String expected) { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getString("string")) - .isEqualTo(expected); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_BOOLEAN", value = "false") - @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "true") - @Test - void getBoolean_systemProperty() { - assertBoolean(true); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_BOOLEAN", value = "true") - @Test - void getBoolean_environmentVariable() { - assertBoolean(true); - } - - @Test - void getBoolean_none() { - assertBoolean(null); - } - - private static void assertBoolean(@Nullable Boolean expected) { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getBoolean("boolean")) - .isEqualTo(expected); - } - - @ParameterizedTest - @MethodSource("booleanValuesProvider") - @SuppressWarnings("unused") - void getBoolean_invalidValue(String value, @Nullable Boolean expected) { - // This test verifies behavior with invalid boolean values via system properties - assertThat(expected).isNull(); - } - - static Stream booleanValuesProvider() { - return Stream.of( - Arguments.of("invalid", null), Arguments.of("123", null), Arguments.of("", null)); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_LIST", value = "a,b,c") - @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = "x,y,z") - @Test - void getList_systemProperty() { - assertList(asList("x", "y", "z")); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_LIST", value = "a,b,c") - @Test - void getList_environmentVariable() { - assertList(asList("a", "b", "c")); - } - - @Test - void getList_none() { - assertList(null); - } - - private static void assertList(@Nullable List expected) { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getScalarList("list", String.class)) - .isEqualTo(expected); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = "a,b,c") - @Test - void getList_multipleValues() { - assertList(asList("a", "b", "c")); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = "single") - @Test - void getList_singleValue() { - assertList(singletonList("single")); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = "") - @Test - void getList_emptyString() { - assertList(emptyList()); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = " a , b , c ") - @Test - void getList_withWhitespace() { - assertList(asList("a", "b", "c")); - } - - @Test - void getList_unsupportedType() { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getScalarList("list", Integer.class)) - .isNull(); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = ",,a,,b,,") - @Test - void getList_multipleCommas() { - assertList(asList("a", "b")); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.list", value = " ") - @Test - void getList_onlyWhitespace() { - assertList(emptyList()); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_INT", value = "100") - @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "200") - @Test - void getInt_systemProperty() { - assertInt(200); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_INT", value = "100") - @Test - void getInt_environmentVariable() { - assertInt(100); - } - - @Test - void getInt_none() { - assertInt(null); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "0") - @Test - void getInt_zero() { - assertInt(0); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "-42") - @Test - void getInt_negative() { - assertInt(-42); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "2147483647") - @Test - void getInt_maxValue() { - assertInt(Integer.MAX_VALUE); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "-2147483648") - @Test - void getInt_minValue() { - assertInt(Integer.MIN_VALUE); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "invalid") - @Test - void getInt_invalidValue() { - assertInt(null); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "12.34") - @Test - void getInt_decimalValue() { - assertInt(null); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.int", value = "") - @Test - void getInt_emptyString() { - assertInt(null); - } - - private static void assertInt(@Nullable Integer expected) { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getInt("int")) - .isEqualTo(expected); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_LONG", value = "100") - @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "200") - @Test - void getLong_systemProperty() { - assertLong(200L); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_LONG", value = "100") - @Test - void getLong_environmentVariable() { - assertLong(100L); - } - - @Test - void getLong_none() { - assertLong(null); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "0") - @Test - void getLong_zero() { - assertLong(0L); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "-42") - @Test - void getLong_negative() { - assertLong(-42L); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "9223372036854775807") - @Test - void getLong_maxValue() { - assertLong(Long.MAX_VALUE); - } - - @SetSystemProperty( - key = "otel.instrumentation.test.property.long", - value = "-9223372036854775808") - @Test - void getLong_minValue() { - assertLong(Long.MIN_VALUE); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "invalid") - @Test - void getLong_invalidValue() { - assertLong(null); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.long", value = "") - @Test - void getLong_emptyString() { - assertLong(null); - } - - private static void assertLong(@Nullable Long expected) { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getLong("long")) - .isEqualTo(expected); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_DOUBLE", value = "1.5") - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "2.5") - @Test - void getDouble_systemProperty() { - assertDouble(2.5); - } - - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_DOUBLE", value = "1.5") - @Test - void getDouble_environmentVariable() { - assertDouble(1.5); - } - - @Test - void getDouble_none() { - assertDouble(null); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "0.0") - @Test - void getDouble_zero() { - assertDouble(0.0); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "-42.5") - @Test - void getDouble_negative() { - assertDouble(-42.5); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "42") - @Test - void getDouble_integerValue() { - assertDouble(42.0); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "1.23e10") - @Test - void getDouble_scientificNotation() { - assertDouble(1.23e10); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "Infinity") - @Test - void getDouble_infinity() { - assertDouble(Double.POSITIVE_INFINITY); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "-Infinity") - @Test - void getDouble_negativeInfinity() { - assertDouble(Double.NEGATIVE_INFINITY); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "NaN") - @Test - void getDouble_nan() { - assertThat( - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig() - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getDouble("double")) - .isNaN(); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "invalid") - @Test - void getDouble_invalidValue() { - assertDouble(null); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.double", value = "") - @Test - void getDouble_emptyString() { - assertDouble(null); - } - - private static void assertDouble(@Nullable Double expected) { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getDouble("double")) - .isEqualTo(expected); - } - - @Test - void getStructuredList_returnsNull() { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getStructuredList("list")) - .isNull(); - } - - @Test - void getPropertyKeys_returnsEmptySet() { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat(config.getPropertyKeys()).isEmpty(); - } - - @SetSystemProperty( - key = "otel.instrumentation.experimental.test-feature.property", - value = "experimental_value") - @Test - void getStructured_developmentSuffix() { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test_feature/development") - .getString("property")) - .isEqualTo("experimental_value"); - } - - @SetSystemProperty(key = "otel.instrumentation.test-feature.property", value = "dash_value") - @Test - void getStructured_underscoreToDash() { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat(config.getStructured("java").getStructured("test_feature").getString("property")) - .isEqualTo("dash_value"); - } - - @SetSystemProperty(key = "otel.instrumentation.nested.path.property", value = "nested_value") - @Test - void getStructured_nestedPath() { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("nested") - .getStructured("path") - .getString("property")) - .isEqualTo("nested_value"); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.string", value = "") - @Test - void getString_emptyString() { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getString("string")) - .isEmpty(); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.string", value = " whitespace ") - @Test - void getString_withWhitespace() { - DeclarativeConfigProperties config = - SystemPropertiesBackedDeclarativeConfigProperties.createInstrumentationConfig(); - assertThat( - config - .getStructured("java") - .getStructured("test") - .getStructured("property") - .getString("string")) - .isEqualTo(" whitespace "); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "false") - @Test - void getBoolean_false() { - assertBoolean(false); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "TRUE") - @Test - void getBoolean_uppercase() { - assertBoolean(true); - } - - @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "False") - @Test - void getBoolean_mixedCase() { - assertBoolean(false); - } -} diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java index 46a3b98f2b0c..810b1d7f1d92 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java @@ -5,6 +5,10 @@ package io.opentelemetry.instrumentation.api.internal; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; import javax.annotation.Nullable; /** @@ -53,7 +57,50 @@ public static int getInt(String propertyName, int defaultValue) { */ @Nullable public static String getString(String propertyName) { - return ConfigUtil.getString(ConfigUtil.normalizePropertyKey(propertyName)); + String value = System.getProperty(propertyName); + if (value != null) { + return value; + } + return System.getenv(toEnvVarName(propertyName)); + } + + /** + * Returns the string value of the given property name from system properties and environment + * variables, or the default value if not found. + * + *

It's recommended to use {@link io.opentelemetry.api.incubator.config.ConfigProvider} instead + * to support Declarative Config. + */ + public static String getString(String propertyName, String defaultValue) { + String strValue = getString(propertyName); + return strValue == null ? defaultValue : strValue; + } + + /** + * Returns the list of strings value of the given property name from system properties and + * environment variables, or the default value if not found. The property value is expected to be + * a comma-separated list. + * + *

It's recommended to use {@link io.opentelemetry.api.incubator.config.ConfigProvider} instead + * to support Declarative Config. + */ + public static List getList(String propertyName, List defaultValue) { + String value = getString(propertyName); + if (value == null) { + return defaultValue; + } + return filterBlanksAndNulls(value.split(",")); + } + + private static List filterBlanksAndNulls(String[] values) { + return Arrays.stream(values) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .collect(Collectors.toList()); + } + + private static String toEnvVarName(String propertyName) { + return propertyName.toUpperCase(Locale.ROOT).replace('-', '_').replace('.', '_'); } private ConfigPropertiesUtil() {} diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigUtil.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigUtil.java deleted file mode 100644 index 6dc734e1d9e4..000000000000 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigUtil.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.api.internal; - -import java.util.ConcurrentModificationException; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import javax.annotation.Nullable; - -/** - * Configuration utilities. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - * - *

Copied from SDK - * because some tests target an SDK version where this class does not exist. - */ -final class ConfigUtil { - - private ConfigUtil() {} - - /** - * Returns a copy of system properties which is safe to iterate over. - * - *

In java 8 and android environments, iterating through system properties may trigger {@link - * ConcurrentModificationException}. This method ensures callers can iterate safely without risk - * of exception. See https://github.com/open-telemetry/opentelemetry-java/issues/6732 for details. - */ - static Properties safeSystemProperties() { - return (Properties) System.getProperties().clone(); - } - - /** - * Return the system property or environment variable for the {@code key}. - * - *

Normalize the {@code key} using {@link #normalizePropertyKey(String)}. Match to system - * property keys also normalized with {@link #normalizePropertyKey(String)}. Match to environment - * variable keys normalized with {@link #normalizeEnvironmentVariableKey(String)}. System - * properties take priority over environment variables. - * - * @param key the property key - * @return the system property if not null, or the environment variable if not null, or {@code - * null} - */ - @Nullable - static String getString(String key) { - String normalizedKey = normalizePropertyKey(key); - - for (Map.Entry entry : safeSystemProperties().entrySet()) { - if (normalizedKey.equals(normalizePropertyKey(entry.getKey().toString()))) { - return entry.getValue().toString(); - } - } - - for (Map.Entry entry : System.getenv().entrySet()) { - if (normalizedKey.equals(normalizeEnvironmentVariableKey(entry.getKey()))) { - return entry.getValue(); - } - } - - return null; - } - - /** - * Normalize an environment variable key by converting to lower case and replacing "_" with ".". - */ - static String normalizeEnvironmentVariableKey(String key) { - return key.toLowerCase(Locale.ROOT).replace("_", "."); - } - - /** Normalize a property key by converting to lower case and replacing "-" with ".". */ - static String normalizePropertyKey(String key) { - return key.toLowerCase(Locale.ROOT).replace("-", "."); - } -} diff --git a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtilTest.java b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtilTest.java index 29e5082fd009..8a496322b6e0 100644 --- a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtilTest.java +++ b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtilTest.java @@ -55,26 +55,21 @@ void getInt_invalidNumber() { assertThat(ConfigPropertiesUtil.getInt("test.property.int", -1)).isEqualTo(-1); } - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_BOOLEAN", value = "false") - @SetSystemProperty(key = "otel.instrumentation.test.property.boolean", value = "true") + @SetEnvironmentVariable(key = "TEST_PROPERTY_BOOLEAN", value = "false") + @SetSystemProperty(key = "test.property.boolean", value = "true") @Test void getBoolean_systemProperty() { - assertBoolean(true); + assertThat(ConfigPropertiesUtil.getBoolean("test.property.boolean", false)).isTrue(); } - @SetEnvironmentVariable(key = "OTEL_INSTRUMENTATION_TEST_PROPERTY_BOOLEAN", value = "true") + @SetEnvironmentVariable(key = "TEST_PROPERTY_BOOLEAN", value = "true") @Test void getBoolean_environmentVariable() { - assertBoolean(true); + assertThat(ConfigPropertiesUtil.getBoolean("test.property.boolean", false)).isTrue(); } @Test void getBoolean_none() { - assertBoolean(false); - } - - private static void assertBoolean(boolean expected) { - assertThat(ConfigPropertiesUtil.getBoolean("otel.instrumentation.test.property.boolean", false)) - .isEqualTo(expected); + assertThat(ConfigPropertiesUtil.getBoolean("test.property.boolean", false)).isFalse(); } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java index 8e00316be3a7..a4c97846f757 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java @@ -13,8 +13,9 @@ import com.amazonaws.handlers.RequestHandler2; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; +import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.awssdk.v1_11.AwsSdkTelemetry; import java.util.Optional; @@ -27,17 +28,29 @@ public class TracingRequestHandler extends RequestHandler2 { private static RequestHandler2 buildDelegate(OpenTelemetry openTelemetry) { ExtendedDeclarativeConfigProperties messaging = - LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "messaging"); + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common").get("messaging"); return AwsSdkTelemetry.builder(openTelemetry) .setCaptureExperimentalSpanAttributes( - LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "aws_sdk") - .getBoolean("span_attributes/development", false)) + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "aws_sdk") + .getBoolean( + "span_attributes/development", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.aws-sdk.experimental-span-attributes", false))) .setMessagingReceiveTelemetryEnabled( - messaging.get("receive_telemetry/development").getBoolean("enabled", false)) + messaging + .get("receive_telemetry/development") + .getBoolean( + "enabled", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.messaging.experimental.receive-telemetry.enabled", + false))) .setCapturedHeaders( Optional.ofNullable( messaging.getScalarList("capture_headers/development", String.class)) - .orElse(emptyList())) + .orElse( + ConfigPropertiesUtil.getList( + "otel.instrumentation.messaging.experimental.capture-headers", + emptyList()))) .build() .newRequestHandler(); } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java index 6b1fd7ed71d1..dce41c9069a1 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java @@ -9,8 +9,9 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; +import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; /** @@ -21,25 +22,51 @@ public final class AwsSdkTelemetryFactory { public static AwsSdkTelemetry telemetry() { OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + ExtendedDeclarativeConfigProperties commonConfig = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common"); + ExtendedDeclarativeConfigProperties messaging = commonConfig.get("messaging"); + ExtendedDeclarativeConfigProperties awsSdk = - LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "aws_sdk"); - ExtendedDeclarativeConfigProperties messaging = - LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "messaging"); + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "aws_sdk"); return AwsSdkTelemetry.builder(openTelemetry) .setCapturedHeaders( - messaging.getScalarList("capture_headers/development", String.class, emptyList())) + messaging.getScalarList( + "capture_headers/development", + String.class, + ConfigPropertiesUtil.getList( + "otel.instrumentation.messaging.experimental.capture-headers", emptyList()))) .setCaptureExperimentalSpanAttributes( - awsSdk.getBoolean("span_attributes/development", false)) + awsSdk.getBoolean( + "span_attributes/development", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.aws-sdk.experimental-span-attributes", false))) .setMessagingReceiveTelemetryEnabled( - messaging.get("receive_telemetry/development").getBoolean("enabled", false)) + messaging + .get("receive_telemetry/development") + .getBoolean( + "enabled", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.messaging.experimental.receive-telemetry.enabled", + false))) .setUseConfiguredPropagatorForMessaging( - awsSdk.getBoolean("use_propagator_for_messaging/development", false)) + awsSdk.getBoolean( + "use_propagator_for_messaging/development", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging", + false))) .setRecordIndividualHttpError( - awsSdk.getBoolean("record_individual_http_error/development", false)) + awsSdk.getBoolean( + "record_individual_http_error/development", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.aws-sdk.experimental-record-individual-http-error", + false))) .setGenaiCaptureMessageContent( - LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "genai") - .getBoolean("capture_message_content", false)) + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "genai") + .getBoolean( + "capture_message_content", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.genai.capture-message-content", false))) .build(); } diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java index b5890b188d62..3ca365874ec0 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java @@ -23,9 +23,10 @@ import static io.opentelemetry.instrumentation.jdbc.internal.JdbcInstrumenterFactory.INSTRUMENTATION_NAME; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.SqlCommenter; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; import io.opentelemetry.instrumentation.jdbc.internal.DbRequest; import io.opentelemetry.instrumentation.jdbc.internal.JdbcConnectionUrlParser; @@ -38,6 +39,7 @@ import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; @@ -45,6 +47,7 @@ import java.util.Properties; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; import java.util.logging.Logger; import javax.annotation.Nullable; @@ -62,19 +65,32 @@ public final class OpenTelemetryDriver implements Driver { private static final String URL_PREFIX = "jdbc:otel:"; private static final AtomicBoolean REGISTERED = new AtomicBoolean(); private static final List DRIVER_CANDIDATES = new CopyOnWriteArrayList<>(); + private static final List> SQL_COMMENTER_VALUE_PROVIDERS = + Arrays.asList( + openTelemetry -> + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "jdbc") + .get("sqlcommenter/development") + .getBoolean("enabled", false), + openTelemetry -> + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") + .get("db_sqlcommenter/development") + .getBoolean("enabled", false), + openTelemetry -> + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled", false), + openTelemetry -> + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.common.experimental.db-sqlcommenter.enabled", false)); private static SqlCommenter getSqlCommenter(OpenTelemetry openTelemetry) { - boolean defaultValue = - LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "common") - .get("db_sqlcommenter/development") - .getBoolean("enabled", false); - - return SqlCommenter.builder() - .setEnabled( - LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") - .get("sqlcommenter/development") - .getBoolean("enabled", defaultValue)) - .build(); + boolean value = false; + for (Function provider : SQL_COMMENTER_VALUE_PROVIDERS) { + value = provider.apply(openTelemetry); + if (value) { + break; + } + } + return SqlCommenter.builder().setEnabled(value).build(); } static { diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java index b7e1c1de3029..bc8b8d35b1d0 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java @@ -8,7 +8,7 @@ import static java.util.Collections.emptyList; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -17,6 +17,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; +import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.jdbc.internal.dbinfo.DbInfo; import java.util.List; import javax.sql.DataSource; @@ -29,8 +30,11 @@ public final class JdbcInstrumenterFactory { public static final String INSTRUMENTATION_NAME = "io.opentelemetry.jdbc"; public static boolean captureQueryParameters(OpenTelemetry openTelemetry) { - return LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") - .getBoolean("capture_query_parameters/development", false); + return DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "jdbc") + .getBoolean( + "capture_query_parameters/development", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.jdbc.experimental.capture-query-parameters", false)); } public static Instrumenter createStatementInstrumenter( @@ -41,9 +45,12 @@ public static Instrumenter createStatementInstrumenter( static Instrumenter createStatementInstrumenter( OpenTelemetry openTelemetry, boolean captureQueryParameters) { boolean statementSanitizationEnabled = - LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "common") + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") .get("db_statement_sanitizer") - .getBoolean("enabled", true); + .getBoolean( + "enabled", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.common.db-statement-sanitizer.enabled", true)); return createStatementInstrumenter( openTelemetry, emptyList(), true, statementSanitizationEnabled, captureQueryParameters); } @@ -92,8 +99,11 @@ public static Instrumenter createDataSourceInstrumenter( public static Instrumenter createTransactionInstrumenter( OpenTelemetry openTelemetry) { boolean enabled = - LegacyLibraryConfigUtil.getJavaInstrumentationConfig(openTelemetry, "jdbc") - .getBoolean("transaction/development", false); + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "jdbc") + .getBoolean( + "transaction/development", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.jdbc.experimental.transaction.enabled", false)); return createTransactionInstrumenter(openTelemetry, enabled); } diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java index af29be863611..ec0985243ff6 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java @@ -11,8 +11,9 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.LegacyLibraryConfigUtil; +import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.api.internal.Timer; import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContext; import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContextUtil; @@ -40,16 +41,25 @@ public class TracingConsumerInterceptor implements ConsumerInterceptor implements ProducerInterceptor Date: Mon, 22 Dec 2025 07:24:25 +0100 Subject: [PATCH 18/40] pr review --- .../DeprecatedConfigProperties.java | 44 ------------------- .../api/instrumenter/InstrumenterBuilder.java | 23 +++------- .../camel-2.20/javaagent/build.gradle.kts | 2 +- .../javaagent/tooling/AgentInstaller.java | 3 +- 4 files changed, 8 insertions(+), 64 deletions(-) delete mode 100644 instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java deleted file mode 100644 index 90c9e03c2744..000000000000 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/DeprecatedConfigProperties.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.api.instrumenter; - -import static java.util.logging.Level.WARNING; - -import java.util.logging.Logger; -import javax.annotation.Nullable; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -@SuppressWarnings("unused") -final class DeprecatedConfigProperties { - - private static final Logger logger = Logger.getLogger(DeprecatedConfigProperties.class.getName()); - - @Nullable - static String warnIfUsed( - String deprecatedPropertyName, - @Nullable String deprecatedPropertyValue, - String newPropertyName, - @Nullable String newPropertyValue) { - if (newPropertyValue != null) { - return newPropertyValue; - } - - if (deprecatedPropertyValue == null) { - return null; - } - - logger.log( - WARNING, - "Deprecated property \"{0}\" was used; use the \"{1}\" property instead", - new Object[] {deprecatedPropertyName, newPropertyName}); - return deprecatedPropertyValue; - } - - private DeprecatedConfigProperties() {} -} diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java index 5b95eb2bce4f..60cfb078f36a 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java @@ -393,8 +393,6 @@ SpanSuppressor buildSpanSuppressor() { @Nullable private String getSpanSuppressionStrategy() { - String key = "otel.instrumentation.common.experimental.span-suppression-strategy"; - String deprecatedKey = "otel.instrumentation.experimental.span-suppression-strategy"; // we cannot use DeclarativeConfigUtil here because it's not available in instrumentation-api if (maybeDeclarativeConfig(openTelemetry)) { DeclarativeConfigProperties instrumentationConfig = @@ -403,22 +401,13 @@ private String getSpanSuppressionStrategy() { return null; } - return DeprecatedConfigProperties.warnIfUsed( - deprecatedKey, - instrumentationConfig - .getStructured("java", empty()) - .getString("span_suppression_strategy/development"), - key, - instrumentationConfig - .getStructured("java", empty()) - .getStructured("common", empty()) - .getString("span_suppression_strategy/development")); + return instrumentationConfig + .getStructured("java", empty()) + .getStructured("common", empty()) + .getString("span_suppression_strategy/development"); } else { - return DeprecatedConfigProperties.warnIfUsed( - deprecatedKey, - ConfigPropertiesUtil.getString(deprecatedKey), - key, - ConfigPropertiesUtil.getString(key)); + return ConfigPropertiesUtil.getString( + "otel.instrumentation.experimental.span-suppression-strategy"); } } diff --git a/instrumentation/camel-2.20/javaagent/build.gradle.kts b/instrumentation/camel-2.20/javaagent/build.gradle.kts index 9880343bb340..b1166690fa58 100644 --- a/instrumentation/camel-2.20/javaagent/build.gradle.kts +++ b/instrumentation/camel-2.20/javaagent/build.gradle.kts @@ -74,7 +74,7 @@ tasks { jvmArgs("-Dotel.instrumentation.aws-sdk.experimental-span-attributes=true") // TODO: fix camel instrumentation so that it uses semantic attributes extractors - jvmArgs("-Dotel.instrumentation.common.experimental.span-suppression-strategy=span-kind") + jvmArgs("-Dotel.instrumentation.experimental.span-suppression-strategy=span-kind") // required on jdk17 jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java index 3d15d1d3004f..400bd5922ea3 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java @@ -292,8 +292,7 @@ private static void installEarlyInstrumentation( } private static void copyNecessaryConfigToSystemProperties(ConfigProperties config) { - for (String property : - asList("otel.instrumentation.common.experimental.span-suppression-strategy")) { + for (String property : asList("otel.instrumentation.experimental.span-suppression-strategy")) { String value = config.getString(property); if (value != null) { System.setProperty(property, value); From a2d115c352e7979f96b87056be95c152ae7e7788 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 07:29:16 +0100 Subject: [PATCH 19/40] no breaking change anymore --- CHANGELOG.md | 6 ------ docs/advanced-configuration-options.md | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7746e597d26..ccb7a7d3abc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,6 @@ ## Unreleased -### ⚠️ Breaking Changes - -- Rename `otel.experimental.javascript-snippet` to - `otel.instrumentation.servlet.experimental.javascript-snippet` to follow naming conventions - ([#15339](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/15339)) - ## Version 2.23.0 (2025-12-13) ### ⚠️ Breaking Changes diff --git a/docs/advanced-configuration-options.md b/docs/advanced-configuration-options.md index 4ae0e075c5d1..688af9d07f13 100644 --- a/docs/advanced-configuration-options.md +++ b/docs/advanced-configuration-options.md @@ -46,8 +46,8 @@ We plan to integrate OpenTelemetry's own client-side monitoring solution by defa (see the [browser instrumentation proposal](https://github.com/open-telemetry/community/blob/main/projects/browser-phase-1.md)). | System property | Environment variable | Purpose | -|----------------------------------------------------------------|----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `otel.instrumentation.servlet.experimental.javascript-snippet` | `OTEL_INSTRUMENTATION_SERVLET_EXPERIMENTAL_JAVASCRIPT_SNIPPET` | Experimental setting to inject a JavaScript snippet into HTML responses after the opening `` tag. The value should be a complete JavaScript snippet including `"` | +|--------------------------------------|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| otel.experimental.javascript-snippet | OTEL_EXPERIMENTAL_JAVASCRIPT_SNIPPET | Experimental setting to inject a JavaScript snippet into HTML responses after the opening `` tag. The value should be a complete JavaScript snippet including `"` | **Important notes:** From f0566aa9e65a53b415be78ad5fc95e9f90c0c0f3 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 08:07:22 +0100 Subject: [PATCH 20/40] fix --- docs/advanced-configuration-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/advanced-configuration-options.md b/docs/advanced-configuration-options.md index 688af9d07f13..537253406497 100644 --- a/docs/advanced-configuration-options.md +++ b/docs/advanced-configuration-options.md @@ -45,7 +45,7 @@ This feature is designed for integrating client-side monitoring. We plan to integrate OpenTelemetry's own client-side monitoring solution by default once it's available (see the [browser instrumentation proposal](https://github.com/open-telemetry/community/blob/main/projects/browser-phase-1.md)). -| System property | Environment variable | Purpose | +| System property | Environment variable | Purpose | |--------------------------------------|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | otel.experimental.javascript-snippet | OTEL_EXPERIMENTAL_JAVASCRIPT_SNIPPET | Experimental setting to inject a JavaScript snippet into HTML responses after the opening `` tag. The value should be a complete JavaScript snippet including `"` | From b7f9fb795ebb17874289ecfeb4ec306a6ec46252 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 08:52:31 +0100 Subject: [PATCH 21/40] fix --- .../ConfigPropertiesBackedDeclarativeConfigProperties.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java index 9c7316b55160..90595ee52c57 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java @@ -77,6 +77,9 @@ public final class ConfigPropertiesBackedDeclarativeConfigProperties SPECIAL_MAPPINGS.put( "java.opentelemetry_extension_annotations.exclude_methods", "otel.instrumentation.opentelemetry-annotations.exclude-methods"); + SPECIAL_MAPPINGS.put( + "java.common.span_suppression_strategy/development", + "otel.instrumentation.experimental.span-suppression-strategy"); } private final ConfigProperties configProperties; From ec4a9dff5691017a1c690e21b7b5ecddc6ad87df Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 08:54:57 +0100 Subject: [PATCH 22/40] fix --- .../instrumentation/jdbc/OpenTelemetryDriver.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java index 3ca365874ec0..a9d714ee0a13 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java @@ -71,13 +71,13 @@ public final class OpenTelemetryDriver implements Driver { DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "jdbc") .get("sqlcommenter/development") .getBoolean("enabled", false), + openTelemetry -> + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled", false), openTelemetry -> DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") .get("db_sqlcommenter/development") .getBoolean("enabled", false), - openTelemetry -> - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled", false), openTelemetry -> ConfigPropertiesUtil.getBoolean( "otel.instrumentation.common.experimental.db-sqlcommenter.enabled", false)); From 4633dd627d7f7eac7f7dd034c2ccd286feb3eca5 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 09:06:18 +0100 Subject: [PATCH 23/40] fix --- .../ConfigPropertiesBackedDeclarativeConfigProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java index 90595ee52c57..22a58297907e 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java @@ -79,7 +79,7 @@ public final class ConfigPropertiesBackedDeclarativeConfigProperties "otel.instrumentation.opentelemetry-annotations.exclude-methods"); SPECIAL_MAPPINGS.put( "java.common.span_suppression_strategy/development", - "otel.instrumentation.experimental.span-suppression-strategy"); + "otel.instrumentation.experimental.span-suppression-strategy"); } private final ConfigProperties configProperties; From 946a126082329695e7200894d9bcc8f4a4b1183f Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 19:26:43 +0100 Subject: [PATCH 24/40] pr review --- .../v1_11/autoconfigure/TracingRequestHandler.java | 11 +++++------ .../smoketest/AbstractTestContainerManager.java | 4 +--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java index a4c97846f757..adbcabb7d06e 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java @@ -45,12 +45,11 @@ private static RequestHandler2 buildDelegate(OpenTelemetry openTelemetry) { "otel.instrumentation.messaging.experimental.receive-telemetry.enabled", false))) .setCapturedHeaders( - Optional.ofNullable( - messaging.getScalarList("capture_headers/development", String.class)) - .orElse( - ConfigPropertiesUtil.getList( - "otel.instrumentation.messaging.experimental.capture-headers", - emptyList()))) + messaging.getScalarList( + "capture_headers/development", + String.class, + ConfigPropertiesUtil.getList( + "otel.instrumentation.messaging.experimental.capture-headers", emptyList()))) .build() .newRequestHandler(); } diff --git a/smoke-tests/src/main/java/io/opentelemetry/smoketest/AbstractTestContainerManager.java b/smoke-tests/src/main/java/io/opentelemetry/smoketest/AbstractTestContainerManager.java index 8342151bb4c5..985c4381138a 100644 --- a/smoke-tests/src/main/java/io/opentelemetry/smoketest/AbstractTestContainerManager.java +++ b/smoke-tests/src/main/java/io/opentelemetry/smoketest/AbstractTestContainerManager.java @@ -45,9 +45,7 @@ protected Map getAgentEnvironment( environment.put("OTEL_RESOURCE_ATTRIBUTES", "service.name=smoke-test"); } environment.put("OTEL_JAVAAGENT_DEBUG", "true"); - environment.put( - "OTEL_INSTRUMENTATION_SERVLET_EXPERIMENTAL_JAVASCRIPT_SNIPPET", - ""); + environment.put("OTEL_EXPERIMENTAL_JAVASCRIPT_SNIPPET", ""); environment.put("OTEL_INSTRUMENTATION_RUNTIME_TELEMETRY_PACKAGE_EMITTER_ENABLED", "true"); return environment; } From 695a6d77efcf813f194d898d36f60d83d4111602 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 19:30:01 +0100 Subject: [PATCH 25/40] pr review --- .../bootstrap/servlet/ExperimentalSnippetHolder.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java index 493731d56aa4..f5890abc821e 100644 --- a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java +++ b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.bootstrap.servlet; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; @@ -14,9 +15,12 @@ public class ExperimentalSnippetHolder { private static volatile String snippet = getSnippetSetting(); private static String getSnippetSetting() { - return DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "servlet") + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + return DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "servlet") .getString( "javascript_snippet/development", + // use ConfigPropertiesUtil only to prevent that the deprecated property is used in + // declarative config ConfigPropertiesUtil.getString("otel.experimental.javascript-snippet", "")); } From cee626f5f3ee8fa4e02d435c447d9ce9cbf330f8 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 19:48:35 +0100 Subject: [PATCH 26/40] pr review --- .../autoconfigure/TracingRequestHandler.java | 1 - .../appender/v2_17/OpenTelemetryAppender.java | 7 +- .../OpenTelemetryContextDataProvider.java | 9 +-- .../v2_17/internal/ContextDataKeys.java | 68 +++++++++++-------- 4 files changed, 49 insertions(+), 36 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java index adbcabb7d06e..c0c93a667999 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java @@ -17,7 +17,6 @@ import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.awssdk.v1_11.AwsSdkTelemetry; -import java.util.Optional; /** * A {@link RequestHandler2} for use as an SPI by the AWS SDK to automatically trace all requests. diff --git a/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/OpenTelemetryAppender.java b/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/OpenTelemetryAppender.java index 85eb7821ee92..e5a9bbfbfa8c 100644 --- a/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/OpenTelemetryAppender.java +++ b/instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/OpenTelemetryAppender.java @@ -323,10 +323,11 @@ private void emit(OpenTelemetry openTelemetry, LogEvent event) { // reconstruct the context from context data if (context == Context.root()) { ContextDataAccessor contextDataAccessor = ContextDataAccessorImpl.INSTANCE; - String traceId = contextDataAccessor.getValue(contextData, ContextDataKeys.TRACE_ID_KEY); - String spanId = contextDataAccessor.getValue(contextData, ContextDataKeys.SPAN_ID_KEY); + ContextDataKeys contextDataKeys = ContextDataKeys.create(openTelemetry); + String traceId = contextDataAccessor.getValue(contextData, contextDataKeys.getTraceIdKey()); + String spanId = contextDataAccessor.getValue(contextData, contextDataKeys.getSpanIdKey()); String traceFlags = - contextDataAccessor.getValue(contextData, ContextDataKeys.TRACE_FLAGS_KEY); + contextDataAccessor.getValue(contextData, contextDataKeys.getTraceFlags()); if (traceId != null && spanId != null && traceFlags != null) { context = Context.root() diff --git a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java index 38de05d23ef4..d32f18418b11 100644 --- a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java +++ b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java @@ -76,16 +76,17 @@ public Map supplyContextData() { return staticContextData; } - if (ThreadContext.containsKey(ContextDataKeys.TRACE_ID_KEY)) { + ContextDataKeys contextDataKeys = ContextDataKeys.create(GlobalOpenTelemetry.get()); + if (ThreadContext.containsKey(contextDataKeys.getTraceIdKey())) { // Assume already instrumented event if traceId is present. return staticContextData; } Map contextData = new HashMap<>(staticContextData); SpanContext spanContext = currentSpan.getSpanContext(); - contextData.put(ContextDataKeys.TRACE_ID_KEY, spanContext.getTraceId()); - contextData.put(ContextDataKeys.SPAN_ID_KEY, spanContext.getSpanId()); - contextData.put(ContextDataKeys.TRACE_FLAGS_KEY, spanContext.getTraceFlags().asHex()); + contextData.put(contextDataKeys.getTraceIdKey(), spanContext.getTraceId()); + contextData.put(contextDataKeys.getSpanIdKey(), spanContext.getSpanId()); + contextData.put(contextDataKeys.getTraceFlags(), spanContext.getTraceFlags().asHex()); if (BAGGAGE_ENABLED) { Baggage baggage = Baggage.fromContext(context); diff --git a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/internal/ContextDataKeys.java b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/internal/ContextDataKeys.java index 16873ce396fe..129e51b854d3 100644 --- a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/internal/ContextDataKeys.java +++ b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/internal/ContextDataKeys.java @@ -5,7 +5,7 @@ package io.opentelemetry.instrumentation.log4j.contextdata.v2_17.internal; -import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.log.LoggingContextConstants; @@ -16,33 +16,45 @@ * any time. */ public final class ContextDataKeys { - public static final String TRACE_ID_KEY = - getLogging() - .getString( - "trace_id", - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.logging.trace-id", - LoggingContextConstants.TRACE_ID)); - - public static final String SPAN_ID_KEY = - getLogging() - .getString( - "span_id", - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.logging.span-id", LoggingContextConstants.SPAN_ID)); - - public static final String TRACE_FLAGS_KEY = - getLogging() - .getString( - "trace_flags", - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.logging.trace-flags", - LoggingContextConstants.TRACE_FLAGS)); - - private static DeclarativeConfigProperties getLogging() { - return DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "common") - .get("logging"); + + private final String traceIdKey; + private final String spanIdKey; + private final String traceFlags; + + private ContextDataKeys(String traceIdKey, String spanIdKey, String traceFlags) { + this.traceIdKey = traceIdKey; + this.spanIdKey = spanIdKey; + this.traceFlags = traceFlags; } - private ContextDataKeys() {} + public static ContextDataKeys create(OpenTelemetry openTelemetry) { + DeclarativeConfigProperties logging = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common").get("logging"); + return new ContextDataKeys( + logging.getString( + "trace_id", + ConfigPropertiesUtil.getString( + "otel.instrumentation.common.logging.trace-id", LoggingContextConstants.TRACE_ID)), + logging.getString( + "span_id", + ConfigPropertiesUtil.getString( + "otel.instrumentation.common.logging.span-id", LoggingContextConstants.SPAN_ID)), + logging.getString( + "trace_flags", + ConfigPropertiesUtil.getString( + "otel.instrumentation.common.logging.trace-flags", + LoggingContextConstants.TRACE_FLAGS))); + } + + public String getTraceIdKey() { + return traceIdKey; + } + + public String getSpanIdKey() { + return spanIdKey; + } + + public String getTraceFlags() { + return traceFlags; + } } From e3bd9016e4e476fda5f02db74feb10ee800d9b6b Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 19:53:53 +0100 Subject: [PATCH 27/40] pr review --- .../instrumentation/jdbc/internal/JdbcInstrumenterFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java index bc8b8d35b1d0..e41d693cb5fd 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java @@ -100,8 +100,9 @@ public static Instrumenter createTransactionInstrumenter( OpenTelemetry openTelemetry) { boolean enabled = DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "jdbc") + .get("transaction/development") .getBoolean( - "transaction/development", + "enabled", ConfigPropertiesUtil.getBoolean( "otel.instrumentation.jdbc.experimental.transaction.enabled", false)); return createTransactionInstrumenter(openTelemetry, enabled); From de1ef5de6e6a4d30e8c6c4cb9c429dde446007e4 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 22 Dec 2025 20:01:09 +0100 Subject: [PATCH 28/40] pr review --- .../v2_6/TracingConsumerInterceptor.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java index ec0985243ff6..08d3f91c4cbd 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java @@ -19,7 +19,6 @@ import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContextUtil; import java.util.Map; import java.util.Objects; -import java.util.Optional; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerInterceptor; import org.apache.kafka.clients.consumer.ConsumerRecords; @@ -54,12 +53,12 @@ public class TracingConsumerInterceptor implements ConsumerInterceptor Date: Mon, 22 Dec 2025 21:19:00 +0100 Subject: [PATCH 29/40] pr review --- .../instrumentation/jdbc/OpenTelemetryDriver.java | 3 ++- .../instrumentation/jdbc/internal/JdbcInstrumenterFactory.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java index a9d714ee0a13..eaafc2fc8578 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java @@ -76,7 +76,8 @@ public final class OpenTelemetryDriver implements Driver { "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled", false), openTelemetry -> DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") - .get("db_sqlcommenter/development") + .get("database") + .get("sqlcommenter/development") .getBoolean("enabled", false), openTelemetry -> ConfigPropertiesUtil.getBoolean( diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java index e41d693cb5fd..dc91d6549c93 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java @@ -46,7 +46,8 @@ static Instrumenter createStatementInstrumenter( OpenTelemetry openTelemetry, boolean captureQueryParameters) { boolean statementSanitizationEnabled = DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") - .get("db_statement_sanitizer") + .get("database") + .get("statement_sanitizer") .getBoolean( "enabled", ConfigPropertiesUtil.getBoolean( From da7325b1f4a50bf659f1d8885cc1b43d93eff47a Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 23 Dec 2025 08:50:00 +0100 Subject: [PATCH 30/40] pr review --- .../awssdk/v1_11/autoconfigure/TracingRequestHandler.java | 2 +- .../awssdk/v2_2/internal/AwsSdkTelemetryFactory.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java index c0c93a667999..e77f1d409b0b 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/autoconfigure/TracingRequestHandler.java @@ -32,7 +32,7 @@ private static RequestHandler2 buildDelegate(OpenTelemetry openTelemetry) { .setCaptureExperimentalSpanAttributes( DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "aws_sdk") .getBoolean( - "span_attributes/development", + "experimental_span_attributes/development", ConfigPropertiesUtil.getBoolean( "otel.instrumentation.aws-sdk.experimental-span-attributes", false))) .setMessagingReceiveTelemetryEnabled( diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java index dce41c9069a1..eb00515b3a27 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java @@ -38,7 +38,7 @@ public static AwsSdkTelemetry telemetry() { "otel.instrumentation.messaging.experimental.capture-headers", emptyList()))) .setCaptureExperimentalSpanAttributes( awsSdk.getBoolean( - "span_attributes/development", + "experimental_span_attributes/development", ConfigPropertiesUtil.getBoolean( "otel.instrumentation.aws-sdk.experimental-span-attributes", false))) .setMessagingReceiveTelemetryEnabled( From 80905ad8cc1a0072ba068f6dc140b3919fdfcf51 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 23 Dec 2025 08:56:57 +0100 Subject: [PATCH 31/40] pr review --- .../ConfigPropertiesBackedDeclarativeConfigProperties.java | 3 +++ .../awssdk/v2_2/internal/AwsSdkTelemetryFactory.java | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java index 22a58297907e..6ef18f04e0bf 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java @@ -80,6 +80,9 @@ public final class ConfigPropertiesBackedDeclarativeConfigProperties SPECIAL_MAPPINGS.put( "java.common.span_suppression_strategy/development", "otel.instrumentation.experimental.span-suppression-strategy"); + SPECIAL_MAPPINGS.put( + "java.common.gen_ai", + "otel.instrumentation.genai.capture-message-content"); } private final ConfigProperties configProperties; diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java index eb00515b3a27..eaf3e34abacd 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java @@ -62,7 +62,8 @@ public static AwsSdkTelemetry telemetry() { "otel.instrumentation.aws-sdk.experimental-record-individual-http-error", false))) .setGenaiCaptureMessageContent( - DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "genai") + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") + .get("gen_ai") .getBoolean( "capture_message_content", ConfigPropertiesUtil.getBoolean( From 33c917f5a5ac5ab418972bfe0a54041dbb455cc2 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 23 Dec 2025 08:59:39 +0100 Subject: [PATCH 32/40] pr review --- .../jdbc/OpenTelemetryDriver.java | 47 +++++++++---------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java index eaafc2fc8578..f31f6027fc12 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java @@ -39,7 +39,6 @@ import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; @@ -47,7 +46,6 @@ import java.util.Properties; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; import java.util.logging.Logger; import javax.annotation.Nullable; @@ -65,33 +63,30 @@ public final class OpenTelemetryDriver implements Driver { private static final String URL_PREFIX = "jdbc:otel:"; private static final AtomicBoolean REGISTERED = new AtomicBoolean(); private static final List DRIVER_CANDIDATES = new CopyOnWriteArrayList<>(); - private static final List> SQL_COMMENTER_VALUE_PROVIDERS = - Arrays.asList( - openTelemetry -> - DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "jdbc") - .get("sqlcommenter/development") - .getBoolean("enabled", false), - openTelemetry -> - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled", false), - openTelemetry -> - DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") - .get("database") - .get("sqlcommenter/development") - .getBoolean("enabled", false), - openTelemetry -> - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.common.experimental.db-sqlcommenter.enabled", false)); private static SqlCommenter getSqlCommenter(OpenTelemetry openTelemetry) { - boolean value = false; - for (Function provider : SQL_COMMENTER_VALUE_PROVIDERS) { - value = provider.apply(openTelemetry); - if (value) { - break; - } + boolean enabled = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "jdbc") + .get("sqlcommenter/development") + .getBoolean("enabled", false); + if (!enabled) { + enabled = + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled", false); + } + if (!enabled) { + enabled = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") + .get("database") + .get("sqlcommenter/development") + .getBoolean("enabled", false); + } + if (!enabled) { + enabled = + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.common.experimental.db-sqlcommenter.enabled", false); } - return SqlCommenter.builder().setEnabled(value).build(); + return SqlCommenter.builder().setEnabled(enabled).build(); } static { From 8f3c3dfa8781e49c2737c424b482423cc53ea83a Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 23 Dec 2025 09:02:40 +0100 Subject: [PATCH 33/40] pr review --- .../ConfigPropertiesBackedDeclarativeConfigProperties.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java index 6ef18f04e0bf..dcc7d664c71e 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java @@ -81,8 +81,7 @@ public final class ConfigPropertiesBackedDeclarativeConfigProperties "java.common.span_suppression_strategy/development", "otel.instrumentation.experimental.span-suppression-strategy"); SPECIAL_MAPPINGS.put( - "java.common.gen_ai", - "otel.instrumentation.genai.capture-message-content"); + "java.common.gen_ai", "otel.instrumentation.genai.capture-message-content"); } private final ConfigProperties configProperties; From a1386267c6858b9d5ca4a0394211bf9d687dbd55 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 23 Dec 2025 09:20:49 +0100 Subject: [PATCH 34/40] pr review --- .../ConfigPropertiesBackedDeclarativeConfigProperties.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java index dcc7d664c71e..5d1bff8ea35d 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java @@ -81,7 +81,8 @@ public final class ConfigPropertiesBackedDeclarativeConfigProperties "java.common.span_suppression_strategy/development", "otel.instrumentation.experimental.span-suppression-strategy"); SPECIAL_MAPPINGS.put( - "java.common.gen_ai", "otel.instrumentation.genai.capture-message-content"); + "java.common.gen_ai.capture_message_content", + "otel.instrumentation.genai.capture-message-content"); } private final ConfigProperties configProperties; From 494711e265ffcbf21bd5789ac8363ae44ecb4b9b Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 24 Dec 2025 12:09:13 +0100 Subject: [PATCH 35/40] no sys props in agent --- .../awssdk/v2_2/AwsSdkSingletons.java | 2 +- .../v2_2/autoconfigure/AwsSdkSingletons.java | 2 +- .../v2_2/internal/AwsSdkTelemetryFactory.java | 46 ++++++++++++------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java index f2fbbbbcd9b2..202cba099e13 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java @@ -10,7 +10,7 @@ public final class AwsSdkSingletons { - private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.telemetry(); + private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.telemetry(false); public static AwsSdkTelemetry telemetry() { return TELEMETRY; diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java index 565b08e048ac..d3d95d7fb704 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java @@ -10,7 +10,7 @@ public final class AwsSdkSingletons { - private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.telemetry(); + private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.telemetry(true); public static AwsSdkTelemetry telemetry() { return TELEMETRY; diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java index eaf3e34abacd..6256f4c2c87f 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java @@ -13,6 +13,7 @@ import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; +import java.util.List; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at @@ -20,7 +21,11 @@ */ public final class AwsSdkTelemetryFactory { - public static AwsSdkTelemetry telemetry() { + private final boolean useLegacyLibraryConfig; + + public static AwsSdkTelemetry telemetry(boolean useLegacyLibraryConfig) { + AwsSdkTelemetryFactory factory = new AwsSdkTelemetryFactory(useLegacyLibraryConfig); + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); ExtendedDeclarativeConfigProperties commonConfig = DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common"); @@ -34,42 +39,49 @@ public static AwsSdkTelemetry telemetry() { messaging.getScalarList( "capture_headers/development", String.class, - ConfigPropertiesUtil.getList( - "otel.instrumentation.messaging.experimental.capture-headers", emptyList()))) + factory.legacyListValue( + "otel.instrumentation.messaging.experimental.capture-headers"))) .setCaptureExperimentalSpanAttributes( awsSdk.getBoolean( "experimental_span_attributes/development", - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.aws-sdk.experimental-span-attributes", false))) + factory.legacyBooleanValue( + "otel.instrumentation.aws-sdk.experimental-span-attributes"))) .setMessagingReceiveTelemetryEnabled( messaging .get("receive_telemetry/development") .getBoolean( "enabled", - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.messaging.experimental.receive-telemetry.enabled", - false))) + factory.legacyBooleanValue( + "otel.instrumentation.messaging.experimental.receive-telemetry.enabled"))) .setUseConfiguredPropagatorForMessaging( awsSdk.getBoolean( "use_propagator_for_messaging/development", - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging", - false))) + factory.legacyBooleanValue( + "otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging"))) .setRecordIndividualHttpError( awsSdk.getBoolean( "record_individual_http_error/development", - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.aws-sdk.experimental-record-individual-http-error", - false))) + factory.legacyBooleanValue( + "otel.instrumentation.aws-sdk.experimental-record-individual-http-error"))) .setGenaiCaptureMessageContent( DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") .get("gen_ai") .getBoolean( "capture_message_content", - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.genai.capture-message-content", false))) + factory.legacyBooleanValue( + "otel.instrumentation.genai.capture-message-content"))) .build(); } - private AwsSdkTelemetryFactory() {} + private List legacyListValue(String key) { + return useLegacyLibraryConfig ? ConfigPropertiesUtil.getList(key, emptyList()) : emptyList(); + } + + private boolean legacyBooleanValue(String key) { + return useLegacyLibraryConfig && ConfigPropertiesUtil.getBoolean(key, false); + } + + private AwsSdkTelemetryFactory(boolean useLegacyLibraryConfig) { + this.useLegacyLibraryConfig = useLegacyLibraryConfig; + } } From 745240ad9207939bd82cfa5cefd3ab356011f3d2 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 24 Dec 2025 12:12:39 +0100 Subject: [PATCH 36/40] allow to set false --- .../api/internal/ConfigPropertiesUtil.java | 14 +++++++++++++- .../jdbc/OpenTelemetryDriver.java | 16 ++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java index 810b1d7f1d92..d29616aaa24a 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java @@ -25,8 +25,20 @@ public final class ConfigPropertiesUtil { * to support Declarative Config. */ public static boolean getBoolean(String propertyName, boolean defaultValue) { + Boolean value = getBoolean(propertyName); + return value == null ? defaultValue : value; + } + + /** + * Returns the boolean value of the given property name from system properties and environment + * variables. + * + *

It's recommended to use {@link io.opentelemetry.api.incubator.config.ConfigProvider} instead + * to support Declarative Config. + */ + public static Boolean getBoolean(String propertyName) { String strValue = getString(propertyName); - return strValue == null ? defaultValue : Boolean.parseBoolean(strValue); + return strValue == null ? null : Boolean.parseBoolean(strValue); } /** diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java index f31f6027fc12..ff7e4b006c1a 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java @@ -65,26 +65,26 @@ public final class OpenTelemetryDriver implements Driver { private static final List DRIVER_CANDIDATES = new CopyOnWriteArrayList<>(); private static SqlCommenter getSqlCommenter(OpenTelemetry openTelemetry) { - boolean enabled = + Boolean enabled = DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "jdbc") .get("sqlcommenter/development") - .getBoolean("enabled", false); - if (!enabled) { + .getBoolean("enabled"); + if (enabled == null) { enabled = ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled", false); + "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled"); } - if (!enabled) { + if (enabled == null) { enabled = DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") .get("database") .get("sqlcommenter/development") - .getBoolean("enabled", false); + .getBoolean("enabled"); } - if (!enabled) { + if (enabled == null) { enabled = ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.common.experimental.db-sqlcommenter.enabled", false); + "otel.instrumentation.common.experimental.db-sqlcommenter.enabled"); } return SqlCommenter.builder().setEnabled(enabled).build(); } From 9749c18d2c13c08533e3ee5c7cd74100e77a5d4d Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 24 Dec 2025 12:50:10 +0100 Subject: [PATCH 37/40] no sys props in agent --- .../instrumentation/awssdk/v2_2/AwsSdkSingletons.java | 2 +- .../awssdk/v2_2/autoconfigure/AwsSdkSingletons.java | 2 +- .../awssdk/v2_2/internal/AwsSdkTelemetryFactory.java | 10 +++++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java index 202cba099e13..f2fbbbbcd9b2 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkSingletons.java @@ -10,7 +10,7 @@ public final class AwsSdkSingletons { - private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.telemetry(false); + private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.telemetry(); public static AwsSdkTelemetry telemetry() { return TELEMETRY; diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java index d3d95d7fb704..3cd892cce0ec 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java @@ -10,7 +10,7 @@ public final class AwsSdkSingletons { - private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.telemetry(true); + private static final AwsSdkTelemetry TELEMETRY = AwsSdkTelemetryFactory.legacyLibraryTelemetry(); public static AwsSdkTelemetry telemetry() { return TELEMETRY; diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java index 6256f4c2c87f..df70827002ea 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkTelemetryFactory.java @@ -23,7 +23,15 @@ public final class AwsSdkTelemetryFactory { private final boolean useLegacyLibraryConfig; - public static AwsSdkTelemetry telemetry(boolean useLegacyLibraryConfig) { + public static AwsSdkTelemetry legacyLibraryTelemetry() { + return telemetry(true); + } + + public static AwsSdkTelemetry telemetry() { + return telemetry(false); + } + + private static AwsSdkTelemetry telemetry(boolean useLegacyLibraryConfig) { AwsSdkTelemetryFactory factory = new AwsSdkTelemetryFactory(useLegacyLibraryConfig); OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); From b436af2c64c712758a0fe24a730a4d7574215b75 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 24 Dec 2025 12:56:55 +0100 Subject: [PATCH 38/40] use special_mapping --- ...igPropertiesBackedDeclarativeConfigProperties.java | 11 ++++++----- .../bootstrap/servlet/ExperimentalSnippetHolder.java | 11 ++--------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java index 5d1bff8ea35d..2694c805f3cc 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesBackedDeclarativeConfigProperties.java @@ -73,16 +73,17 @@ public final class ConfigPropertiesBackedDeclarativeConfigProperties SPECIAL_MAPPINGS.put( "java.common.gen_ai.capture_message_content", "otel.instrumentation.genai.capture-message-content"); + // top-level common configs + SPECIAL_MAPPINGS.put( + "java.common.span_suppression_strategy/development", + "otel.instrumentation.experimental.span-suppression-strategy"); // renaming to match instrumentation module name SPECIAL_MAPPINGS.put( "java.opentelemetry_extension_annotations.exclude_methods", "otel.instrumentation.opentelemetry-annotations.exclude-methods"); + // renaming to avoid top level config SPECIAL_MAPPINGS.put( - "java.common.span_suppression_strategy/development", - "otel.instrumentation.experimental.span-suppression-strategy"); - SPECIAL_MAPPINGS.put( - "java.common.gen_ai.capture_message_content", - "otel.instrumentation.genai.capture-message-content"); + "java.servlet.javascript_snippet/development", "otel.experimental.javascript-snippet"); } private final ConfigProperties configProperties; diff --git a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java index f5890abc821e..c43cf3f4cf3e 100644 --- a/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java +++ b/instrumentation/servlet/servlet-common/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/servlet/ExperimentalSnippetHolder.java @@ -6,22 +6,15 @@ package io.opentelemetry.javaagent.bootstrap.servlet; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; public class ExperimentalSnippetHolder { private static volatile String snippet = getSnippetSetting(); private static String getSnippetSetting() { - OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); - return DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "servlet") - .getString( - "javascript_snippet/development", - // use ConfigPropertiesUtil only to prevent that the deprecated property is used in - // declarative config - ConfigPropertiesUtil.getString("otel.experimental.javascript-snippet", "")); + return DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "servlet") + .getString("javascript_snippet/development", ""); } public static void setSnippet(String newValue) { From 2ee1181cb2002e441a212797299628bf63cc5cb7 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 24 Dec 2025 13:30:21 +0100 Subject: [PATCH 39/40] fix --- .../instrumentation/api/internal/ConfigPropertiesUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java index d29616aaa24a..81962afbf656 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/ConfigPropertiesUtil.java @@ -36,6 +36,7 @@ public static boolean getBoolean(String propertyName, boolean defaultValue) { *

It's recommended to use {@link io.opentelemetry.api.incubator.config.ConfigProvider} instead * to support Declarative Config. */ + @Nullable public static Boolean getBoolean(String propertyName) { String strValue = getString(propertyName); return strValue == null ? null : Boolean.parseBoolean(strValue); From 77fa4cbfb97592d7427f50ef134f5a82867f6d82 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 24 Dec 2025 14:14:33 +0100 Subject: [PATCH 40/40] fix --- .../instrumentation/jdbc/OpenTelemetryDriver.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java index ff7e4b006c1a..95256834d246 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/OpenTelemetryDriver.java @@ -86,6 +86,9 @@ private static SqlCommenter getSqlCommenter(OpenTelemetry openTelemetry) { ConfigPropertiesUtil.getBoolean( "otel.instrumentation.common.experimental.db-sqlcommenter.enabled"); } + if (enabled == null) { + enabled = false; // default value + } return SqlCommenter.builder().setEnabled(enabled).build(); }