diff --git a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/checkstyle-suppressions.xml b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/checkstyle-suppressions.xml index 48b0ee4d0f7d..74979833a4bf 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/checkstyle-suppressions.xml +++ b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/checkstyle-suppressions.xml @@ -70,6 +70,12 @@ + + + + + + diff --git a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/AzureMonitorAutoConfigure.java b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/AzureMonitorAutoConfigure.java index 1a45e4b90e53..6cb20fc18023 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/AzureMonitorAutoConfigure.java +++ b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/AzureMonitorAutoConfigure.java @@ -3,6 +3,7 @@ package com.azure.monitor.opentelemetry.autoconfigure; +import com.azure.monitor.opentelemetry.autoconfigure.implementation.AzureMonitorConfigurableSamplerProvider; import com.azure.monitor.opentelemetry.autoconfigure.implementation.AzureMonitorLogRecordExporterProvider; import com.azure.monitor.opentelemetry.autoconfigure.implementation.AzureMonitorMetricExporterProvider; import com.azure.monitor.opentelemetry.autoconfigure.implementation.AzureMonitorExporterProviderKeys; @@ -56,6 +57,7 @@ public static void customize(AutoConfigurationCustomizer autoConfigurationCustom props.put("otel.traces.exporter", AzureMonitorExporterProviderKeys.EXPORTER_NAME); props.put("otel.metrics.exporter", AzureMonitorExporterProviderKeys.EXPORTER_NAME); props.put("otel.logs.exporter", AzureMonitorExporterProviderKeys.EXPORTER_NAME); + props.put("otel.traces.sampler", AzureMonitorConfigurableSamplerProvider.SAMPLER_NAME); props.put(AzureMonitorExporterProviderKeys.INTERNAL_USING_AZURE_MONITOR_EXPORTER_BUILDER, "true"); return props; }); diff --git a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/AiSemanticAttributes.java b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/AiSemanticAttributes.java index 5e8c2b180a25..f1cd77a40feb 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/AiSemanticAttributes.java +++ b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/AiSemanticAttributes.java @@ -46,7 +46,7 @@ public final class AiSemanticAttributes { public static final AttributeKey OPERATION_NAME = stringKey("applicationinsights.internal.operation_name"); - public static final AttributeKey SAMPLE_RATE = doubleKey("applicationinsights.internal.sample_rate"); + public static final AttributeKey SAMPLE_RATE = doubleKey("microsoft.sample_rate"); // marks whether a request is coming from a "real" user, or a "synthetic" user (e.g. a bot or // health check) diff --git a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/ApplicationInsightsSampler.java b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/ApplicationInsightsSampler.java new file mode 100644 index 000000000000..13fedf5b530a --- /dev/null +++ b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/ApplicationInsightsSampler.java @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) AutoRest Code Generator. + +package com.azure.monitor.opentelemetry.autoconfigure.implementation; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import io.opentelemetry.sdk.trace.samplers.SamplingDecision; +import io.opentelemetry.sdk.trace.samplers.SamplingResult; + +import java.util.List; + +public class ApplicationInsightsSampler implements Sampler { + + private final double percentage; + private final SamplingResult recordAndSample; + private final String description; + + public ApplicationInsightsSampler(double ratio) { + this.percentage = ratio * 100; + recordAndSample = new RecordAndSampleWithSampleRate(percentage); + description = "ApplicationInsightsSampler{" + ratio + "}"; + } + + @Override + public SamplingResult shouldSample( + Context parentContext, + String traceId, + String name, + SpanKind spanKind, + Attributes attributes, + List parentLinks) { + + if (shouldRecordAndSample(traceId)) { + return recordAndSample; + } + return SamplingResult.drop(); + } + + private static class RecordAndSampleWithSampleRate implements SamplingResult { + + private final Attributes attributes; + + RecordAndSampleWithSampleRate(double sampleRate) { + attributes = Attributes.builder().put(AiSemanticAttributes.SAMPLE_RATE, sampleRate).build(); + } + + @Override + public SamplingDecision getDecision() { + return SamplingDecision.RECORD_AND_SAMPLE; + } + + @Override + public Attributes getAttributes() { + return attributes; + } + } + + private boolean shouldRecordAndSample(String traceId) { + if (percentage == 100) { + // optimization, no need to calculate score + return true; + } + if (percentage == 0) { + // optimization, no need to calculate score + return false; + } + return SamplingScoreGeneratorV2.getSamplingScore(traceId) < percentage; + } + + @Override + public String getDescription() { + return description; + } +} diff --git a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/AzureMonitorConfigurableSamplerProvider.java b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/AzureMonitorConfigurableSamplerProvider.java new file mode 100644 index 000000000000..8cb04da72fb1 --- /dev/null +++ b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/AzureMonitorConfigurableSamplerProvider.java @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.monitor.opentelemetry.autoconfigure.implementation; + +import com.azure.monitor.opentelemetry.autoconfigure.AzureMonitorAutoConfigure; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider; +import io.opentelemetry.sdk.trace.samplers.Sampler; + +public class AzureMonitorConfigurableSamplerProvider implements ConfigurableSamplerProvider { + + public static final String SAMPLER_NAME = "azure_monitor"; + + @Override + public Sampler createSampler(ConfigProperties configProperties) { + if (configProperties.getBoolean(AzureMonitorExporterProviderKeys.INTERNAL_USING_AZURE_MONITOR_EXPORTER_BUILDER, + false)) { + double ratio = configProperties.getDouble("OTEL_TRACES_SAMPLER_ARG", 1); + return new ApplicationInsightsSampler(ratio); + } + throw new IllegalStateException( + getName() + " currently only supports usage via " + AzureMonitorAutoConfigure.class.getName()); + } + + @Override + public String getName() { + return SAMPLER_NAME; + } +} diff --git a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/module-info.java b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/module-info.java index 4d249d2d398f..ecfabfc856da 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/module-info.java +++ b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/module-info.java @@ -28,7 +28,9 @@ provides io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider with com.azure.monitor.opentelemetry.autoconfigure.implementation.AzureMonitorMetricExporterProvider; provides io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider - with com.azure.monitor.opentelemetry.autoconfigure.implementation.AzureMonitorSpanExporterProvider; + with com.azure.monitor.opentelemetry.autoconfigure.implementation.AzureMonitorSpanExporterProvider; + provides io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider + with com.azure.monitor.opentelemetry.autoconfigure.implementation.AzureMonitorConfigurableSamplerProvider; exports com.azure.monitor.opentelemetry.autoconfigure; diff --git a/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider new file mode 100644 index 000000000000..4d1f8ba50c5a --- /dev/null +++ b/sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider @@ -0,0 +1 @@ +com.azure.monitor.opentelemetry.autoconfigure.implementation.AzureMonitorConfigurableSamplerProvider