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..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,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; 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..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 @@ -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,11 +51,7 @@ public final class InstrumenterBuilder { 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; @@ -76,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) -> @@ -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; + } + + 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() { @@ -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 { 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..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 @@ -17,11 +17,38 @@ */ 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) { + 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. + */ + @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. + * + *

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,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. + * + *

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); @@ -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. + * + *

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) { 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..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 @@ -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; @@ -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) { 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..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 @@ -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 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..df70827002ea --- /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,95 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2.internal; + +import static java.util.Collections.emptyList; + +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.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 final class AwsSdkTelemetryFactory { + + private final 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(); + ExtendedDeclarativeConfigProperties commonConfig = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common"); + ExtendedDeclarativeConfigProperties messaging = commonConfig.get("messaging"); + + ExtendedDeclarativeConfigProperties awsSdk = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "aws_sdk"); + + return AwsSdkTelemetry.builder(openTelemetry) + .setCapturedHeaders( + messaging.getScalarList( + "capture_headers/development", + String.class, + factory.legacyListValue( + "otel.instrumentation.messaging.experimental.capture-headers"))) + .setCaptureExperimentalSpanAttributes( + awsSdk.getBoolean( + "experimental_span_attributes/development", + factory.legacyBooleanValue( + "otel.instrumentation.aws-sdk.experimental-span-attributes"))) + .setMessagingReceiveTelemetryEnabled( + messaging + .get("receive_telemetry/development") + .getBoolean( + "enabled", + factory.legacyBooleanValue( + "otel.instrumentation.messaging.experimental.receive-telemetry.enabled"))) + .setUseConfiguredPropagatorForMessaging( + awsSdk.getBoolean( + "use_propagator_for_messaging/development", + factory.legacyBooleanValue( + "otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging"))) + .setRecordIndividualHttpError( + awsSdk.getBoolean( + "record_individual_http_error/development", + factory.legacyBooleanValue( + "otel.instrumentation.aws-sdk.experimental-record-individual-http-error"))) + .setGenaiCaptureMessageContent( + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") + .get("gen_ai") + .getBoolean( + "capture_message_content", + factory.legacyBooleanValue( + "otel.instrumentation.genai.capture-message-content"))) + .build(); + } + + 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; + } +} 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..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 @@ -23,6 +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.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; @@ -63,14 +64,33 @@ 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) { + Boolean enabled = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "jdbc") + .get("sqlcommenter/development") + .getBoolean("enabled"); + if (enabled == null) { + enabled = + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.jdbc.experimental.sqlcommenter.enabled"); + } + if (enabled == null) { + enabled = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") + .get("database") + .get("sqlcommenter/development") + .getBoolean("enabled"); + } + if (enabled == null) { + enabled = + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.common.experimental.db-sqlcommenter.enabled"); + } + if (enabled == null) { + enabled = false; // default value + } + return SqlCommenter.builder().setEnabled(enabled).build(); + } static { try { @@ -256,7 +276,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 +286,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..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 @@ -8,6 +8,7 @@ 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; @@ -28,25 +29,31 @@ 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.getInstrumentationConfig(openTelemetry, "jdbc") + .getBoolean( + "capture_query_parameters/development", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.jdbc.experimental.capture-query-parameters", 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.getInstrumentationConfig(openTelemetry, "common") + .get("database") + .get("statement_sanitizer") + .getBoolean( + "enabled", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.common.db-statement-sanitizer.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 +99,14 @@ 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.getInstrumentationConfig(openTelemetry, "jdbc") + .get("transaction/development") + .getBoolean( + "enabled", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.jdbc.experimental.transaction.enabled", 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..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 @@ -9,7 +9,10 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; 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.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.api.internal.Timer; import io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal.KafkaConsumerContext; @@ -32,15 +35,32 @@ @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(); + ExtendedDeclarativeConfigProperties messaging = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common").get("messaging"); + + telemetry = + KafkaTelemetry.builder(openTelemetry) + .setMessagingReceiveInstrumentationEnabled( + 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(); + } 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..3cdac25a982b 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 @@ -9,6 +9,8 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; 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; import java.util.Map; import java.util.Objects; @@ -28,12 +30,24 @@ @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( + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "common") + .get("messaging") + .getScalarList( + "capture_headers/development", + String.class, + ConfigPropertiesUtil.getList( + "otel.instrumentation.messaging.experimental.capture-headers", + emptyList()))) + .build(); + } @Nullable private String clientId; 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 57024ded7c3c..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 @@ -5,11 +5,13 @@ package io.opentelemetry.instrumentation.log4j.contextdata.v2_17; +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.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.log4j.contextdata.v2_17.internal.ContextDataKeys; import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder; @@ -25,7 +27,13 @@ */ public class OpenTelemetryContextDataProvider implements ContextDataProvider { private static final boolean BAGGAGE_ENABLED = - ConfigPropertiesUtil.getBoolean("otel.instrumentation.log4j-context-data.add-baggage", false); + DeclarativeConfigUtil.getInstrumentationConfig( + GlobalOpenTelemetry.get(), "log4j_context_data") + .getBoolean( + "add_baggage", + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.log4j-context-data.add-baggage", false)); + private static final boolean configuredResourceAttributeAccessible = isConfiguredResourceAttributeAccessible(); private static final Map staticContextData = getStaticContextData(); @@ -68,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 a57da53ba61c..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,6 +5,9 @@ package io.opentelemetry.instrumentation.log4j.contextdata.v2_17.internal; +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; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; @@ -13,15 +16,45 @@ * any time. */ public final class ContextDataKeys { - public static final String TRACE_ID_KEY = - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.logging.trace-id", LoggingContextConstants.TRACE_ID); - public static final String SPAN_ID_KEY = - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.logging.span-id", LoggingContextConstants.SPAN_ID); - public static final String TRACE_FLAGS_KEY = - ConfigPropertiesUtil.getString( - "otel.instrumentation.common.logging.trace-flags", LoggingContextConstants.TRACE_FLAGS); - - private ContextDataKeys() {} + + 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; + } + + 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; + } } 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..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 @@ -5,15 +5,16 @@ package io.opentelemetry.javaagent.bootstrap.servlet; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; public class ExperimentalSnippetHolder { private static volatile String snippet = getSnippetSetting(); private static String getSnippetSetting() { - String result = ConfigPropertiesUtil.getString("otel.experimental.javascript-snippet"); - return result == null ? "" : result; + return DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "servlet") + .getString("javascript_snippet/development", ""); } public static void setSnippet(String newValue) {