Skip to content

Commit 70579e2

Browse files
committed
up
1 parent bc7348b commit 70579e2

File tree

7 files changed

+204
-147
lines changed

7 files changed

+204
-147
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.TelemetryItem;
1212
import com.azure.monitor.opentelemetry.autoconfigure.implementation.quickpulse.QuickPulse;
1313
import com.microsoft.applicationinsights.agent.internal.configuration.Configuration.SamplingOverride;
14-
import com.microsoft.applicationinsights.agent.internal.sampling.AiSampler;
14+
import com.microsoft.applicationinsights.agent.internal.sampling.AiSamplerForOverride;
1515
import com.microsoft.applicationinsights.agent.internal.sampling.SamplingOverrides;
1616
import com.microsoft.applicationinsights.agent.internal.telemetry.BatchItemProcessor;
1717
import com.microsoft.applicationinsights.agent.internal.telemetry.TelemetryClient;
@@ -113,7 +113,7 @@ private CompletableResultCode internalExport(Collection<LogRecordData> logs) {
113113
SpanContext spanContext = log.getSpanContext();
114114
Double parentSpanSampleRate = log.getAttributes().get(AiSemanticAttributes.SAMPLE_RATE);
115115

116-
AiSampler sampler = samplingOverrides.getOverride(log.getAttributes());
116+
AiSamplerForOverride sampler = samplingOverrides.getOverride(log.getAttributes());
117117

118118
if (sampler == null && spanContext.isValid() && !spanContext.getTraceFlags().isSampled()) {
119119
// if there is no sampling override, and the log is part of an unsampled trace, then don't

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
package com.microsoft.applicationinsights.agent.internal.exporter;
55

6-
import com.microsoft.applicationinsights.agent.internal.sampling.AiSampler;
6+
import com.microsoft.applicationinsights.agent.internal.sampling.SamplerUtil;
77
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
88
import io.opentelemetry.api.trace.SpanContext;
99
import java.util.concurrent.ThreadLocalRandom;
@@ -23,7 +23,7 @@ public static boolean shouldSample(SpanContext spanContext, double percentage) {
2323
return false;
2424
}
2525
if (spanContext.isValid()) {
26-
return AiSampler.shouldRecordAndSample(spanContext.getTraceId(), percentage);
26+
return SamplerUtil.shouldRecordAndSample(spanContext.getTraceId(), percentage);
2727
}
2828
// this is a standalone log (not part of a trace), so randomly sample at the given percentage
2929
return ThreadLocalRandom.current().nextDouble() < percentage / 100;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import com.microsoft.applicationinsights.agent.internal.processors.LogExporterWithAttributeProcessor;
4646
import com.microsoft.applicationinsights.agent.internal.processors.SpanExporterWithAttributeProcessor;
4747
import com.microsoft.applicationinsights.agent.internal.profiler.triggers.AlertTriggerSpanProcessor;
48-
import com.microsoft.applicationinsights.agent.internal.sampling.AiSampler;
48+
import com.microsoft.applicationinsights.agent.internal.sampling.AiSamplerForOverride;
4949
import com.microsoft.applicationinsights.agent.internal.sampling.SamplingOverrides;
5050
import com.microsoft.applicationinsights.agent.internal.telemetry.BatchItemProcessor;
5151
import com.microsoft.applicationinsights.agent.internal.telemetry.MetricFilter;
@@ -581,7 +581,8 @@ private static SpanExporter createSpanExporter(
581581
return false;
582582
},
583583
(span, event) -> {
584-
AiSampler sampler = exceptionSamplingOverrides.getOverride(event.getAttributes());
584+
AiSamplerForOverride sampler =
585+
exceptionSamplingOverrides.getOverride(event.getAttributes());
585586
return sampler != null
586587
&& sampler
587588
.shouldSampleLog(

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

Lines changed: 6 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,14 @@
55

66
import com.azure.monitor.opentelemetry.autoconfigure.implementation.AiSemanticAttributes;
77
import com.azure.monitor.opentelemetry.autoconfigure.implementation.RequestChecker;
8-
import com.azure.monitor.opentelemetry.autoconfigure.implementation.SamplingScoreGeneratorV2;
98
import io.opentelemetry.api.common.Attributes;
109
import io.opentelemetry.api.trace.Span;
1110
import io.opentelemetry.api.trace.SpanContext;
1211
import io.opentelemetry.api.trace.SpanKind;
1312
import io.opentelemetry.context.Context;
14-
import io.opentelemetry.instrumentation.api.internal.cache.Cache;
1513
import io.opentelemetry.sdk.trace.ReadableSpan;
1614
import io.opentelemetry.sdk.trace.data.LinkData;
1715
import io.opentelemetry.sdk.trace.samplers.Sampler;
18-
import io.opentelemetry.sdk.trace.samplers.SamplingDecision;
1916
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
2017
import java.util.List;
2118
import javax.annotation.Nullable;
@@ -27,14 +24,9 @@
2724
// * adds item count to span attribute if it is sampled
2825
public class AiSampler implements Sampler {
2926

30-
private static final double SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING = 99.99;
31-
3227
private final SamplingPercentage requestSamplingPercentage;
3328
private final SamplingPercentage parentlessDependencySamplingPercentage;
3429
private final boolean ingestionSamplingEnabled;
35-
private final boolean override;
36-
37-
private final Cache<Double, SamplingResult> recordAndSampleWithSampleRateMap = Cache.bounded(100);
3830

3931
public static AiSampler create(
4032
SamplingPercentage requestSamplingPercentage,
@@ -43,26 +35,16 @@ public static AiSampler create(
4335
return new AiSampler(
4436
requestSamplingPercentage,
4537
parentlessDependencySamplingPercentage,
46-
ingestionSamplingEnabled,
47-
false);
48-
}
49-
50-
public static AiSampler createSamplingOverride(
51-
SamplingPercentage samplingPercentage,
52-
boolean sampleWhenLocalParentSampled,
53-
boolean dropWhenLocalParentDropped) {
54-
return new AiSampler(samplingPercentage, samplingPercentage, false, true);
38+
ingestionSamplingEnabled);
5539
}
5640

5741
private AiSampler(
5842
SamplingPercentage requestSamplingPercentage,
5943
SamplingPercentage parentlessDependencySamplingPercentage,
60-
boolean ingestionSamplingEnabled,
61-
boolean override) {
44+
boolean ingestionSamplingEnabled) {
6245
this.requestSamplingPercentage = requestSamplingPercentage;
6346
this.parentlessDependencySamplingPercentage = parentlessDependencySamplingPercentage;
6447
this.ingestionSamplingEnabled = ingestionSamplingEnabled;
65-
this.override = override;
6648
}
6749

6850
@Override
@@ -82,30 +64,6 @@ public SamplingResult shouldSample(
8264
((ReadableSpan) parentSpan).getAttribute(AiSemanticAttributes.SAMPLE_RATE);
8365
}
8466

85-
return internalShouldSample(
86-
parentSpanContext, parentSpanSampleRate, traceId, spanKind, attributes);
87-
}
88-
89-
public SamplingResult shouldSampleLog(SpanContext spanContext, @Nullable Double spanSampleRate) {
90-
return internalShouldSample(
91-
spanContext,
92-
spanSampleRate,
93-
spanContext.getTraceId(),
94-
SpanKind.INTERNAL, // unused
95-
Attributes.empty());
96-
}
97-
98-
public SamplingPercentage getParentlessDependencySamplingPercentage() {
99-
return parentlessDependencySamplingPercentage;
100-
}
101-
102-
private SamplingResult internalShouldSample(
103-
SpanContext parentSpanContext,
104-
@Nullable Double parentSpanSampleRate,
105-
String traceId,
106-
SpanKind spanKind,
107-
Attributes attributes) {
108-
10967
SamplingResult samplingResult =
11068
useLocalParentDecisionIfPossible(parentSpanContext, parentSpanSampleRate);
11169
if (samplingResult != null) {
@@ -124,35 +82,15 @@ private SamplingResult internalShouldSample(
12482
: parentlessDependencySamplingPercentage.get();
12583
}
12684

127-
if (sp == 0) {
128-
return SamplingResult.drop();
129-
}
130-
131-
if (sp != 100 && !shouldRecordAndSample(traceId, sp)) {
132-
return SamplingResult.drop();
133-
}
134-
13585
if (sp == 100 && ingestionSamplingEnabled) {
13686
return SamplingResult.recordAndSample();
13787
}
13888

139-
if (sp == 100) {
140-
// ingestion sampling is applied when sample rate is 100 (or missing)
141-
// so we set it to 99.99 which will bypass ingestion sampling
142-
// (and will still be stored as item count 1)
143-
sp = SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING;
144-
}
145-
146-
samplingResult = recordAndSampleWithSampleRateMap.get(sp);
147-
if (samplingResult == null) {
148-
samplingResult = new RecordAndSampleWithItemCount(sp);
149-
recordAndSampleWithSampleRateMap.put(sp, samplingResult);
150-
}
151-
return samplingResult;
89+
return SamplerUtil.shouldSample(traceId, sp);
15290
}
15391

15492
@Nullable
155-
private SamplingResult useLocalParentDecisionIfPossible(
93+
private static SamplingResult useLocalParentDecisionIfPossible(
15694
SpanContext parentSpanContext, @Nullable Double parentSpanSampleRate) {
15795

15896
// remote parent-based sampling messes up item counts since item count is not propagated in
@@ -163,77 +101,17 @@ private SamplingResult useLocalParentDecisionIfPossible(
163101
return null;
164102
}
165103

166-
if (!override) {
167-
if (!parentSpanContext.isSampled()) {
168-
return SamplingResult.drop();
169-
}
170-
if (parentSpanSampleRate == null) {
171-
return null;
172-
}
173-
return new RecordAndSampleWithItemCount(parentSpanSampleRate);
174-
}
175-
176-
// override case:
177-
178-
// note: in the override case, requestSamplingPercentage and
179-
// parentlessDependencySamplingPercentage are always the same (and fixed)
180-
double sp = parentlessDependencySamplingPercentage.get();
181-
182104
if (!parentSpanContext.isSampled()) {
183-
if (sp < 100) {
184-
// only 100% sampling override will override an unsampled parent!!
185-
return SamplingResult.drop();
186-
} else {
187-
// falls back in this case to sp
188-
return null;
189-
}
105+
return SamplingResult.drop();
190106
}
191-
192107
if (parentSpanSampleRate == null) {
193108
return null;
194109
}
195-
196-
if (sp < parentSpanSampleRate || sp == 100) {
197-
// falls back in this case to sp
198-
return null;
199-
}
200-
// don't sample more dependencies than parent in this case
201-
return new RecordAndSampleWithItemCount(parentSpanSampleRate);
202-
}
203-
204-
public static boolean shouldRecordAndSample(String traceId, double percentage) {
205-
if (percentage == 100) {
206-
// optimization, no need to calculate score
207-
return true;
208-
}
209-
if (percentage == 0) {
210-
// optimization, no need to calculate score
211-
return false;
212-
}
213-
return SamplingScoreGeneratorV2.getSamplingScore(traceId) < percentage;
110+
return new SamplerUtil.RecordAndSampleWithItemCount(parentSpanSampleRate);
214111
}
215112

216113
@Override
217114
public String getDescription() {
218115
return "AiSampler";
219116
}
220-
221-
private static class RecordAndSampleWithItemCount implements SamplingResult {
222-
223-
private final Attributes attributes;
224-
225-
RecordAndSampleWithItemCount(double sampleRate) {
226-
attributes = Attributes.builder().put(AiSemanticAttributes.SAMPLE_RATE, sampleRate).build();
227-
}
228-
229-
@Override
230-
public SamplingDecision getDecision() {
231-
return SamplingDecision.RECORD_AND_SAMPLE;
232-
}
233-
234-
@Override
235-
public Attributes getAttributes() {
236-
return attributes;
237-
}
238-
}
239117
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.applicationinsights.agent.internal.sampling;
5+
6+
import com.azure.monitor.opentelemetry.autoconfigure.implementation.AiSemanticAttributes;
7+
import io.opentelemetry.api.common.Attributes;
8+
import io.opentelemetry.api.trace.Span;
9+
import io.opentelemetry.api.trace.SpanContext;
10+
import io.opentelemetry.api.trace.SpanKind;
11+
import io.opentelemetry.context.Context;
12+
import io.opentelemetry.sdk.trace.ReadableSpan;
13+
import io.opentelemetry.sdk.trace.data.LinkData;
14+
import io.opentelemetry.sdk.trace.samplers.Sampler;
15+
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
16+
import java.util.List;
17+
import javax.annotation.Nullable;
18+
19+
public class AiSamplerForOverride implements Sampler {
20+
21+
private final SamplingPercentage samplingPercentage;
22+
23+
public static AiSamplerForOverride create(SamplingPercentage samplingPercentage) {
24+
return new AiSamplerForOverride(samplingPercentage);
25+
}
26+
27+
private AiSamplerForOverride(SamplingPercentage samplingPercentage) {
28+
this.samplingPercentage = samplingPercentage;
29+
}
30+
31+
@Override
32+
public SamplingResult shouldSample(
33+
Context parentContext,
34+
String traceId,
35+
String name,
36+
SpanKind spanKind,
37+
Attributes attributes,
38+
List<LinkData> parentLinks) {
39+
40+
Span parentSpan = Span.fromContext(parentContext);
41+
SpanContext parentSpanContext = parentSpan.getSpanContext();
42+
Double parentSpanSampleRate = null;
43+
if (parentSpan instanceof ReadableSpan) {
44+
parentSpanSampleRate =
45+
((ReadableSpan) parentSpan).getAttribute(AiSemanticAttributes.SAMPLE_RATE);
46+
}
47+
48+
return internalShouldSample(parentSpanContext, parentSpanSampleRate, traceId);
49+
}
50+
51+
public SamplingResult shouldSampleLog(SpanContext spanContext, @Nullable Double spanSampleRate) {
52+
return internalShouldSample(spanContext, spanSampleRate, spanContext.getTraceId());
53+
}
54+
55+
private SamplingResult internalShouldSample(
56+
SpanContext parentSpanContext, @Nullable Double parentSpanSampleRate, String traceId) {
57+
58+
SamplingResult samplingResult =
59+
useLocalParentDecisionIfPossible(parentSpanContext, parentSpanSampleRate);
60+
if (samplingResult != null) {
61+
return samplingResult;
62+
}
63+
64+
double sp = samplingPercentage.get();
65+
66+
return SamplerUtil.shouldSample(traceId, sp);
67+
}
68+
69+
@Nullable
70+
private SamplingResult useLocalParentDecisionIfPossible(
71+
SpanContext parentSpanContext, @Nullable Double parentSpanSampleRate) {
72+
73+
// remote parent-based sampling messes up item counts since item count is not propagated in
74+
// tracestate (yet), but local parent-based sampling doesn't have this issue since we are
75+
// propagating item count locally
76+
77+
if (!parentSpanContext.isValid() || parentSpanContext.isRemote()) {
78+
return null;
79+
}
80+
81+
double sp = samplingPercentage.get();
82+
83+
if (!parentSpanContext.isSampled()) {
84+
if (sp < 100) {
85+
// only 100% sampling override will override an unsampled parent!!
86+
return SamplingResult.drop();
87+
} else {
88+
// falls back in this case to sp
89+
return null;
90+
}
91+
}
92+
93+
if (parentSpanSampleRate == null) {
94+
return null;
95+
}
96+
97+
if (sp < parentSpanSampleRate || sp == 100) {
98+
// falls back in this case to sp
99+
return null;
100+
}
101+
// don't sample more dependencies than parent in this case
102+
return new SamplerUtil.RecordAndSampleWithItemCount(parentSpanSampleRate);
103+
}
104+
105+
@Override
106+
public String getDescription() {
107+
return "AiSampler";
108+
}
109+
}

0 commit comments

Comments
 (0)