Skip to content

Commit 71cac47

Browse files
authored
Support traceId-based r-values (#417)
* Support traceId-based r-values * Interface * Fix javadoc * Spotless * More * Clean * Review
1 parent bd08352 commit 71cac47

14 files changed

+179
-107
lines changed

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,8 @@
1010
@Immutable
1111
final class ConsistentAlwaysOffSampler extends ConsistentSampler {
1212

13-
private ConsistentAlwaysOffSampler() {}
14-
15-
private static final ConsistentSampler INSTANCE = new ConsistentAlwaysOffSampler();
16-
17-
static ConsistentSampler getInstance() {
18-
return INSTANCE;
13+
ConsistentAlwaysOffSampler(RValueGenerator rValueGenerator) {
14+
super(rValueGenerator);
1915
}
2016

2117
@Override

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,8 @@
1010
@Immutable
1111
final class ConsistentAlwaysOnSampler extends ConsistentSampler {
1212

13-
private ConsistentAlwaysOnSampler() {}
14-
15-
private static final ConsistentSampler INSTANCE = new ConsistentAlwaysOnSampler();
16-
17-
static ConsistentSampler getInstance() {
18-
return INSTANCE;
13+
ConsistentAlwaysOnSampler(RValueGenerator rValueGenerator) {
14+
super(rValueGenerator);
1915
}
2016

2117
@Override

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ final class ConsistentComposedAndSampler extends ConsistentSampler {
2121
private final ConsistentSampler sampler2;
2222
private final String description;
2323

24-
ConsistentComposedAndSampler(ConsistentSampler sampler1, ConsistentSampler sampler2) {
24+
ConsistentComposedAndSampler(
25+
ConsistentSampler sampler1, ConsistentSampler sampler2, RValueGenerator rValueGenerator) {
26+
super(rValueGenerator);
2527
this.sampler1 = requireNonNull(sampler1);
2628
this.sampler2 = requireNonNull(sampler2);
2729
this.description =

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ final class ConsistentComposedOrSampler extends ConsistentSampler {
2121
private final ConsistentSampler sampler2;
2222
private final String description;
2323

24-
ConsistentComposedOrSampler(ConsistentSampler sampler1, ConsistentSampler sampler2) {
24+
ConsistentComposedOrSampler(
25+
ConsistentSampler sampler1, ConsistentSampler sampler2, RValueGenerator rValueGenerator) {
26+
super(rValueGenerator);
2527
this.sampler1 = requireNonNull(sampler1);
2628
this.sampler2 = requireNonNull(sampler2);
2729
this.description =

consistent-sampling/src/main/java/io/opentelemetry/contrib/samplers/ConsistentParentBasedSampler.java

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,15 @@ final class ConsistentParentBasedSampler extends ConsistentSampler {
2121

2222
private final String description;
2323

24-
/**
25-
* Constructs a new consistent parent based sampler using the given root sampler.
26-
*
27-
* @param rootSampler the root sampler
28-
*/
29-
ConsistentParentBasedSampler(ConsistentSampler rootSampler) {
30-
this(rootSampler, RandomGenerator.getDefault());
31-
}
32-
3324
/**
3425
* Constructs a new consistent parent based sampler using the given root sampler and the given
3526
* thread-safe random generator.
3627
*
3728
* @param rootSampler the root sampler
38-
* @param threadSafeRandomGenerator a thread-safe random generator
29+
* @param rValueGenerator the function to use for generating the r-value
3930
*/
40-
ConsistentParentBasedSampler(
41-
ConsistentSampler rootSampler, RandomGenerator threadSafeRandomGenerator) {
42-
super(threadSafeRandomGenerator);
31+
ConsistentParentBasedSampler(ConsistentSampler rootSampler, RValueGenerator rValueGenerator) {
32+
super(rValueGenerator);
4333
this.rootSampler = requireNonNull(rootSampler);
4434
this.description =
4535
"ConsistentParentBasedSampler{rootSampler=" + rootSampler.getDescription() + '}';

consistent-sampling/src/main/java/io/opentelemetry/contrib/samplers/ConsistentProbabilityBasedSampler.java

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,25 @@ final class ConsistentProbabilityBasedSampler extends ConsistentSampler {
1515
private final int upperPValue;
1616
private final double probabilityToUseLowerPValue;
1717
private final String description;
18+
private final RandomGenerator randomGenerator;
1819

1920
/**
2021
* Constructor.
2122
*
2223
* @param samplingProbability the sampling probability
24+
* @param rValueGenerator the function to use for generating the r-value
2325
*/
24-
ConsistentProbabilityBasedSampler(double samplingProbability) {
25-
this(samplingProbability, RandomGenerator.getDefault());
26-
}
27-
28-
/**
29-
* Constructor.
30-
*
31-
* @param samplingProbability the sampling probability
32-
* @param randomGenerator a random generator
33-
*/
34-
ConsistentProbabilityBasedSampler(double samplingProbability, RandomGenerator randomGenerator) {
35-
super(randomGenerator);
26+
ConsistentProbabilityBasedSampler(
27+
double samplingProbability,
28+
RValueGenerator rValueGenerator,
29+
RandomGenerator randomGenerator) {
30+
super(rValueGenerator);
3631
if (samplingProbability < 0.0 || samplingProbability > 1.0) {
3732
throw new IllegalArgumentException("Sampling probability must be in range [0.0, 1.0]!");
3833
}
3934
this.description =
4035
String.format("ConsistentProbabilityBasedSampler{%.6f}", samplingProbability);
36+
this.randomGenerator = randomGenerator;
4137

4238
lowerPValue = getLowerBoundP(samplingProbability);
4339
upperPValue = getUpperBoundP(samplingProbability);

consistent-sampling/src/main/java/io/opentelemetry/contrib/samplers/ConsistentRateLimitingSampler.java

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -85,37 +85,25 @@ public State(double effectiveWindowCount, double effectiveWindowNanos, long last
8585
private final double inverseAdaptationTimeNanos;
8686
private final double targetSpansPerNanosecondLimit;
8787
private final AtomicReference<State> state;
88+
private final RandomGenerator randomGenerator;
8889

8990
/**
9091
* Constructor.
9192
*
9293
* @param targetSpansPerSecondLimit the desired spans per second limit
9394
* @param adaptationTimeSeconds the typical time to adapt to a new load (time constant used for
9495
* exponential smoothing)
95-
*/
96-
ConsistentRateLimitingSampler(double targetSpansPerSecondLimit, double adaptationTimeSeconds) {
97-
this(
98-
targetSpansPerSecondLimit,
99-
adaptationTimeSeconds,
100-
RandomGenerator.getDefault(),
101-
System::nanoTime);
102-
}
103-
104-
/**
105-
* Constructor.
106-
*
107-
* @param targetSpansPerSecondLimit the desired spans per second limit
108-
* @param adaptationTimeSeconds the typical time to adapt to a new load (time constant used for
109-
* exponential smoothing)
96+
* @param rValueGenerator the function to use for generating the r-value
11097
* @param randomGenerator a random generator
11198
* @param nanoTimeSupplier a supplier for the current nano time
11299
*/
113100
ConsistentRateLimitingSampler(
114101
double targetSpansPerSecondLimit,
115102
double adaptationTimeSeconds,
103+
RValueGenerator rValueGenerator,
116104
RandomGenerator randomGenerator,
117105
LongSupplier nanoTimeSupplier) {
118-
super(randomGenerator);
106+
super(rValueGenerator);
119107

120108
if (targetSpansPerSecondLimit < 0.0) {
121109
throw new IllegalArgumentException("Limit for sampled spans per second must be nonnegative!");
@@ -133,6 +121,8 @@ public State(double effectiveWindowCount, double effectiveWindowNanos, long last
133121
this.targetSpansPerNanosecondLimit = 1e-9 * targetSpansPerSecondLimit;
134122

135123
this.state = new AtomicReference<>(new State(0, 0, nanoTimeSupplier.getAsLong()));
124+
125+
this.randomGenerator = randomGenerator;
136126
}
137127

138128
private State updateState(State oldState, long currentNanoTime) {

consistent-sampling/src/main/java/io/opentelemetry/contrib/samplers/ConsistentSampler.java

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,37 @@ public abstract class ConsistentSampler implements Sampler {
2828
*
2929
* @return a sampler
3030
*/
31-
public static final ConsistentSampler alwaysOn() {
32-
return ConsistentAlwaysOnSampler.getInstance();
31+
public static ConsistentSampler alwaysOn() {
32+
return alwaysOn(RValueGenerators.getDefault());
33+
}
34+
35+
/**
36+
* Returns a {@link ConsistentSampler} that samples all spans.
37+
*
38+
* @param rValueGenerator the function to use for generating the r-value
39+
* @return a sampler
40+
*/
41+
public static ConsistentSampler alwaysOn(RValueGenerator rValueGenerator) {
42+
return new ConsistentAlwaysOnSampler(rValueGenerator);
43+
}
44+
45+
/**
46+
* Returns a {@link ConsistentSampler} that does not sample any span.
47+
*
48+
* @return a sampler
49+
*/
50+
public static ConsistentSampler alwaysOff() {
51+
return alwaysOff(RValueGenerators.getDefault());
3352
}
3453

3554
/**
3655
* Returns a {@link ConsistentSampler} that does not sample any span.
3756
*
57+
* @param rValueGenerator the function to use for generating the r-value
3858
* @return a sampler
3959
*/
40-
public static final ConsistentSampler alwaysOff() {
41-
return ConsistentAlwaysOffSampler.getInstance();
60+
public static ConsistentSampler alwaysOff(RValueGenerator rValueGenerator) {
61+
return new ConsistentAlwaysOffSampler(rValueGenerator);
4262
}
4363

4464
/**
@@ -47,20 +67,21 @@ public static final ConsistentSampler alwaysOff() {
4767
* @param samplingProbability the sampling probability
4868
* @return a sampler
4969
*/
50-
public static final ConsistentSampler probabilityBased(double samplingProbability) {
51-
return new ConsistentProbabilityBasedSampler(samplingProbability);
70+
public static ConsistentSampler probabilityBased(double samplingProbability) {
71+
return probabilityBased(samplingProbability, RValueGenerators.getDefault());
5272
}
5373

5474
/**
5575
* Returns a {@link ConsistentSampler} that samples each span with a fixed probability.
5676
*
5777
* @param samplingProbability the sampling probability
58-
* @param randomGenerator a random generator
78+
* @param rValueGenerator the function to use for generating the r-value
5979
* @return a sampler
6080
*/
61-
static final ConsistentSampler probabilityBased(
62-
double samplingProbability, RandomGenerator randomGenerator) {
63-
return new ConsistentProbabilityBasedSampler(samplingProbability, randomGenerator);
81+
public static ConsistentSampler probabilityBased(
82+
double samplingProbability, RValueGenerator rValueGenerator) {
83+
return new ConsistentProbabilityBasedSampler(
84+
samplingProbability, rValueGenerator, RandomGenerator.getDefault());
6485
}
6586

6687
/**
@@ -69,20 +90,20 @@ static final ConsistentSampler probabilityBased(
6990
*
7091
* @param rootSampler the root sampler
7192
*/
72-
public static final ConsistentSampler parentBased(ConsistentSampler rootSampler) {
73-
return new ConsistentParentBasedSampler(rootSampler);
93+
public static ConsistentSampler parentBased(ConsistentSampler rootSampler) {
94+
return parentBased(rootSampler, RValueGenerators.getDefault());
7495
}
7596

7697
/**
7798
* Returns a new {@link ConsistentSampler} that respects the sampling decision of the parent span
7899
* or falls-back to the given sampler if it is a root span.
79100
*
80101
* @param rootSampler the root sampler
81-
* @param randomGenerator a random generator
102+
* @param rValueGenerator the function to use for generating the r-value
82103
*/
83-
static final ConsistentSampler parentBased(
84-
ConsistentSampler rootSampler, RandomGenerator randomGenerator) {
85-
return new ConsistentParentBasedSampler(rootSampler, randomGenerator);
104+
public static ConsistentSampler parentBased(
105+
ConsistentSampler rootSampler, RValueGenerator rValueGenerator) {
106+
return new ConsistentParentBasedSampler(rootSampler, rValueGenerator);
86107
}
87108

88109
/**
@@ -93,9 +114,10 @@ static final ConsistentSampler parentBased(
93114
* @param adaptationTimeSeconds the typical time to adapt to a new load (time constant used for
94115
* exponential smoothing)
95116
*/
96-
public static final ConsistentSampler rateLimited(
117+
public static ConsistentSampler rateLimited(
97118
double targetSpansPerSecondLimit, double adaptationTimeSeconds) {
98-
return new ConsistentRateLimitingSampler(targetSpansPerSecondLimit, adaptationTimeSeconds);
119+
return rateLimited(
120+
targetSpansPerSecondLimit, adaptationTimeSeconds, RValueGenerators.getDefault());
99121
}
100122

101123
/**
@@ -105,16 +127,37 @@ public static final ConsistentSampler rateLimited(
105127
* @param targetSpansPerSecondLimit the desired spans per second limit
106128
* @param adaptationTimeSeconds the typical time to adapt to a new load (time constant used for
107129
* exponential smoothing)
108-
* @param randomGenerator a random generator
130+
* @param rValueGenerator the function to use for generating the r-value
131+
*/
132+
public static ConsistentSampler rateLimited(
133+
double targetSpansPerSecondLimit,
134+
double adaptationTimeSeconds,
135+
RValueGenerator rValueGenerator) {
136+
return rateLimited(
137+
targetSpansPerSecondLimit, adaptationTimeSeconds, rValueGenerator, System::nanoTime);
138+
}
139+
140+
/**
141+
* Returns a new {@link ConsistentSampler} that attempts to adjust the sampling probability
142+
* dynamically to meet the target span rate.
143+
*
144+
* @param targetSpansPerSecondLimit the desired spans per second limit
145+
* @param adaptationTimeSeconds the typical time to adapt to a new load (time constant used for
146+
* exponential smoothing)
147+
* @param rValueGenerator the function to use for generating the r-value
109148
* @param nanoTimeSupplier a supplier for the current nano time
110149
*/
111-
static final ConsistentSampler rateLimited(
150+
static ConsistentSampler rateLimited(
112151
double targetSpansPerSecondLimit,
113152
double adaptationTimeSeconds,
114-
RandomGenerator randomGenerator,
153+
RValueGenerator rValueGenerator,
115154
LongSupplier nanoTimeSupplier) {
116155
return new ConsistentRateLimitingSampler(
117-
targetSpansPerSecondLimit, adaptationTimeSeconds, randomGenerator, nanoTimeSupplier);
156+
targetSpansPerSecondLimit,
157+
adaptationTimeSeconds,
158+
rValueGenerator,
159+
RandomGenerator.getDefault(),
160+
nanoTimeSupplier);
118161
}
119162

120163
/**
@@ -136,7 +179,8 @@ public ConsistentSampler and(ConsistentSampler otherConsistentSampler) {
136179
if (otherConsistentSampler == this) {
137180
return this;
138181
}
139-
return new ConsistentComposedAndSampler(this, otherConsistentSampler);
182+
return new ConsistentComposedAndSampler(
183+
this, otherConsistentSampler, RValueGenerators.getDefault());
140184
}
141185

142186
/**
@@ -158,20 +202,17 @@ public ConsistentSampler or(ConsistentSampler otherConsistentSampler) {
158202
if (otherConsistentSampler == this) {
159203
return this;
160204
}
161-
return new ConsistentComposedOrSampler(this, otherConsistentSampler);
205+
return new ConsistentComposedOrSampler(
206+
this, otherConsistentSampler, RValueGenerators.getDefault());
162207
}
163208

164-
protected final RandomGenerator randomGenerator;
165-
166-
protected ConsistentSampler(RandomGenerator randomGenerator) {
167-
this.randomGenerator = requireNonNull(randomGenerator);
168-
}
209+
private final RValueGenerator rValueGenerator;
169210

170-
protected ConsistentSampler() {
171-
this(RandomGenerator.getDefault());
211+
protected ConsistentSampler(RValueGenerator rValueGenerator) {
212+
this.rValueGenerator = requireNonNull(rValueGenerator);
172213
}
173214

174-
private static final boolean isInvariantViolated(
215+
private static boolean isInvariantViolated(
175216
OtelTraceState otelTraceState, boolean isParentSampled) {
176217
if (otelTraceState.hasValidR() && otelTraceState.hasValidP()) {
177218
// if valid p- and r-values are given, they must be consistent with the isParentSampled flag
@@ -212,8 +253,7 @@ public final SamplingResult shouldSample(
212253

213254
// generate new r-value if not available
214255
if (!otelTraceState.hasValidR()) {
215-
otelTraceState.setR(
216-
Math.min(randomGenerator.numberOfLeadingZerosOfRandomLong(), OtelTraceState.getMaxR()));
256+
otelTraceState.setR(Math.min(rValueGenerator.generate(traceId), OtelTraceState.getMaxR()));
217257
}
218258

219259
// determine and set new p-value that is used for the sampling decision

0 commit comments

Comments
 (0)