declarative config: map common-enabled (#14589)

Co-authored-by: otelbot <197425009+otelbot@users.noreply.github.com>
This commit is contained in:
Gregor Zeitlinger 2025-09-11 17:05:44 +02:00 committed by GitHub
parent 1304ae8b7f
commit bf7c9645f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 91 additions and 10 deletions

View File

@ -5,7 +5,10 @@
package io.opentelemetry.javaagent.tooling; 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.ConfigProvider;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.instrumentation.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.instrumentation.config.bridge.DeclarativeConfigPropertiesBridgeBuilder;
import io.opentelemetry.javaagent.bootstrap.OpenTelemetrySdkAccess; import io.opentelemetry.javaagent.bootstrap.OpenTelemetrySdkAccess;
import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig; import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
@ -13,6 +16,8 @@ import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess; import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess;
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; 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 io.opentelemetry.sdk.common.CompletableResultCode;
import java.util.Arrays; import java.util.Arrays;
@ -44,22 +49,49 @@ public final class OpenTelemetryInstaller {
return SdkAutoconfigureAccess.create( return SdkAutoconfigureAccess.create(
sdk, sdk,
SdkAutoconfigureAccess.getResource(autoConfiguredSdk), SdkAutoconfigureAccess.getResource(autoConfiguredSdk),
new DeclarativeConfigPropertiesBridgeBuilder() getDeclarativeConfigBridgedProperties(earlyConfig, configProvider),
.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()),
configProvider); configProvider);
} }
return autoConfiguredSdk; 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) { private static void setForceFlush(OpenTelemetrySdk sdk) {
OpenTelemetrySdkAccess.internalSetForceFlush( OpenTelemetrySdkAccess.internalSetForceFlush(
(timeout, unit) -> { (timeout, unit) -> {

View File

@ -6,14 +6,24 @@
package io.opentelemetry.javaagent.tooling; package io.opentelemetry.javaagent.tooling;
import static org.assertj.core.api.Assertions.assertThat; 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.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig; import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; 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.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
class OpenTelemetryInstallerTest { class OpenTelemetryInstallerTest {
@ -31,4 +41,43 @@ class OpenTelemetryInstallerTest {
assertThat(sdk).isNotNull().isNotEqualTo(OpenTelemetry.noop()); 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<ConfigProperties> 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);
}
}
} }