Skip to content

Commit 11f2111

Browse files
PeterF778oertl
authored andcommitted
Composite Samplers prototype (open-telemetry#1443)
Co-authored-by: Otmar Ertl <[email protected]>
1 parent b3386de commit 11f2111

22 files changed

+1264
-248
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.sampler.consistent56;
7+
8+
import io.opentelemetry.api.common.Attributes;
9+
import io.opentelemetry.api.trace.SpanKind;
10+
import io.opentelemetry.context.Context;
11+
import io.opentelemetry.sdk.trace.data.LinkData;
12+
import java.util.List;
13+
14+
/** An interface for components to be used by composite consistent probability samplers. */
15+
public interface ComposableSampler {
16+
17+
/**
18+
* Returns the SamplingIntent that is used for the sampling decision. The SamplingIntent includes
19+
* the threshold value which will be used for the sampling decision.
20+
*
21+
* <p>NOTE: Keep in mind, that in any case the returned threshold value must not depend directly
22+
* or indirectly on the random value. In particular this means that the parent sampled flag must
23+
* not be used for the calculation of the threshold as the sampled flag depends itself on the
24+
* random value.
25+
*/
26+
SamplingIntent getSamplingIntent(
27+
Context parentContext,
28+
String name,
29+
SpanKind spanKind,
30+
Attributes attributes,
31+
List<LinkData> parentLinks);
32+
33+
/** Return the string providing a description of the implementation. */
34+
String getDescription();
35+
}

consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSampler.java

+15-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55

66
package io.opentelemetry.contrib.sampler.consistent56;
77

8+
import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getInvalidThreshold;
9+
10+
import io.opentelemetry.api.common.Attributes;
11+
import io.opentelemetry.api.trace.SpanKind;
12+
import io.opentelemetry.context.Context;
13+
import io.opentelemetry.sdk.trace.data.LinkData;
14+
import java.util.List;
815
import javax.annotation.concurrent.Immutable;
916

1017
@Immutable
@@ -19,8 +26,14 @@ static ConsistentAlwaysOffSampler getInstance() {
1926
}
2027

2128
@Override
22-
protected long getThreshold(long parentThreshold, boolean isRoot) {
23-
return ConsistentSamplingUtil.getMaxThreshold();
29+
public SamplingIntent getSamplingIntent(
30+
Context parentContext,
31+
String name,
32+
SpanKind spanKind,
33+
Attributes attributes,
34+
List<LinkData> parentLinks) {
35+
36+
return () -> getInvalidThreshold();
2437
}
2538

2639
@Override

consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSampler.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77

88
import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMinThreshold;
99

10+
import io.opentelemetry.api.common.Attributes;
11+
import io.opentelemetry.api.trace.SpanKind;
12+
import io.opentelemetry.context.Context;
13+
import io.opentelemetry.sdk.trace.data.LinkData;
14+
import java.util.List;
1015
import javax.annotation.concurrent.Immutable;
1116

1217
@Immutable
@@ -21,8 +26,14 @@ static ConsistentAlwaysOnSampler getInstance() {
2126
}
2227

2328
@Override
24-
protected long getThreshold(long parentThreshold, boolean isRoot) {
25-
return getMinThreshold();
29+
public SamplingIntent getSamplingIntent(
30+
Context parentContext,
31+
String name,
32+
SpanKind spanKind,
33+
Attributes attributes,
34+
List<LinkData> parentLinks) {
35+
36+
return () -> getMinThreshold();
2637
}
2738

2839
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.sampler.consistent56;
7+
8+
import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getInvalidThreshold;
9+
import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.isValidThreshold;
10+
11+
import io.opentelemetry.api.common.Attributes;
12+
import io.opentelemetry.api.common.AttributesBuilder;
13+
import io.opentelemetry.api.trace.SpanKind;
14+
import io.opentelemetry.api.trace.TraceState;
15+
import io.opentelemetry.context.Context;
16+
import io.opentelemetry.sdk.trace.data.LinkData;
17+
import java.util.List;
18+
import java.util.stream.Collectors;
19+
import java.util.stream.Stream;
20+
import javax.annotation.Nullable;
21+
import javax.annotation.concurrent.Immutable;
22+
23+
/**
24+
* A consistent sampler that queries all its delegate samplers for their sampling threshold, and
25+
* uses the minimum threshold value received.
26+
*/
27+
@Immutable
28+
final class ConsistentAnyOf extends ConsistentSampler {
29+
30+
private final ComposableSampler[] delegates;
31+
32+
private final String description;
33+
34+
/**
35+
* Constructs a new consistent AnyOf sampler using the provided delegate samplers.
36+
*
37+
* @param delegates the delegate samplers
38+
*/
39+
ConsistentAnyOf(@Nullable ComposableSampler... delegates) {
40+
if (delegates == null || delegates.length == 0) {
41+
throw new IllegalArgumentException(
42+
"At least one delegate must be specified for ConsistentAnyOf");
43+
}
44+
45+
this.delegates = delegates;
46+
47+
this.description =
48+
Stream.of(delegates)
49+
.map(Object::toString)
50+
.collect(Collectors.joining(",", "ConsistentAnyOf{", "}"));
51+
}
52+
53+
@Override
54+
public SamplingIntent getSamplingIntent(
55+
Context parentContext,
56+
String name,
57+
SpanKind spanKind,
58+
Attributes attributes,
59+
List<LinkData> parentLinks) {
60+
61+
SamplingIntent[] intents = new SamplingIntent[delegates.length];
62+
int k = 0;
63+
long minimumThreshold = getInvalidThreshold();
64+
for (ComposableSampler delegate : delegates) {
65+
SamplingIntent delegateIntent =
66+
delegate.getSamplingIntent(parentContext, name, spanKind, attributes, parentLinks);
67+
long delegateThreshold = delegateIntent.getThreshold();
68+
if (isValidThreshold(delegateThreshold)) {
69+
if (isValidThreshold(minimumThreshold)) {
70+
minimumThreshold = Math.min(delegateThreshold, minimumThreshold);
71+
} else {
72+
minimumThreshold = delegateThreshold;
73+
}
74+
}
75+
intents[k++] = delegateIntent;
76+
}
77+
78+
long resultingThreshold = minimumThreshold;
79+
80+
return new SamplingIntent() {
81+
@Override
82+
public long getThreshold() {
83+
return resultingThreshold;
84+
}
85+
86+
@Override
87+
public Attributes getAttributes() {
88+
AttributesBuilder builder = Attributes.builder();
89+
for (SamplingIntent intent : intents) {
90+
builder = builder.putAll(intent.getAttributes());
91+
}
92+
return builder.build();
93+
}
94+
95+
@Override
96+
public TraceState updateTraceState(TraceState previousState) {
97+
for (SamplingIntent intent : intents) {
98+
previousState = intent.updateTraceState(previousState);
99+
}
100+
return previousState;
101+
}
102+
};
103+
}
104+
105+
@Override
106+
public String getDescription() {
107+
return description;
108+
}
109+
}

consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedAndSampler.java

-52
This file was deleted.

consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentComposedOrSampler.java

-57
This file was deleted.

consistent-sampling/src/main/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSampler.java

+22-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77

88
import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.calculateSamplingProbability;
99
import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.checkThreshold;
10+
import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getInvalidThreshold;
11+
import static io.opentelemetry.contrib.sampler.consistent56.ConsistentSamplingUtil.getMaxThreshold;
12+
13+
import io.opentelemetry.api.common.Attributes;
14+
import io.opentelemetry.api.trace.SpanKind;
15+
import io.opentelemetry.context.Context;
16+
import io.opentelemetry.sdk.trace.data.LinkData;
17+
import java.util.List;
1018

1119
public class ConsistentFixedThresholdSampler extends ConsistentSampler {
1220

@@ -18,7 +26,7 @@ protected ConsistentFixedThresholdSampler(long threshold) {
1826
this.threshold = threshold;
1927

2028
String thresholdString;
21-
if (threshold == ConsistentSamplingUtil.getMaxThreshold()) {
29+
if (threshold == getMaxThreshold()) {
2230
thresholdString = "max";
2331
} else {
2432
thresholdString =
@@ -41,7 +49,18 @@ public String getDescription() {
4149
}
4250

4351
@Override
44-
protected long getThreshold(long parentThreshold, boolean isRoot) {
45-
return threshold;
52+
public SamplingIntent getSamplingIntent(
53+
Context parentContext,
54+
String name,
55+
SpanKind spanKind,
56+
Attributes attributes,
57+
List<LinkData> parentLinks) {
58+
59+
return () -> {
60+
if (threshold == getMaxThreshold()) {
61+
return getInvalidThreshold();
62+
}
63+
return threshold;
64+
};
4665
}
4766
}

0 commit comments

Comments
 (0)