From d40519bdebe427f73969360790ac453a109f280f Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 17 Jun 2024 07:01:09 +0200 Subject: [PATCH] use ConfigPropertiesBridge for spring starter --- .../internal/config/CommonConfigSetter.java | 24 ++++ .../internal/config/CoreCommonConfig.java | 125 ++++++++++++++++++ .../config/CoreInstrumentationConfig.java | 110 +++++++++++++++ .../internal/config}/EnduserConfig.java | 4 +- .../HttpClientInstrumenterBuilder.java | 40 ++++++ .../javaagent-unit-tests/build.gradle.kts | 1 + .../extannotations/IncludeTest.java | 4 +- .../ExternalAnnotationInstrumentation.java | 3 +- .../log4j/appender/v2_17/Log4jHelper.java | 3 +- .../appender/v1_0/LogbackSingletons.java | 3 +- .../micrometer/v1_5/MicrometerSingletons.java | 3 +- .../web/RestTemplateBeanPostProcessor.java | 12 +- .../web/RestTemplateInstrumentation.java | 12 +- ...ngWebInstrumentationAutoConfiguration.java | 11 +- .../internal/properties/CommonConfigUtil.java | 21 +++ .../properties/ConfigPropertiesBridge.java | 109 +++++++++++++++ ...itional-spring-configuration-metadata.json | 27 ++++ ...bInstrumentationAutoConfigurationTest.java | 6 + .../bootstrap/internal/CommonConfig.java | 120 +---------------- .../internal/DeprecatedConfigProperties.java | 7 +- .../internal/EmptyInstrumentationConfig.java | 3 +- .../internal/ExperimentalConfig.java | 5 +- .../internal/InstrumentationConfig.java | 111 ++-------------- javaagent-tooling/build.gradle.kts | 1 + .../config/ConfigPropertiesBridge.java | 4 +- muzzle/build.gradle.kts | 1 + 26 files changed, 530 insertions(+), 240 deletions(-) create mode 100644 instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CommonConfigSetter.java create mode 100644 instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CoreCommonConfig.java create mode 100644 instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CoreInstrumentationConfig.java rename {javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal => instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config}/EnduserConfig.java (96%) create mode 100644 instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/instrumenter/HttpClientInstrumenterBuilder.java create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/CommonConfigUtil.java create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CommonConfigSetter.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CommonConfigSetter.java new file mode 100644 index 000000000000..0bce3e18e6bd --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CommonConfigSetter.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.internal.config; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class CommonConfigSetter { + private CommonConfigSetter() {} + + public static void set(Supplier supplier, Consumer consumer) { + T t = supplier.get(); + if (t != null) { + consumer.accept(t); + } + } +} diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CoreCommonConfig.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CoreCommonConfig.java new file mode 100644 index 000000000000..7bf1b58f2af6 --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CoreCommonConfig.java @@ -0,0 +1,125 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.internal.config; + +import static java.util.Collections.emptyMap; + +import io.opentelemetry.instrumentation.api.incubator.log.LoggingContextConstants; +import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceResolver; +import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class CoreCommonConfig { + + private final PeerServiceResolver peerServiceResolver; + private final List clientRequestHeaders; + private final List clientResponseHeaders; + private final List serverRequestHeaders; + private final List serverResponseHeaders; + private final Set knownHttpRequestMethods; + private final EnduserConfig enduserConfig; + private final boolean statementSanitizationEnabled; + private final boolean emitExperimentalHttpClientTelemetry; + private final boolean emitExperimentalHttpServerTelemetry; + private final String loggingTraceIdKey; + private final String loggingSpanIdKey; + private final String loggingTraceFlagsKey; + + public CoreCommonConfig(CoreInstrumentationConfig config) { + peerServiceResolver = + PeerServiceResolver.create( + config.getMap("otel.instrumentation.common.peer-service-mapping", emptyMap())); + + clientRequestHeaders = + config.getList("otel.instrumentation.http.client.capture-request-headers"); + clientResponseHeaders = + config.getList("otel.instrumentation.http.client.capture-response-headers"); + serverRequestHeaders = + config.getList("otel.instrumentation.http.server.capture-request-headers"); + serverResponseHeaders = + config.getList("otel.instrumentation.http.server.capture-response-headers"); + knownHttpRequestMethods = + new HashSet<>( + config.getList( + "otel.instrumentation.http.known-methods", + new ArrayList<>(HttpConstants.KNOWN_METHODS))); + statementSanitizationEnabled = + config.getBoolean("otel.instrumentation.common.db-statement-sanitizer.enabled", true); + emitExperimentalHttpClientTelemetry = + config.getBoolean("otel.instrumentation.http.client.emit-experimental-telemetry", false); + emitExperimentalHttpServerTelemetry = + config.getBoolean("otel.instrumentation.http.server.emit-experimental-telemetry", false); + enduserConfig = new EnduserConfig(config); + loggingTraceIdKey = + config.getString( + "otel.instrumentation.common.logging.trace-id", LoggingContextConstants.TRACE_ID); + loggingSpanIdKey = + config.getString( + "otel.instrumentation.common.logging.span-id", LoggingContextConstants.SPAN_ID); + loggingTraceFlagsKey = + config.getString( + "otel.instrumentation.common.logging.trace-flags", LoggingContextConstants.TRACE_FLAGS); + } + + public PeerServiceResolver getPeerServiceResolver() { + return peerServiceResolver; + } + + public List getClientRequestHeaders() { + return clientRequestHeaders; + } + + public List getClientResponseHeaders() { + return clientResponseHeaders; + } + + public List getServerRequestHeaders() { + return serverRequestHeaders; + } + + public List getServerResponseHeaders() { + return serverResponseHeaders; + } + + public Set getKnownHttpRequestMethods() { + return knownHttpRequestMethods; + } + + public EnduserConfig getEnduserConfig() { + return enduserConfig; + } + + public boolean isStatementSanitizationEnabled() { + return statementSanitizationEnabled; + } + + public boolean shouldEmitExperimentalHttpClientTelemetry() { + return emitExperimentalHttpClientTelemetry; + } + + public boolean shouldEmitExperimentalHttpServerTelemetry() { + return emitExperimentalHttpServerTelemetry; + } + + public String getTraceIdKey() { + return loggingTraceIdKey; + } + + public String getSpanIdKey() { + return loggingSpanIdKey; + } + + public String getTraceFlagsKey() { + return loggingTraceFlagsKey; + } +} diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CoreInstrumentationConfig.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CoreInstrumentationConfig.java new file mode 100644 index 000000000000..e375cba5da3e --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/CoreInstrumentationConfig.java @@ -0,0 +1,110 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.internal.config; + +import static java.util.Collections.emptyList; + +import java.time.Duration; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +/** + * Represents the global instrumentation configuration consisting of system properties, environment + * variables, contents of the agent configuration file and properties defined by the {@code + * ConfigPropertySource} SPI implementations. + * + *

In case any {@code get*()} method variant gets called for the same property more than once + * (e.g. each time an advice class executes) it is suggested to cache the result instead of + * repeatedly calling {@link CoreInstrumentationConfig}. Instrumentation configuration does not + * change during the runtime so retrieving the property once and storing its result in a static + * final field allows JIT to do its magic and remove some code branches. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public interface CoreInstrumentationConfig { + + /** + * Returns a string-valued configuration property or {@code null} if a property with name {@code + * name} has not been configured. + */ + @Nullable + String getString(String name); + + /** + * Returns a string-valued configuration property or {@code defaultValue} if a property with name + * {@code name} has not been configured. + */ + String getString(String name, String defaultValue); + + /** + * Returns a boolean-valued configuration property or {@code defaultValue} if a property with name + * {@code name} has not been configured. + */ + boolean getBoolean(String name, boolean defaultValue); + + /** + * Returns an integer-valued configuration property or {@code defaultValue} if a property with + * name {@code name} has not been configured or when parsing has failed. + */ + int getInt(String name, int defaultValue); + + /** + * Returns a long-valued configuration property or {@code defaultValue} if a property with name + * {@code name} has not been configured or when parsing has failed. + */ + long getLong(String name, long defaultValue); + + /** + * Returns a double-valued configuration property or {@code defaultValue} if a property with name + * {@code name} has not been configured or when parsing has failed. + */ + double getDouble(String name, double defaultValue); + + /** + * Returns a duration-valued configuration property or {@code defaultValue} if a property with + * name {@code name} has not been configured or when parsing has failed. + * + *

Durations can be of the form "{number}{unit}", where unit is one of: + * + *

    + *
  • ms + *
  • s + *
  • m + *
  • h + *
  • d + *
+ * + *

If no unit is specified, milliseconds is the assumed duration unit. + * + *

Examples: 10s, 20ms, 5000 + */ + Duration getDuration(String name, Duration defaultValue); + + /** + * This is the same as calling {@code getList(String, List)} with the defaultValue equal to the + * emptyList()/ + */ + default List getList(String name) { + return getList(name, emptyList()); + } + + /** + * Returns a list-valued configuration property or {@code defaultValue} if a property with name + * {@code name} has not been configured. The format of the original value must be comma-separated, + * e.g. {@code one,two,three}. The returned list is unmodifiable. + */ + List getList(String name, List defaultValue); + + /** + * Returns a map-valued configuration property or {@code defaultValue} if a property with name + * {@code name} has not been configured or when parsing has failed. The format of the original + * value must be comma-separated for each key, with an '=' separating the key and value, e.g. + * {@code key=value,anotherKey=anotherValue}. The returned map is unmodifiable. + */ + Map getMap(String name, Map defaultValue); +} diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EnduserConfig.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/EnduserConfig.java similarity index 96% rename from javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EnduserConfig.java rename to instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/EnduserConfig.java index fbde1c90aaa2..9f56241aed18 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EnduserConfig.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/config/EnduserConfig.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.bootstrap.internal; +package io.opentelemetry.instrumentation.api.incubator.internal.config; import java.util.Objects; @@ -39,7 +39,7 @@ public class EnduserConfig { private final boolean roleEnabled; private final boolean scopeEnabled; - EnduserConfig(InstrumentationConfig instrumentationConfig) { + EnduserConfig(CoreInstrumentationConfig instrumentationConfig) { Objects.requireNonNull(instrumentationConfig, "instrumentationConfig must not be null"); /* diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/instrumenter/HttpClientInstrumenterBuilder.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/instrumenter/HttpClientInstrumenterBuilder.java new file mode 100644 index 000000000000..a2e12e1ed1f1 --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/internal/instrumenter/HttpClientInstrumenterBuilder.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.internal.instrumenter; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.instrumentation.api.incubator.builder.AbstractHttpClientTelemetryBuilder; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreCommonConfig; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class HttpClientInstrumenterBuilder { + private HttpClientInstrumenterBuilder() {} + + @CanIgnoreReturnValue + public static > T configure( + CoreCommonConfig config, T builder) { + set(config::getKnownHttpRequestMethods, builder::setKnownMethods); + set(config::getClientRequestHeaders, builder::setCapturedRequestHeaders); + set(config::getClientResponseHeaders, builder::setCapturedResponseHeaders); + set(config::getPeerServiceResolver, builder::setPeerServiceResolver); + set( + config::shouldEmitExperimentalHttpClientTelemetry, + builder::setEmitExperimentalHttpClientMetrics); + return builder; + } + + private static void set(Supplier supplier, Consumer consumer) { + T t = supplier.get(); + if (t != null) { + consumer.accept(t); + } + } +} diff --git a/instrumentation/external-annotations/javaagent-unit-tests/build.gradle.kts b/instrumentation/external-annotations/javaagent-unit-tests/build.gradle.kts index 364911c6d0df..7ce37d7de0b3 100644 --- a/instrumentation/external-annotations/javaagent-unit-tests/build.gradle.kts +++ b/instrumentation/external-annotations/javaagent-unit-tests/build.gradle.kts @@ -4,6 +4,7 @@ plugins { dependencies { testImplementation(project(":instrumentation-api")) + testImplementation(project(":instrumentation-api-incubator")) testImplementation(project(":javaagent-extension-api")) testImplementation(project(":javaagent-tooling")) testImplementation(project(":instrumentation:external-annotations:javaagent")) diff --git a/instrumentation/external-annotations/javaagent-unit-tests/src/test/java/io/opentelemetry/javaagent/instrumentation/extannotations/IncludeTest.java b/instrumentation/external-annotations/javaagent-unit-tests/src/test/java/io/opentelemetry/javaagent/instrumentation/extannotations/IncludeTest.java index b1f096ced00a..4344ffd61a60 100644 --- a/instrumentation/external-annotations/javaagent-unit-tests/src/test/java/io/opentelemetry/javaagent/instrumentation/extannotations/IncludeTest.java +++ b/instrumentation/external-annotations/javaagent-unit-tests/src/test/java/io/opentelemetry/javaagent/instrumentation/extannotations/IncludeTest.java @@ -9,7 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; @@ -25,7 +25,7 @@ @ExtendWith(MockitoExtension.class) class IncludeTest { - @Mock InstrumentationConfig config; + @Mock CoreInstrumentationConfig config; @ParameterizedTest @MethodSource("provideArguments") diff --git a/instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java b/instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java index 6b231d97aa5c..2e19864a8bdc 100644 --- a/instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java +++ b/instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java @@ -17,6 +17,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import io.opentelemetry.instrumentation.api.incubator.semconv.util.ClassAndMethod; import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; @@ -113,7 +114,7 @@ public void transform(TypeTransformer transformer) { } // visible for testing - static Set configureAdditionalTraceAnnotations(InstrumentationConfig config) { + static Set configureAdditionalTraceAnnotations(CoreInstrumentationConfig config) { String configString = config.getString(TRACE_ANNOTATIONS_CONFIG); if (configString == null) { return Collections.unmodifiableSet(new HashSet<>(DEFAULT_ANNOTATIONS)); diff --git a/instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java b/instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java index 3c228dafa1f5..5d3807e0673a 100644 --- a/instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java +++ b/instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java @@ -9,6 +9,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.logs.LogRecordBuilder; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import io.opentelemetry.instrumentation.log4j.appender.v2_17.internal.ContextDataAccessor; import io.opentelemetry.instrumentation.log4j.appender.v2_17.internal.LogEventMapper; import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; @@ -30,7 +31,7 @@ public final class Log4jHelper { private static final boolean captureExperimentalAttributes; static { - InstrumentationConfig config = InstrumentationConfig.get(); + CoreInstrumentationConfig config = InstrumentationConfig.get(); captureExperimentalAttributes = config.getBoolean("otel.instrumentation.log4j-appender.experimental-log-attributes", false); diff --git a/instrumentation/logback/logback-appender-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/appender/v1_0/LogbackSingletons.java b/instrumentation/logback/logback-appender-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/appender/v1_0/LogbackSingletons.java index 23d3ff8f44ab..981852c54cbf 100644 --- a/instrumentation/logback/logback-appender-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/appender/v1_0/LogbackSingletons.java +++ b/instrumentation/logback/logback-appender-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/appender/v1_0/LogbackSingletons.java @@ -7,6 +7,7 @@ import static java.util.Collections.emptyList; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import io.opentelemetry.instrumentation.logback.appender.v1_0.internal.LoggingEventMapper; import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import java.util.List; @@ -16,7 +17,7 @@ public final class LogbackSingletons { private static final LoggingEventMapper mapper; static { - InstrumentationConfig config = InstrumentationConfig.get(); + CoreInstrumentationConfig config = InstrumentationConfig.get(); boolean captureExperimentalAttributes = config.getBoolean( diff --git a/instrumentation/micrometer/micrometer-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/MicrometerSingletons.java b/instrumentation/micrometer/micrometer-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/MicrometerSingletons.java index 8416c35fe9f2..860dcb918024 100644 --- a/instrumentation/micrometer/micrometer-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/MicrometerSingletons.java +++ b/instrumentation/micrometer/micrometer-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/MicrometerSingletons.java @@ -7,6 +7,7 @@ import io.micrometer.core.instrument.MeterRegistry; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import io.opentelemetry.instrumentation.micrometer.v1_5.OpenTelemetryMeterRegistry; import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; @@ -15,7 +16,7 @@ public final class MicrometerSingletons { private static final MeterRegistry METER_REGISTRY; static { - InstrumentationConfig config = InstrumentationConfig.get(); + CoreInstrumentationConfig config = InstrumentationConfig.get(); METER_REGISTRY = OpenTelemetryMeterRegistry.builder(GlobalOpenTelemetry.get()) .setPrometheusMode( diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateBeanPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateBeanPostProcessor.java index 43d0c52bac38..096e97c83061 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateBeanPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateBeanPostProcessor.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.web.client.RestTemplate; @@ -14,8 +15,13 @@ final class RestTemplateBeanPostProcessor implements BeanPostProcessor { private final ObjectProvider openTelemetryProvider; - RestTemplateBeanPostProcessor(ObjectProvider openTelemetryProvider) { + private final ObjectProvider configPropertiesProvider; + + RestTemplateBeanPostProcessor( + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { this.openTelemetryProvider = openTelemetryProvider; + this.configPropertiesProvider = configPropertiesProvider; } @Override @@ -25,6 +31,8 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { } return RestTemplateInstrumentation.addIfNotPresent( - (RestTemplate) bean, openTelemetryProvider.getObject()); + (RestTemplate) bean, + openTelemetryProvider.getObject(), + configPropertiesProvider.getObject()); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateInstrumentation.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateInstrumentation.java index 58c266f09e8c..89f5b109bc82 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateInstrumentation.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateInstrumentation.java @@ -7,7 +7,10 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.internal.instrumenter.HttpClientInstrumenterBuilder; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.CommonConfigUtil; import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import java.util.List; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; @@ -17,9 +20,14 @@ class RestTemplateInstrumentation { private RestTemplateInstrumentation() {} @CanIgnoreReturnValue - static RestTemplate addIfNotPresent(RestTemplate restTemplate, OpenTelemetry openTelemetry) { + static RestTemplate addIfNotPresent( + RestTemplate restTemplate, OpenTelemetry openTelemetry, ConfigProperties config) { + ClientHttpRequestInterceptor instrumentationInterceptor = - SpringWebTelemetry.create(openTelemetry).newInterceptor(); + HttpClientInstrumenterBuilder.configure( + CommonConfigUtil.getCommonConfig(config), SpringWebTelemetry.builder(openTelemetry)) + .build() + .newInterceptor(); List restTemplateInterceptors = restTemplate.getInterceptors(); if (restTemplateInterceptors.stream() diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java index 961ee82fea13..7fed019fe527 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java @@ -7,6 +7,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.web.client.RestTemplateCustomizer; @@ -29,15 +30,17 @@ public SpringWebInstrumentationAutoConfiguration() {} // static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning @Bean static RestTemplateBeanPostProcessor otelRestTemplateBeanPostProcessor( - ObjectProvider openTelemetryProvider) { - return new RestTemplateBeanPostProcessor(openTelemetryProvider); + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { + return new RestTemplateBeanPostProcessor(openTelemetryProvider, configPropertiesProvider); } @Bean RestTemplateCustomizer otelRestTemplateCustomizer( - ObjectProvider openTelemetryProvider) { + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { return restTemplate -> RestTemplateInstrumentation.addIfNotPresent( - restTemplate, openTelemetryProvider.getObject()); + restTemplate, openTelemetryProvider.getObject(), configPropertiesProvider.getObject()); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/CommonConfigUtil.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/CommonConfigUtil.java new file mode 100644 index 000000000000..a02e281d5655 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/CommonConfigUtil.java @@ -0,0 +1,21 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties; + +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreCommonConfig; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class CommonConfigUtil { + private CommonConfigUtil() {} + + public static CoreCommonConfig getCommonConfig(ConfigProperties config) { + return new CoreCommonConfig(new ConfigPropertiesBridge(config)); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java new file mode 100644 index 000000000000..37a7bbbf9b4f --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java @@ -0,0 +1,109 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties; + +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; +import java.time.Duration; +import java.util.List; +import java.util.Map; +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. + */ +public final class ConfigPropertiesBridge implements CoreInstrumentationConfig { + + private final ConfigProperties configProperties; + + public ConfigPropertiesBridge(ConfigProperties configProperties) { + this.configProperties = configProperties; + } + + @Nullable + @Override + public String getString(String name) { + try { + return configProperties.getString(name); + } catch (ConfigurationException ignored) { + return null; + } + } + + @Override + public String getString(String name, String defaultValue) { + try { + return configProperties.getString(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public boolean getBoolean(String name, boolean defaultValue) { + try { + return configProperties.getBoolean(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public int getInt(String name, int defaultValue) { + try { + return configProperties.getInt(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public long getLong(String name, long defaultValue) { + try { + return configProperties.getLong(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public double getDouble(String name, double defaultValue) { + try { + return configProperties.getDouble(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public Duration getDuration(String name, Duration defaultValue) { + try { + return configProperties.getDuration(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public List getList(String name, List defaultValue) { + try { + return configProperties.getList(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public Map getMap(String name, Map defaultValue) { + try { + return configProperties.getMap(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 9bea00f40e19..1bd1e0c59f07 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -279,6 +279,33 @@ "description": "Enables the DB statement sanitization.", "defaultValue": true }, + { + "name": "otel.instrumentation.common.peer-service-mapping", + "type": "java.util.Map", + "description": "Used to specify a mapping from host names or IP addresses to peer services, as a comma-separated list of host_or_ip=user_assigned_name pairs. The peer service is added as an attribute to a span whose host or IP address match the mapping. See https://opentelemetry.io/docs/zero-code/java/agent/configuration/#peer-service-name." + }, + { + "name": "otel.instrumentation.http.client.capture-request-headers", + "type": "java.util.List", + "description": "List of HTTP request headers to capture in HTTP clients." + }, + { + "name": "otel.instrumentation.http.client.capture-response-headers", + "type": "java.util.List", + "description": "List of HTTP response headers to capture in HTTP clients." + }, + { + "name": "otel.instrumentation.http.client.emit-experimental-telemetry", + "type": "java.lang.Boolean", + "description": "Enable the capture of experimental HTTP client telemetry. Add the http.request.body.size and http.response.body.size> attributes to spans, and record the http.client.request.size and http.client.response.size metrics.", + "defaultValue": false + }, + { + "name": "otel.instrumentation.http.known-methods", + "type": "java.util.List", + "description": "Configures the instrumentation to recognize an alternative set of HTTP request methods. All other methods will be treated as _OTHER.", + "defaultValue": "CONNECT,DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,TRACE" + }, { "name": "otel.instrumentation.jdbc.enabled", "type": "java.lang.Boolean", diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java index 67b4e4e75a37..5dd0b973a345 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java @@ -8,6 +8,9 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import java.util.Collections; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -18,6 +21,9 @@ class SpringWebInstrumentationAutoConfigurationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) + .withBean( + ConfigProperties.class, + () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) .withBean(RestTemplate.class, RestTemplate::new) .withConfiguration( AutoConfigurations.of(SpringWebInstrumentationAutoConfiguration.class)); diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/CommonConfig.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/CommonConfig.java index f6d5a5479001..6ec149352bca 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/CommonConfig.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/CommonConfig.java @@ -5,127 +5,19 @@ package io.opentelemetry.javaagent.bootstrap.internal; -import static java.util.Collections.emptyMap; - -import io.opentelemetry.instrumentation.api.incubator.log.LoggingContextConstants; -import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceResolver; -import io.opentelemetry.instrumentation.api.internal.HttpConstants; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreCommonConfig; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ -public final class CommonConfig { +public class CommonConfig { + private CommonConfig() {} - private static final CommonConfig instance = new CommonConfig(InstrumentationConfig.get()); + private static final CoreCommonConfig instance = + new CoreCommonConfig(InstrumentationConfig.get()); - public static CommonConfig get() { + public static CoreCommonConfig get() { return instance; } - - private final PeerServiceResolver peerServiceResolver; - private final List clientRequestHeaders; - private final List clientResponseHeaders; - private final List serverRequestHeaders; - private final List serverResponseHeaders; - private final Set knownHttpRequestMethods; - private final EnduserConfig enduserConfig; - private final boolean statementSanitizationEnabled; - private final boolean emitExperimentalHttpClientTelemetry; - private final boolean emitExperimentalHttpServerTelemetry; - private final String loggingTraceIdKey; - private final String loggingSpanIdKey; - private final String loggingTraceFlagsKey; - - CommonConfig(InstrumentationConfig config) { - peerServiceResolver = - PeerServiceResolver.create( - config.getMap("otel.instrumentation.common.peer-service-mapping", emptyMap())); - - clientRequestHeaders = - config.getList("otel.instrumentation.http.client.capture-request-headers"); - clientResponseHeaders = - config.getList("otel.instrumentation.http.client.capture-response-headers"); - serverRequestHeaders = - config.getList("otel.instrumentation.http.server.capture-request-headers"); - serverResponseHeaders = - config.getList("otel.instrumentation.http.server.capture-response-headers"); - knownHttpRequestMethods = - new HashSet<>( - config.getList( - "otel.instrumentation.http.known-methods", - new ArrayList<>(HttpConstants.KNOWN_METHODS))); - statementSanitizationEnabled = - config.getBoolean("otel.instrumentation.common.db-statement-sanitizer.enabled", true); - emitExperimentalHttpClientTelemetry = - config.getBoolean("otel.instrumentation.http.client.emit-experimental-telemetry", false); - emitExperimentalHttpServerTelemetry = - config.getBoolean("otel.instrumentation.http.server.emit-experimental-telemetry", false); - enduserConfig = new EnduserConfig(config); - loggingTraceIdKey = - config.getString( - "otel.instrumentation.common.logging.trace-id", LoggingContextConstants.TRACE_ID); - loggingSpanIdKey = - config.getString( - "otel.instrumentation.common.logging.span-id", LoggingContextConstants.SPAN_ID); - loggingTraceFlagsKey = - config.getString( - "otel.instrumentation.common.logging.trace-flags", LoggingContextConstants.TRACE_FLAGS); - } - - public PeerServiceResolver getPeerServiceResolver() { - return peerServiceResolver; - } - - public List getClientRequestHeaders() { - return clientRequestHeaders; - } - - public List getClientResponseHeaders() { - return clientResponseHeaders; - } - - public List getServerRequestHeaders() { - return serverRequestHeaders; - } - - public List getServerResponseHeaders() { - return serverResponseHeaders; - } - - public Set getKnownHttpRequestMethods() { - return knownHttpRequestMethods; - } - - public EnduserConfig getEnduserConfig() { - return enduserConfig; - } - - public boolean isStatementSanitizationEnabled() { - return statementSanitizationEnabled; - } - - public boolean shouldEmitExperimentalHttpClientTelemetry() { - return emitExperimentalHttpClientTelemetry; - } - - public boolean shouldEmitExperimentalHttpServerTelemetry() { - return emitExperimentalHttpServerTelemetry; - } - - public String getTraceIdKey() { - return loggingTraceIdKey; - } - - public String getSpanIdKey() { - return loggingSpanIdKey; - } - - public String getTraceFlagsKey() { - return loggingTraceFlagsKey; - } } diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/DeprecatedConfigProperties.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/DeprecatedConfigProperties.java index 002bf787c99c..be9dd9247139 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/DeprecatedConfigProperties.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/DeprecatedConfigProperties.java @@ -8,6 +8,7 @@ import static java.util.Collections.emptyList; import static java.util.logging.Level.WARNING; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import java.util.List; import java.util.logging.Logger; @@ -21,7 +22,7 @@ public final class DeprecatedConfigProperties { private static final Logger logger = Logger.getLogger(DeprecatedConfigProperties.class.getName()); public static boolean getBoolean( - InstrumentationConfig config, + CoreInstrumentationConfig config, String deprecatedPropertyName, String newPropertyName, boolean defaultValue) { @@ -31,14 +32,14 @@ public static boolean getBoolean( } public static List getList( - InstrumentationConfig config, String deprecatedPropertyName, String newPropertyName) { + CoreInstrumentationConfig config, String deprecatedPropertyName, String newPropertyName) { warnIfUsed(config, deprecatedPropertyName, newPropertyName); List value = config.getList(deprecatedPropertyName, emptyList()); return config.getList(newPropertyName, value); } private static void warnIfUsed( - InstrumentationConfig config, String deprecatedPropertyName, String newPropertyName) { + CoreInstrumentationConfig config, String deprecatedPropertyName, String newPropertyName) { if (config.getString(deprecatedPropertyName) != null) { logger.log( WARNING, diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EmptyInstrumentationConfig.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EmptyInstrumentationConfig.java index ede916b3b6ad..1942c6aaa191 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EmptyInstrumentationConfig.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EmptyInstrumentationConfig.java @@ -5,12 +5,13 @@ package io.opentelemetry.javaagent.bootstrap.internal; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import java.time.Duration; import java.util.List; import java.util.Map; import javax.annotation.Nullable; -final class EmptyInstrumentationConfig extends InstrumentationConfig { +final class EmptyInstrumentationConfig implements CoreInstrumentationConfig { @Nullable @Override diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ExperimentalConfig.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ExperimentalConfig.java index fe3779ab2550..255ce114706b 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ExperimentalConfig.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ExperimentalConfig.java @@ -7,6 +7,7 @@ import static java.util.Collections.emptyList; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import java.util.List; /** @@ -18,7 +19,7 @@ public final class ExperimentalConfig { private static final ExperimentalConfig instance = new ExperimentalConfig(InstrumentationConfig.get()); - private final InstrumentationConfig config; + private final CoreInstrumentationConfig config; private final List messagingHeaders; /** Returns the global agent configuration. */ @@ -26,7 +27,7 @@ public static ExperimentalConfig get() { return instance; } - public ExperimentalConfig(InstrumentationConfig config) { + public ExperimentalConfig(CoreInstrumentationConfig config) { this.config = config; messagingHeaders = config.getList("otel.instrumentation.messaging.experimental.capture-headers", emptyList()); diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/InstrumentationConfig.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/InstrumentationConfig.java index fc4b7aabc6c2..fc1c7fb75095 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/InstrumentationConfig.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/InstrumentationConfig.java @@ -5,37 +5,24 @@ package io.opentelemetry.javaagent.bootstrap.internal; -import static java.util.Collections.emptyList; import static java.util.Objects.requireNonNull; -import java.time.Duration; -import java.util.List; -import java.util.Map; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import java.util.logging.Logger; -import javax.annotation.Nullable; /** - * Represents the global instrumentation configuration consisting of system properties, environment - * variables, contents of the agent configuration file and properties defined by the {@code - * ConfigPropertySource} SPI implementations. - * - *

In case any {@code get*()} method variant gets called for the same property more than once - * (e.g. each time an advice class executes) it is suggested to cache the result instead of - * repeatedly calling {@link InstrumentationConfig}. Instrumentation configuration does not change - * during the runtime so retrieving the property once and storing its result in a static final field - * allows JIT to do its magic and remove some code branches. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. */ -public abstract class InstrumentationConfig { +public class InstrumentationConfig { + private InstrumentationConfig() {} private static final Logger logger = Logger.getLogger(InstrumentationConfig.class.getName()); - private static final InstrumentationConfig DEFAULT = new EmptyInstrumentationConfig(); + private static final CoreInstrumentationConfig DEFAULT = new EmptyInstrumentationConfig(); // lazy initialized, so that javaagent can set it - private static volatile InstrumentationConfig instance = DEFAULT; + private static volatile CoreInstrumentationConfig instance = DEFAULT; /** * Sets the instrumentation configuration singleton. This method is only supposed to be called @@ -45,7 +32,7 @@ public abstract class InstrumentationConfig { *

This method is internal and is hence not for public use. Its API is unstable and can change * at any time. */ - public static void internalInitializeConfig(InstrumentationConfig config) { + public static void internalInitializeConfig(CoreInstrumentationConfig config) { if (instance != DEFAULT) { logger.warning("InstrumentationConfig#instance was already set earlier"); return; @@ -54,87 +41,7 @@ public static void internalInitializeConfig(InstrumentationConfig config) { } /** Returns the global instrumentation configuration. */ - public static InstrumentationConfig get() { + public static CoreInstrumentationConfig get() { return instance; } - - /** - * Returns a string-valued configuration property or {@code null} if a property with name {@code - * name} has not been configured. - */ - @Nullable - public abstract String getString(String name); - - /** - * Returns a string-valued configuration property or {@code defaultValue} if a property with name - * {@code name} has not been configured. - */ - public abstract String getString(String name, String defaultValue); - - /** - * Returns a boolean-valued configuration property or {@code defaultValue} if a property with name - * {@code name} has not been configured. - */ - public abstract boolean getBoolean(String name, boolean defaultValue); - - /** - * Returns an integer-valued configuration property or {@code defaultValue} if a property with - * name {@code name} has not been configured or when parsing has failed. - */ - public abstract int getInt(String name, int defaultValue); - - /** - * Returns a long-valued configuration property or {@code defaultValue} if a property with name - * {@code name} has not been configured or when parsing has failed. - */ - public abstract long getLong(String name, long defaultValue); - - /** - * Returns a double-valued configuration property or {@code defaultValue} if a property with name - * {@code name} has not been configured or when parsing has failed. - */ - public abstract double getDouble(String name, double defaultValue); - - /** - * Returns a duration-valued configuration property or {@code defaultValue} if a property with - * name {@code name} has not been configured or when parsing has failed. - * - *

Durations can be of the form "{number}{unit}", where unit is one of: - * - *

    - *
  • ms - *
  • s - *
  • m - *
  • h - *
  • d - *
- * - *

If no unit is specified, milliseconds is the assumed duration unit. - * - *

Examples: 10s, 20ms, 5000 - */ - public abstract Duration getDuration(String name, Duration defaultValue); - - /** - * This is the same as calling {@code getList(String, List)} with the defaultValue equal to the - * emptyList()/ - */ - public List getList(String name) { - return getList(name, emptyList()); - } - - /** - * Returns a list-valued configuration property or {@code defaultValue} if a property with name - * {@code name} has not been configured. The format of the original value must be comma-separated, - * e.g. {@code one,two,three}. The returned list is unmodifiable. - */ - public abstract List getList(String name, List defaultValue); - - /** - * Returns a map-valued configuration property or {@code defaultValue} if a property with name - * {@code name} has not been configured or when parsing has failed. The format of the original - * value must be comma-separated for each key, with an '=' separating the key and value, e.g. - * {@code key=value,anotherKey=anotherValue}. The returned map is unmodifiable. - */ - public abstract Map getMap(String name, Map defaultValue); } diff --git a/javaagent-tooling/build.gradle.kts b/javaagent-tooling/build.gradle.kts index 850f4382fe17..6043f1eb0d72 100644 --- a/javaagent-tooling/build.gradle.kts +++ b/javaagent-tooling/build.gradle.kts @@ -13,6 +13,7 @@ dependencies { implementation(project(":javaagent-extension-api")) implementation(project(":javaagent-tooling:javaagent-tooling-java9")) implementation(project(":instrumentation-api")) + implementation(project(":instrumentation-api-incubator")) implementation(project(":instrumentation-annotations-support")) implementation(project(":muzzle")) implementation(project(":sdk-autoconfigure-support")) diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigPropertiesBridge.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigPropertiesBridge.java index c690921de4a8..d0aa2c97eec5 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigPropertiesBridge.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigPropertiesBridge.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.tooling.config; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.api.incubator.internal.config.CoreInstrumentationConfig; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import java.time.Duration; @@ -13,7 +13,7 @@ import java.util.Map; import javax.annotation.Nullable; -public final class ConfigPropertiesBridge extends InstrumentationConfig { +public final class ConfigPropertiesBridge implements CoreInstrumentationConfig { private final ConfigProperties configProperties; diff --git a/muzzle/build.gradle.kts b/muzzle/build.gradle.kts index bd25aeff7ed8..5e8f5ff9b9f6 100644 --- a/muzzle/build.gradle.kts +++ b/muzzle/build.gradle.kts @@ -18,6 +18,7 @@ dependencies { implementation(project(":javaagent-bootstrap")) implementation(project(":instrumentation-api")) + implementation(project(":instrumentation-api-incubator")) implementation(project(":javaagent-extension-api")) // Used by byte-buddy but not brought in as a transitive dependency.