Skip to content

Commit ae3b5a3

Browse files
authored
Introduce explicit preview option to disable ingestion sampling (#3713)
1 parent 233328f commit ae3b5a3

File tree

21 files changed

+191
-98
lines changed

21 files changed

+191
-98
lines changed

.github/workflows/build-common.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
required: false
99

1010
env:
11-
EXPORTER_VERSION: 1.0.0-beta.23 # to be updated with the latest version
11+
EXPORTER_VERSION: 1.0.0-beta.24 # to be updated with the latest version
1212

1313
jobs:
1414
spotless:

agent/agent-tooling/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ dependencies {
2121
implementation(project(":agent:agent-profiler:agent-diagnostics"))
2222
implementation(project(":etw:java"))
2323

24-
implementation("com.azure:azure-monitor-opentelemetry-exporter:1.0.0-beta.23")
24+
implementation("com.azure:azure-monitor-opentelemetry-exporter:1.0.0-beta.24")
2525
compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-bootstrap")
2626
compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling")
2727
compileOnly("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-servlet-common-bootstrap")

agent/agent-tooling/gradle.lockfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ com.azure:azure-core-http-netty:1.14.2=runtimeClasspath
99
com.azure:azure-core:1.48.0=runtimeClasspath
1010
com.azure:azure-identity:1.12.1=runtimeClasspath
1111
com.azure:azure-json:1.1.0=runtimeClasspath
12-
com.azure:azure-monitor-opentelemetry-exporter:1.0.0-beta.23=runtimeClasspath
12+
com.azure:azure-monitor-opentelemetry-exporter:1.0.0-beta.24=runtimeClasspath
1313
com.azure:azure-sdk-bom:1.2.23=runtimeClasspath
1414
com.azure:azure-storage-blob:12.25.4=runtimeClasspath
1515
com.azure:azure-storage-common:12.24.4=runtimeClasspath

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/classicsdk/BytecodeUtilImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,9 @@ private static void track(
506506
}
507507

508508
if (isPartOfTheCurrentTrace && applySampling && span instanceof ReadableSpan) {
509-
Long itemCount = ((ReadableSpan) span).getAttribute(AiSemanticAttributes.ITEM_COUNT);
510-
if (itemCount != null) {
511-
telemetryBuilder.setSampleRate(100.0f / itemCount);
509+
Double sampleRate = ((ReadableSpan) span).getAttribute(AiSemanticAttributes.SAMPLE_RATE);
510+
if (sampleRate != null) {
511+
telemetryBuilder.setSampleRate(sampleRate.floatValue());
512512
}
513513
}
514514

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/configuration/Configuration.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,13 @@ public static class Role {
159159

160160
public static class Sampling {
161161

162-
// fixed percentage of requests
163-
@Nullable public Double percentage;
164-
165162
// default is 5 requests per second (set in ConfigurationBuilder if neither percentage nor
166163
// requestsPerSecond was configured)
167164
@Nullable public Double requestsPerSecond;
168165

166+
// fixed percentage of requests
167+
@Nullable public Double percentage;
168+
169169
// this config option only existed in one BETA release (3.4.0-BETA)
170170
@Deprecated @Nullable public Double limitPerSecond;
171171

@@ -202,6 +202,8 @@ public static class SamplingPreview {
202202
// future goal: make parentBased sampling the default if item count is received via tracestate
203203
public boolean parentBased;
204204

205+
public boolean ingestionSamplingEnabled = true;
206+
205207
@Deprecated public List<SamplingOverride> overrides = new ArrayList<>();
206208
}
207209

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/configuration/ConfigurationBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ private static void logConfigurationWarnings(Configuration config) {
269269
+ "If you're on premise, you can use APPLICATIONINSIGHTS_AUTHENTICATION_STRING environment variable to pass the client ID and secret, "
270270
+ "e.g. APPLICATIONINSIGHTS_AUTHENTICATION_STRING=Authorization=AAD;ClientId={CLIENT_ID};ClientSecret={CLIENT_SECRET}.");
271271
}
272-
if (config.sampling.percentage != null && config.sampling.requestsPerSecond != null) {
272+
if (config.sampling.requestsPerSecond != null && config.sampling.percentage != null) {
273273
configurationLogger.warn(
274274
"Sampling \"requestsPerSecond\" and \"percentage\" should not be used at the same time."
275275
+ " Please remove one of them.");

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/exporter/AgentLogExporter.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,7 @@ public CompletableResultCode export(Collection<LogRecordData> logs) {
105105
continue;
106106
}
107107

108-
Long itemCount = null;
109-
if (samplingPercentage != null) {
110-
// samplingPercentage cannot be 0 here
111-
itemCount = Math.round(100.0 / samplingPercentage);
112-
}
113-
114-
TelemetryItem telemetryItem = mapper.map(log, stack, itemCount);
108+
TelemetryItem telemetryItem = mapper.map(log, stack, samplingPercentage);
115109
telemetryItemConsumer.accept(telemetryItem);
116110

117111
exportingLogLogger.recordSuccess();

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureMonitorLogProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ public void onEmit(Context context, ReadWriteLogRecord logRecord) {
4040
ReadableSpan readableSpan = (ReadableSpan) currentSpan;
4141
logRecord.setAttribute(
4242
AiSemanticAttributes.OPERATION_NAME, OperationNames.getOperationName(readableSpan));
43-
Long itemCount = readableSpan.getAttribute(AiSemanticAttributes.ITEM_COUNT);
44-
if (itemCount != null) {
45-
logRecord.setAttribute(AiSemanticAttributes.ITEM_COUNT, itemCount);
43+
Double sampleRate = readableSpan.getAttribute(AiSemanticAttributes.SAMPLE_RATE);
44+
if (sampleRate != null) {
45+
logRecord.setAttribute(AiSemanticAttributes.SAMPLE_RATE, sampleRate);
4646
}
4747
}
4848

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/sampling/AiSampler.java

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,34 @@
2727
// * adds item count to span attribute if it is sampled
2828
public class AiSampler implements Sampler {
2929

30+
private static final double SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING = 99.99;
31+
32+
private final boolean ingestionSamplingEnabled;
3033
private final boolean localParentBased;
3134
private final SamplingPercentage requestSamplingPercentage;
3235
// when localParentBased=false, then this applies to all dependencies, not only parentless
3336
private final SamplingPercentage parentlessDependencySamplingPercentage;
34-
private final Cache<Long, SamplingResult> recordAndSampleWithItemCountMap = Cache.bounded(100);
37+
private final Cache<Double, SamplingResult> recordAndSampleWithSampleRateMap = Cache.bounded(100);
3538

3639
public AiSampler(
3740
SamplingPercentage requestSamplingPercentage,
38-
SamplingPercentage parentlessDependencySamplingPercentage) {
39-
this(requestSamplingPercentage, parentlessDependencySamplingPercentage, true);
41+
SamplingPercentage parentlessDependencySamplingPercentage,
42+
boolean ingestionSamplingEnabled) {
43+
this(
44+
requestSamplingPercentage,
45+
parentlessDependencySamplingPercentage,
46+
ingestionSamplingEnabled,
47+
true);
4048
}
4149

4250
public AiSampler(
4351
SamplingPercentage requestSamplingPercentage,
4452
SamplingPercentage parentlessDependencySamplingPercentage,
53+
boolean ingestionSamplingEnabled,
4554
boolean localParentBased) {
4655
this.requestSamplingPercentage = requestSamplingPercentage;
4756
this.parentlessDependencySamplingPercentage = parentlessDependencySamplingPercentage;
57+
this.ingestionSamplingEnabled = ingestionSamplingEnabled;
4858
this.localParentBased = localParentBased;
4959
}
5060

@@ -76,24 +86,29 @@ public SamplingResult shouldSample(
7686
: parentlessDependencySamplingPercentage.get();
7787
}
7888

79-
if (sp == SamplingPercentage.USE_INGESTION_SAMPLING) {
80-
return SamplingResult.recordAndSample();
81-
}
82-
8389
if (sp == 0) {
8490
return SamplingResult.drop();
8591
}
8692

87-
if (!shouldRecordAndSample(traceId, sp)) {
93+
if (sp != 100 && !shouldRecordAndSample(traceId, sp)) {
8894
return SamplingResult.drop();
8995
}
9096

91-
// sp cannot be 0 here
92-
long itemCount = Math.round(100.0 / sp);
93-
SamplingResult samplingResult = recordAndSampleWithItemCountMap.get(itemCount);
97+
if (sp == 100 && ingestionSamplingEnabled) {
98+
return SamplingResult.recordAndSample();
99+
}
100+
101+
if (sp == 100) {
102+
// ingestion sampling is applied when sample rate is 100 (or missing)
103+
// so we set it to 99.99 which will bypass ingestion sampling
104+
// (and will still be stored as item count 1)
105+
sp = SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING;
106+
}
107+
108+
SamplingResult samplingResult = recordAndSampleWithSampleRateMap.get(sp);
94109
if (samplingResult == null) {
95-
samplingResult = new RecordAndSampleWithItemCount(itemCount);
96-
recordAndSampleWithItemCountMap.put(itemCount, samplingResult);
110+
samplingResult = new RecordAndSampleWithItemCount(sp);
111+
recordAndSampleWithSampleRateMap.put(sp, samplingResult);
97112
}
98113
return samplingResult;
99114
}
@@ -112,9 +127,10 @@ private static SamplingResult useLocalParentDecisionIfPossible(Context parentCon
112127
return SamplingResult.drop();
113128
}
114129
if (parentSpan instanceof ReadableSpan) {
115-
Long itemCount = ((ReadableSpan) parentSpan).getAttribute(AiSemanticAttributes.ITEM_COUNT);
116-
if (itemCount != null) {
117-
return new RecordAndSampleWithItemCount(itemCount);
130+
Double parentSampleRate =
131+
((ReadableSpan) parentSpan).getAttribute(AiSemanticAttributes.SAMPLE_RATE);
132+
if (parentSampleRate != null) {
133+
return new RecordAndSampleWithItemCount(parentSampleRate);
118134
}
119135
}
120136
return null;
@@ -141,8 +157,8 @@ private static class RecordAndSampleWithItemCount implements SamplingResult {
141157

142158
private final Attributes attributes;
143159

144-
RecordAndSampleWithItemCount(long itemCount) {
145-
attributes = Attributes.builder().put(AiSemanticAttributes.ITEM_COUNT, itemCount).build();
160+
RecordAndSampleWithItemCount(double sampleRate) {
161+
attributes = Attributes.builder().put(AiSemanticAttributes.SAMPLE_RATE, sampleRate).build();
146162
}
147163

148164
@Override

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/sampling/Samplers.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@ public static Sampler getSampler(
1818
SamplingPercentage requestSamplingPercentage =
1919
SamplingPercentage.rateLimited(sampling.requestsPerSecond);
2020
SamplingPercentage parentlessDependencySamplingPercentage = SamplingPercentage.fixed(100);
21-
sampler = new AiSampler(requestSamplingPercentage, parentlessDependencySamplingPercentage);
21+
sampler =
22+
new AiSampler(
23+
requestSamplingPercentage,
24+
parentlessDependencySamplingPercentage,
25+
samplingPreview.ingestionSamplingEnabled);
2226
} else if (sampling.percentage != null) {
23-
SamplingPercentage samplingPercentage;
24-
if (sampling.percentage == 100) {
25-
samplingPercentage = SamplingPercentage.useIngestionSampling();
26-
} else {
27-
samplingPercentage = SamplingPercentage.fixed(sampling.percentage);
28-
}
29-
sampler = new AiSampler(samplingPercentage, samplingPercentage);
27+
SamplingPercentage samplingPercentage = SamplingPercentage.fixed(sampling.percentage);
28+
sampler =
29+
new AiSampler(
30+
samplingPercentage, samplingPercentage, samplingPreview.ingestionSamplingEnabled);
3031
} else {
3132
throw new AssertionError("ConfigurationBuilder should have set the default sampling");
3233
}

0 commit comments

Comments
 (0)