diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstaller.java index b51fa03a3a95..0e477d386399 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstaller.java @@ -5,7 +5,10 @@ package io.opentelemetry.javaagent.tooling; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; + import io.opentelemetry.api.incubator.config.ConfigProvider; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.instrumentation.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.javaagent.bootstrap.OpenTelemetrySdkAccess; import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig; @@ -13,6 +16,8 @@ import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess; import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.common.CompletableResultCode; import java.util.Arrays; @@ -44,22 +49,49 @@ public static AutoConfiguredOpenTelemetrySdk installOpenTelemetrySdk( return SdkAutoconfigureAccess.create( sdk, SdkAutoconfigureAccess.getResource(autoConfiguredSdk), - new DeclarativeConfigPropertiesBridgeBuilder() - .addMapping("otel.javaagent", "agent") - // these properties are used to initialize the SDK before the configuration file - // is loaded for consistency, we pass them to the bridge, so that they can be read - // later with the same value from the {@link DeclarativeConfigPropertiesBridge} - .addOverride( - "otel.javaagent.debug", earlyConfig.getBoolean("otel.javaagent.debug", false)) - .addOverride( - "otel.javaagent.logging", earlyConfig.getString("otel.javaagent.logging")) - .buildFromInstrumentationConfig(configProvider.getInstrumentationConfig()), + getDeclarativeConfigBridgedProperties(earlyConfig, configProvider), configProvider); } return autoConfiguredSdk; } + // Visible for testing + static ConfigProperties getDeclarativeConfigBridgedProperties( + EarlyInitAgentConfig earlyConfig, ConfigProvider configProvider) { + return new DeclarativeConfigPropertiesBridgeBuilder() + .addMapping("otel.javaagent", "agent") + .addOverride("otel.instrumentation.common.default-enabled", defaultEnabled(configProvider)) + // these properties are used to initialize the SDK before the configuration file + // is loaded for consistency, we pass them to the bridge, so that they can be read + // later with the same value from the {@link DeclarativeConfigPropertiesBridge} + .addOverride("otel.javaagent.debug", earlyConfig.getBoolean("otel.javaagent.debug", false)) + .addOverride("otel.javaagent.logging", earlyConfig.getString("otel.javaagent.logging")) + .buildFromInstrumentationConfig(configProvider.getInstrumentationConfig()); + } + + private static boolean defaultEnabled(ConfigProvider configProvider) { + DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); + if (instrumentationConfig == null) { + return true; + } + + String profile = + instrumentationConfig + .getStructured("java", empty()) + .getStructured("agent", empty()) + .getString("instrumentation_mode", "default"); + + switch (profile) { + case "none": + return false; + case "default": + return true; + default: + throw new ConfigurationException("Unknown instrumentation profile: " + profile); + } + } + private static void setForceFlush(OpenTelemetrySdk sdk) { OpenTelemetrySdkAccess.internalSetForceFlush( (timeout, unit) -> { diff --git a/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstallerTest.java b/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstallerTest.java index 268f4b40ccc7..af34bc3727d9 100644 --- a/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstallerTest.java +++ b/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstallerTest.java @@ -6,14 +6,24 @@ package io.opentelemetry.javaagent.tooling; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.util.function.Supplier; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; class OpenTelemetryInstallerTest { @@ -31,4 +41,43 @@ void globalOpenTelemetry() { assertThat(sdk).isNotNull().isNotEqualTo(OpenTelemetry.noop()); } + + @ParameterizedTest + @CsvSource({ + "default, true, false", + "none, false, false", + ", true, false", // empty value means property is not set + "invalid, false, true", + }) + void defaultEnabledInDeclarativeConfigPropertiesBridge( + String propertyValue, boolean expected, boolean fail) { + String profile = propertyValue == null ? "" : "instrumentation_mode: \"" + propertyValue + "\""; + String yaml = + "file_format: \"1.0-rc.1\"\n" + + "instrumentation/development:\n" + + " java:\n" + + " agent:\n" + + " " + + profile; + + Supplier configPropertiesSupplier = + () -> + OpenTelemetryInstaller.getDeclarativeConfigBridgedProperties( + EarlyInitAgentConfig.create(), + SdkConfigProvider.create( + DeclarativeConfiguration.parse( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))))); + + if (fail) { + assertThatCode(() -> configPropertiesSupplier.get()) + .isInstanceOf(ConfigurationException.class) + .hasMessage("Unknown instrumentation profile: invalid"); + } else { + assertThat( + configPropertiesSupplier + .get() + .getBoolean("otel.instrumentation.common.default-enabled")) + .isEqualTo(expected); + } + } }