Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d847267
Apply spotless formatting and finalize span-suppression-strategy rename
Abhilash-Garapati Dec 11, 2025
64ccedf
Apply backward-compatible span suppression config rename in AgentInst…
Abhilash-Garapati Dec 11, 2025
7913784
Apply spotless formatting
Abhilash-Garapati Dec 11, 2025
5848fb4
Add DeprecatedConfigProperties and apply backward-compatible config r…
Abhilash-Garapati Dec 12, 2025
90a7295
use DeclarativeConfigUtil for library config usage
zeitlinger Dec 15, 2025
9bdca32
use DeclarativeConfigUtil for library config usage
zeitlinger Dec 16, 2025
e8dbab4
use DeclarativeConfigUtil for library config usage
zeitlinger Dec 16, 2025
f49d942
fix
zeitlinger Dec 16, 2025
fbb4477
fix
zeitlinger Dec 16, 2025
15b9f26
fix
zeitlinger Dec 16, 2025
ea460af
fix
zeitlinger Dec 16, 2025
3862072
fix
zeitlinger Dec 16, 2025
da3cffb
rename to LibraryConfigUtil to make a clear distinction to Declarativ…
zeitlinger Dec 18, 2025
6014150
fix
zeitlinger Dec 20, 2025
e410d80
fix
zeitlinger Dec 20, 2025
bfd1ad1
pr review
zeitlinger Dec 20, 2025
736155b
use explicit fallback instead of LegacyLibraryConfigUtil.java
zeitlinger Dec 22, 2025
42a7af9
pr review
zeitlinger Dec 22, 2025
a2d115c
no breaking change anymore
zeitlinger Dec 22, 2025
f0566aa
fix
zeitlinger Dec 22, 2025
b7f9fb7
fix
zeitlinger Dec 22, 2025
ec4a9df
fix
zeitlinger Dec 22, 2025
4633dd6
fix
zeitlinger Dec 22, 2025
946a126
pr review
zeitlinger Dec 22, 2025
695a6d7
pr review
zeitlinger Dec 22, 2025
cee626f
pr review
zeitlinger Dec 22, 2025
e3bd901
pr review
zeitlinger Dec 22, 2025
de1ef5d
pr review
zeitlinger Dec 22, 2025
3f8fdfc
pr review
zeitlinger Dec 22, 2025
da7325b
pr review
zeitlinger Dec 23, 2025
80905ad
pr review
zeitlinger Dec 23, 2025
33c917f
pr review
zeitlinger Dec 23, 2025
8f3c3df
pr review
zeitlinger Dec 23, 2025
a138626
pr review
zeitlinger Dec 23, 2025
494711e
no sys props in agent
zeitlinger Dec 24, 2025
745240a
allow to set false
zeitlinger Dec 24, 2025
9749c18
no sys props in agent
zeitlinger Dec 24, 2025
b436af2
use special_mapping
zeitlinger Dec 24, 2025
2ee1181
fix
zeitlinger Dec 24, 2025
77fa4cb
fix
zeitlinger Dec 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +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.servlet.javascript_snippet/development", "otel.experimental.javascript-snippet");
}

private final ConfigProperties configProperties;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -48,11 +51,7 @@
public final class InstrumenterBuilder<REQUEST, RESPONSE> {

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

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

final OpenTelemetry openTelemetry;
final String instrumentationName;
Expand All @@ -76,6 +75,20 @@ public final class InstrumenterBuilder<REQUEST, RESPONSE> {
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) ->
Expand Down Expand Up @@ -374,7 +387,28 @@ private String getSchemaUrl() {

SpanSuppressor buildSpanSuppressor() {
return new SpanSuppressors.ByContextKey(
spanSuppressionStrategy.create(getSpanKeysFromAttributesExtractors()));
SpanSuppressionStrategy.fromConfig(getSpanSuppressionStrategy())
.create(getSpanKeysFromAttributesExtractors()));
}

@Nullable
private String getSpanSuppressionStrategy() {
// we cannot use DeclarativeConfigUtil here because it's not available in instrumentation-api
if (maybeDeclarativeConfig(openTelemetry)) {
DeclarativeConfigProperties instrumentationConfig =
((ExtendedOpenTelemetry) openTelemetry).getConfigProvider().getInstrumentationConfig();
if (instrumentationConfig == null) {
return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once getConfigProvider() is moved out of ExtendedOpenTelemetry to OpenTelemetry, I think we'll need to check the sys prop here? If so, may be good to do that now, could be easy to forget when refactoring later

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a mapping to check for the old value

SPECIAL_MAPPINGS.put(
"java.common.span_suppression_strategy/development",
"otel.instrumentation.experimental.span-suppression-strategy");

}

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<SpanKey> getSpanKeysFromAttributesExtractors() {
Expand Down Expand Up @@ -454,6 +488,15 @@ public void setSpanStatusExtractorCustomizer(
}
}

/**
* 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;
}

private interface InstrumenterConstructor<RQ, RS> {
Instrumenter<RQ, RS> create(InstrumenterBuilder<RQ, RS> builder);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,38 @@
*/
public final class ConfigPropertiesUtil {

/**
* Returns the boolean value of the given property name from system properties and environment
* variables.
*
* <p>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) {
Boolean value = getBoolean(propertyName);
return value == null ? defaultValue : value;
}

/**
* Returns the boolean value of the given property name from system properties and environment
* variables.
*
* <p>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 ? defaultValue : Boolean.parseBoolean(strValue);
return strValue == null ? null : Boolean.parseBoolean(strValue);
}

/**
* Returns the int value of the given property name from system properties and environment
* variables.
*
* <p>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) {
Expand All @@ -34,6 +61,13 @@ public static int getInt(String propertyName, int defaultValue) {
}
}

/**
* Returns the string value of the given property name from system properties and environment
* variables.
*
* <p>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);
Expand All @@ -43,11 +77,26 @@ public static String getString(String propertyName) {
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.
*
* <p>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.
*
* <p>It's recommended to use {@link io.opentelemetry.api.incubator.config.ConfigProvider} instead
* to support Declarative Config.
*/
public static List<String> getList(String propertyName, List<String> defaultValue) {
String value = getString(propertyName);
if (value == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import com.amazonaws.Response;
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.internal.ConfigPropertiesUtil;
import io.opentelemetry.instrumentation.awssdk.v1_11.AwsSdkTelemetry;

Expand All @@ -20,19 +23,35 @@
*/
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) {
ExtendedDeclarativeConfigProperties messaging =
DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common").get("messaging");
return AwsSdkTelemetry.builder(openTelemetry)
.setCaptureExperimentalSpanAttributes(
DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "aws_sdk")
.getBoolean(
"experimental_span_attributes/development",
ConfigPropertiesUtil.getBoolean(
"otel.instrumentation.aws-sdk.experimental-span-attributes", false)))
.setMessagingReceiveTelemetryEnabled(
messaging
.get("receive_telemetry/development")
.getBoolean(
"enabled",
ConfigPropertiesUtil.getBoolean(
"otel.instrumentation.messaging.experimental.receive-telemetry.enabled",
false)))
.setCapturedHeaders(
messaging.getScalarList(
"capture_headers/development",
String.class,
ConfigPropertiesUtil.getList(
"otel.instrumentation.messaging.experimental.capture-headers", emptyList())))
.build()
.newRequestHandler();
}

@Override
public void beforeRequest(Request<?> request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> 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() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.legacyLibraryTelemetry();

public static AwsSdkTelemetry telemetry() {
return TELEMETRY;
}

private static class AwsSdkTelemetryFactory extends AbstractAwsSdkTelemetryFactory {

@Override
protected List<String> 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() {}
}

This file was deleted.

Loading
Loading