diff --git a/custom/src/main/java/co/elastic/otel/ElasticAutoConfigurationCustomizerProvider.java b/custom/src/main/java/co/elastic/otel/ElasticAutoConfigurationCustomizerProvider.java index a11bfdb1..95446f2d 100644 --- a/custom/src/main/java/co/elastic/otel/ElasticAutoConfigurationCustomizerProvider.java +++ b/custom/src/main/java/co/elastic/otel/ElasticAutoConfigurationCustomizerProvider.java @@ -18,7 +18,6 @@ */ package co.elastic.otel; -import co.elastic.otel.compositesampling.DynamicCompositeParentBasedTraceIdRatioBasedSampler; import co.elastic.otel.config.ConfigLoggingAgentListener; import co.elastic.otel.dynamicconfig.BlockableLogRecordExporter; import co.elastic.otel.dynamicconfig.BlockableMetricExporter; @@ -46,6 +45,7 @@ public class ElasticAutoConfigurationCustomizerProvider "otel.instrumentation.runtime-telemetry.emit-experimental-telemetry"; private static final String METRIC_TEMPORALITY_PREFERENCE = "otel.exporter.otlp.metrics.temporality.preference"; + private static final String TRACES_SAMPLER = "otel.traces.sampler"; // must match value in io.opentelemetry.contrib.stacktrace.StackTraceAutoConfig private static final String STACKTRACE_OTEL_FILTER = @@ -93,7 +93,6 @@ public void customize(AutoConfigurationCustomizer autoConfiguration) { (providerBuilder, properties) -> { CentralConfig.init(providerBuilder, properties); AgentLog.addSpanLoggingIfRequired(providerBuilder, properties); - providerBuilder.setSampler(DynamicCompositeParentBasedTraceIdRatioBasedSampler.INSTANCE); return providerBuilder; }); } @@ -105,6 +104,7 @@ static Map propertiesCustomizer(ConfigProperties configPropertie deltaMetricsTemporality(config, configProperties); resourceProviders(config, configProperties); spanStackTrace(config, configProperties); + defaultSampler(config, configProperties); ConfigLoggingAgentListener.logTheConfig( configProperties.getBoolean(ConfigLoggingAgentListener.LOG_THE_CONFIG, true)); @@ -151,6 +151,15 @@ private static void resourceProviders( config.put(DISABLED_RESOURCE_PROVIDERS, String.join(",", disabledResourceProviders)); } + private static void defaultSampler( + Map config, ConfigProperties configProperties) { + // enable EDOT default sampler by default if not explicitly disabled + String sampler = + configProperties.getString( + TRACES_SAMPLER, "experimental_composite_parentbased_traceidratio"); + config.put(TRACES_SAMPLER, sampler); + } + private static void spanStackTrace( Map config, ConfigProperties configProperties) { diff --git a/custom/src/main/java/co/elastic/otel/config/ConfigLoggingAgentListener.java b/custom/src/main/java/co/elastic/otel/config/ConfigLoggingAgentListener.java index 1029e399..a047869d 100644 --- a/custom/src/main/java/co/elastic/otel/config/ConfigLoggingAgentListener.java +++ b/custom/src/main/java/co/elastic/otel/config/ConfigLoggingAgentListener.java @@ -18,6 +18,7 @@ */ package co.elastic.otel.config; +import co.elastic.otel.compositesampling.DynamicCompositeParentBasedTraceIdRatioBasedSampler; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.AgentListener; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; @@ -27,6 +28,9 @@ public class ConfigLoggingAgentListener implements AgentListener { public static final String LOG_THE_CONFIG = "elastic.otel.java.experimental.configuration.logging.enabled"; + + private static volatile boolean enableDynamicSamplingRate = false; + private static final Logger logger = Logger.getLogger(ConfigLoggingAgentListener.class.getName()); private static boolean logTheConfig = true; @@ -35,11 +39,19 @@ public static synchronized void logTheConfig(boolean logTheConfig) { ConfigLoggingAgentListener.logTheConfig = logTheConfig; } + public static boolean getEnableDynamicSamplingRate() { + return enableDynamicSamplingRate; + } + @Override public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { if (logTheConfig) { logger.info(autoConfiguredOpenTelemetrySdk.toString()); } + if (autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk().getSdkTracerProvider().getSampler() + instanceof DynamicCompositeParentBasedTraceIdRatioBasedSampler) { + enableDynamicSamplingRate = true; + } } @Override diff --git a/custom/src/main/java/co/elastic/otel/dynamicconfig/CentralConfig.java b/custom/src/main/java/co/elastic/otel/dynamicconfig/CentralConfig.java index 9cee1555..7ede7b40 100644 --- a/custom/src/main/java/co/elastic/otel/dynamicconfig/CentralConfig.java +++ b/custom/src/main/java/co/elastic/otel/dynamicconfig/CentralConfig.java @@ -19,6 +19,7 @@ package co.elastic.otel.dynamicconfig; import co.elastic.otel.compositesampling.DynamicCompositeParentBasedTraceIdRatioBasedSampler; +import co.elastic.otel.config.ConfigLoggingAgentListener; import co.elastic.otel.dynamicconfig.internal.OpampManager; import co.elastic.otel.logging.AgentLog; import io.opentelemetry.contrib.inferredspans.InferredSpans; @@ -311,6 +312,10 @@ public static final class SamplingRate extends ConfigOption { @Override void update(String configurationValue, OpampManager opampManager) throws IllegalArgumentException { + if (!ConfigLoggingAgentListener.getEnableDynamicSamplingRate()) { + logger.warning("ignoring \"sampling_rate\" because non-default sampler in use"); + return; + } DynamicCompositeParentBasedTraceIdRatioBasedSampler.setRatio( Double.parseDouble(configurationValue)); } diff --git a/custom/src/test/java/co/elastic/otel/ElasticAutoConfigurationCustomizerProviderTest.java b/custom/src/test/java/co/elastic/otel/ElasticAutoConfigurationCustomizerProviderTest.java index 974fdf6d..42aff53e 100644 --- a/custom/src/test/java/co/elastic/otel/ElasticAutoConfigurationCustomizerProviderTest.java +++ b/custom/src/test/java/co/elastic/otel/ElasticAutoConfigurationCustomizerProviderTest.java @@ -52,6 +52,10 @@ void defaultConfiguration() { .describedAs("runtime experimental metrics must be enabled") .containsEntry( "otel.instrumentation.runtime-telemetry.emit-experimental-telemetry", "true"); + + assertThat(config) + .describedAs("edot default sampler when not set by user") + .containsEntry("otel.traces.sampler", "experimental_composite_parentbased_traceidratio"); } @Test @@ -98,6 +102,16 @@ void customizeMetricTemporalityPreference() { assertThat(value).isEqualTo("LOWMEMORY"); } + @Test + void customizeSampler() { + Map userConfig = new HashMap<>(); + userConfig.put("otel.traces.sampler", "always_off"); + Map config = + propertiesCustomizer(DefaultConfigProperties.createFromMap(userConfig)); + String value = config.get("otel.traces.sampler"); + assertThat(value).isEqualTo("always_off"); + } + @Test void verifyDefaultTemporalityOverriddenToDelta() { try (OpenTelemetrySdk sdk =