Skip to content
This repository was archived by the owner on Dec 23, 2023. It is now read-only.

Commit 83fed9c

Browse files
author
Bogdan Drutu
authored
Change when we check the sampler. (#657)
* Change when we check the sampler. * Fix comments. * Deprecate setIsSampled without an argument.
1 parent 17470b3 commit 83fed9c

11 files changed

Lines changed: 175 additions & 66 deletions

File tree

api/src/main/java/io/opencensus/trace/TraceOptions.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,26 @@ private Builder(byte options) {
182182
}
183183

184184
/**
185-
* Marks this trace as sampled.
186-
*
185+
* @deprecated Use {@code Builder.setIsSampled(true)}.
187186
* @return this.
188187
*/
188+
@Deprecated
189189
public Builder setIsSampled() {
190-
options |= IS_SAMPLED;
190+
return setIsSampled(true);
191+
}
192+
193+
/**
194+
* Sets the sampling bit in the options.
195+
*
196+
* @param isSampled the sampling bit.
197+
* @return this.
198+
*/
199+
public Builder setIsSampled(boolean isSampled) {
200+
if (isSampled) {
201+
options = (byte) (options | IS_SAMPLED);
202+
} else {
203+
options = (byte) (options & ~IS_SAMPLED);;
204+
}
191205
return this;
192206
}
193207

api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,6 @@ public final boolean shouldSample(
7979
SpanId spanId,
8080
String name,
8181
@Nullable List<Span> parentLinks) {
82-
// Always enable sampling if parent was sampled.
83-
if (parentContext != null && parentContext.getTraceOptions().isSampled()) {
84-
return true;
85-
}
8682
// Always sample if we are within probability range. This is true even for child spans (that
8783
// may have had a different sampling decision made) to allow for different sampling policies,
8884
// and dynamic increases to sampling probabilities for debugging purposes.

api/src/test/java/io/opencensus/trace/SpanContextTest.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class SpanContextTest {
4141
SpanContext.create(
4242
TraceId.fromBytes(secondTraceIdBytes),
4343
SpanId.fromBytes(secondSpanIdBytes),
44-
TraceOptions.builder().setIsSampled().build());
44+
TraceOptions.builder().setIsSampled(true).build());
4545

4646
@Test
4747
public void invalidSpanContext() {
@@ -82,7 +82,8 @@ public void getSpanId() {
8282
@Test
8383
public void getTraceOptions() {
8484
assertThat(first.getTraceOptions()).isEqualTo(TraceOptions.DEFAULT);
85-
assertThat(second.getTraceOptions()).isEqualTo(TraceOptions.builder().setIsSampled().build());
85+
assertThat(second.getTraceOptions())
86+
.isEqualTo(TraceOptions.builder().setIsSampled(true).build());
8687
}
8788

8889
@Test
@@ -93,13 +94,17 @@ public void spanContext_EqualsAndHashCode() {
9394
SpanContext.create(
9495
TraceId.fromBytes(firstTraceIdBytes),
9596
SpanId.fromBytes(firstSpanIdBytes),
96-
TraceOptions.DEFAULT));
97+
TraceOptions.DEFAULT),
98+
SpanContext.create(
99+
TraceId.fromBytes(firstTraceIdBytes),
100+
SpanId.fromBytes(firstSpanIdBytes),
101+
TraceOptions.builder().setIsSampled(false).build()));
97102
tester.addEqualityGroup(
98103
second,
99104
SpanContext.create(
100105
TraceId.fromBytes(secondTraceIdBytes),
101106
SpanId.fromBytes(secondSpanIdBytes),
102-
TraceOptions.builder().setIsSampled().build()));
107+
TraceOptions.builder().setIsSampled(true).build()));
103108
tester.testEquals();
104109
}
105110

@@ -111,6 +116,6 @@ public void spanContext_ToString() {
111116
assertThat(second.toString()).contains(TraceId.fromBytes(secondTraceIdBytes).toString());
112117
assertThat(second.toString()).contains(SpanId.fromBytes(secondSpanIdBytes).toString());
113118
assertThat(second.toString())
114-
.contains(TraceOptions.builder().setIsSampled().build().toString());
119+
.contains(TraceOptions.builder().setIsSampled(true).build().toString());
115120
}
116121
}

api/src/test/java/io/opencensus/trace/SpanTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public void setUp() {
4646
SpanContext.create(
4747
TraceId.generateRandomId(random),
4848
SpanId.generateRandomId(random),
49-
TraceOptions.builder().setIsSampled().build());
49+
TraceOptions.builder().setIsSampled(true).build());
5050
notSampledSpanContext =
5151
SpanContext.create(
5252
TraceId.generateRandomId(random),

api/src/test/java/io/opencensus/trace/TraceOptionsTest.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ public class TraceOptionsTest {
3333
@Test
3434
public void getOptions() {
3535
assertThat(TraceOptions.DEFAULT.getOptions()).isEqualTo(0);
36-
assertThat(TraceOptions.builder().setIsSampled().build().getOptions()).isEqualTo(1);
36+
assertThat(TraceOptions.builder().setIsSampled(false).build().getOptions()).isEqualTo(0);
37+
assertThat(TraceOptions.builder().setIsSampled(true).build().getOptions()).isEqualTo(1);
38+
assertThat(TraceOptions.builder().setIsSampled(true).setIsSampled(false).build().getOptions())
39+
.isEqualTo(0);
3740
assertThat(TraceOptions.fromBytes(firstBytes).getOptions()).isEqualTo(-1);
3841
assertThat(TraceOptions.fromBytes(secondBytes).getOptions()).isEqualTo(1);
3942
assertThat(TraceOptions.fromBytes(thirdBytes).getOptions()).isEqualTo(6);
@@ -42,7 +45,7 @@ public void getOptions() {
4245
@Test
4346
public void isSampled() {
4447
assertThat(TraceOptions.DEFAULT.isSampled()).isFalse();
45-
assertThat(TraceOptions.builder().setIsSampled().build().isSampled()).isTrue();
48+
assertThat(TraceOptions.builder().setIsSampled(true).build().isSampled()).isTrue();
4649
}
4750

4851
@Test
@@ -56,7 +59,7 @@ public void toFromBytes() {
5659
public void builder_FromOptions() {
5760
assertThat(
5861
TraceOptions.builder(TraceOptions.fromBytes(thirdBytes))
59-
.setIsSampled()
62+
.setIsSampled(true)
6063
.build()
6164
.getOptions())
6265
.isEqualTo(6 | 1);
@@ -67,14 +70,15 @@ public void traceOptions_EqualsAndHashCode() {
6770
EqualsTester tester = new EqualsTester();
6871
tester.addEqualityGroup(TraceOptions.DEFAULT);
6972
tester.addEqualityGroup(
70-
TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled().build());
73+
TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled(true).build());
7174
tester.addEqualityGroup(TraceOptions.fromBytes(firstBytes));
7275
tester.testEquals();
7376
}
7477

7578
@Test
7679
public void traceOptions_ToString() {
7780
assertThat(TraceOptions.DEFAULT.toString()).contains("sampled=false");
78-
assertThat(TraceOptions.builder().setIsSampled().build().toString()).contains("sampled=true");
81+
assertThat(TraceOptions.builder().setIsSampled(true).build().toString())
82+
.contains("sampled=true");
7983
}
8084
}

api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@
3333
/** Unit tests for {@link Samplers}. */
3434
@RunWith(JUnit4.class)
3535
public class SamplersTest {
36+
private static final String SPAN_NAME = "MySpanName";
37+
private static final int NUM_SAMPLE_TRIES = 1000;
3638
private final Random random = new Random(1234);
3739
private final TraceId traceId = TraceId.generateRandomId(random);
3840
private final SpanId parentSpanId = SpanId.generateRandomId(random);
3941
private final SpanId spanId = SpanId.generateRandomId(random);
4042
private final SpanContext sampledSpanContext =
41-
SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled().build());
43+
SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled(true).build());
4244
private final SpanContext notSampledSpanContext =
4345
SpanContext.create(traceId, parentSpanId, TraceOptions.DEFAULT);
4446

@@ -114,59 +116,40 @@ public void probabilitySampler_outOfRangeLowProbability() {
114116
Samplers.probabilitySampler(-0.00001);
115117
}
116118

117-
private final void probabilitySampler_AlwaysReturnTrueForSampled(Sampler sampler) {
118-
final int numSamples = 100; // Number of traces for which to generate sampling decisions.
119-
for (int i = 0; i < numSamples; i++) {
120-
assertThat(
121-
sampler.shouldSample(
122-
sampledSpanContext,
123-
false,
124-
TraceId.generateRandomId(random),
125-
spanId,
126-
"bar",
127-
Collections.<Span>emptyList()))
128-
.isTrue();
129-
}
130-
}
131-
132-
private final void probabilitySampler_SamplesWithProbabilityForUnsampled(
133-
Sampler sampler, double probability) {
134-
final int numSamples = 1000; // Number of traces for which to generate sampling decisions.
119+
// Applies the given sampler to NUM_SAMPLE_TRIES random traceId/spanId pairs.
120+
private static void assertSamplerSamplesWithProbability(
121+
Sampler sampler, SpanContext parent, double probability) {
122+
Random random = new Random(1234);
135123
int count = 0; // Count of spans with sampling enabled
136-
for (int i = 0; i < numSamples; i++) {
124+
for (int i = 0; i < NUM_SAMPLE_TRIES; i++) {
137125
if (sampler.shouldSample(
138-
notSampledSpanContext,
126+
parent,
139127
false,
140128
TraceId.generateRandomId(random),
141-
spanId,
142-
"bar",
129+
SpanId.generateRandomId(random),
130+
SPAN_NAME,
143131
Collections.<Span>emptyList())) {
144132
count++;
145133
}
146134
}
147-
double proportionSampled = (double) count / numSamples;
135+
double proportionSampled = (double) count / NUM_SAMPLE_TRIES;
148136
// Allow for a large amount of slop (+/- 10%) in number of sampled traces, to avoid flakiness.
149137
assertThat(proportionSampled < probability + 0.1 && proportionSampled > probability - 0.1)
150138
.isTrue();
151139
}
152140

153141
@Test
154-
public void probabilitySamper_SamplesWithProbability() {
142+
public void probabilitySampler_differentProbabilities() {
155143
final Sampler neverSample = Samplers.probabilitySampler(0.0);
156-
probabilitySampler_AlwaysReturnTrueForSampled(neverSample);
157-
probabilitySampler_SamplesWithProbabilityForUnsampled(neverSample, 0.0);
144+
assertSamplerSamplesWithProbability(neverSample, sampledSpanContext, 0.0);
158145
final Sampler alwaysSample = Samplers.probabilitySampler(1.0);
159-
probabilitySampler_AlwaysReturnTrueForSampled(alwaysSample);
160-
probabilitySampler_SamplesWithProbabilityForUnsampled(alwaysSample, 1.0);
146+
assertSamplerSamplesWithProbability(alwaysSample, sampledSpanContext, 1.0);
161147
final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5);
162-
probabilitySampler_AlwaysReturnTrueForSampled(fiftyPercentSample);
163-
probabilitySampler_SamplesWithProbabilityForUnsampled(fiftyPercentSample, 0.5);
148+
assertSamplerSamplesWithProbability(fiftyPercentSample, sampledSpanContext, 0.5);
164149
final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2);
165-
probabilitySampler_AlwaysReturnTrueForSampled(twentyPercentSample);
166-
probabilitySampler_SamplesWithProbabilityForUnsampled(twentyPercentSample, 0.2);
150+
assertSamplerSamplesWithProbability(twentyPercentSample, sampledSpanContext, 0.2);
167151
final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0);
168-
probabilitySampler_AlwaysReturnTrueForSampled(twoThirdsSample);
169-
probabilitySampler_SamplesWithProbabilityForUnsampled(twoThirdsSample, 2.0 / 3.0);
152+
assertSamplerSamplesWithProbability(twoThirdsSample, sampledSpanContext, 2.0 / 3.0);
170153
}
171154

172155
@Test

impl_core/src/main/java/io/opencensus/implcore/trace/SpanBuilderImpl.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,8 @@ private SpanImpl startSpanInternal(
7575
parentSpanId = parent.getSpanId();
7676
traceOptionsBuilder = TraceOptions.builder(parent.getTraceOptions());
7777
}
78-
if (sampler == null) {
79-
sampler = activeTraceParams.getSampler();
80-
}
81-
if (sampler.shouldSample(parent, hasRemoteParent, traceId, spanId, name, parentLinks)) {
82-
traceOptionsBuilder.setIsSampled();
83-
}
78+
traceOptionsBuilder.setIsSampled(makeSamplingDecision(
79+
parent, hasRemoteParent, name, sampler, parentLinks, traceId, spanId, activeTraceParams));
8480
TraceOptions traceOptions = traceOptionsBuilder.build();
8581
EnumSet<Span.Options> spanOptions = EnumSet.noneOf(Span.Options.class);
8682
if (traceOptions.isSampled() || Boolean.TRUE.equals(recordEvents)) {
@@ -101,6 +97,30 @@ private SpanImpl startSpanInternal(
10197
return span;
10298
}
10399

100+
private static boolean makeSamplingDecision(
101+
@Nullable SpanContext parent,
102+
@Nullable Boolean hasRemoteParent,
103+
String name,
104+
@Nullable Sampler sampler,
105+
List<Span> parentLinks,
106+
TraceId traceId,
107+
SpanId spanId,
108+
TraceParams activeTraceParams) {
109+
// If users set a specific sampler in the SpanBuilder, use it.
110+
if (sampler != null) {
111+
return sampler.shouldSample(parent, hasRemoteParent, traceId, spanId, name, parentLinks);
112+
}
113+
// Use the default sampler if this is a root Span or this is an entry point Span (has remote
114+
// parent).
115+
if (Boolean.TRUE.equals(hasRemoteParent) || parent == null || !parent.isValid()) {
116+
return activeTraceParams
117+
.getSampler()
118+
.shouldSample(parent, hasRemoteParent, traceId, spanId, name, parentLinks);
119+
}
120+
// Parent is always different than null because otherwise we use the default sampler.
121+
return parent.getTraceOptions().isSampled();
122+
}
123+
104124
private static void linkSpans(Span span, List<Span> parentLinks) {
105125
if (!parentLinks.isEmpty()) {
106126
Link childLink = Link.fromSpanContext(span.getContext(), Type.CHILD_LINKED_SPAN);

impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,14 @@ public void startChildSpan() {
107107
assertThat(rootSpan.getContext().isValid()).isTrue();
108108
assertThat(rootSpan.getOptions().contains(Options.RECORD_EVENTS)).isTrue();
109109
assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isTrue();
110-
assertThat(((SpanImpl) rootSpan).toSpanData().getHasRemoteParent())
111-
.isNull();
110+
assertThat(((SpanImpl) rootSpan).toSpanData().getHasRemoteParent()).isNull();
112111
Span childSpan =
113112
SpanBuilderImpl.createWithParent(SPAN_NAME, rootSpan, spanBuilderOptions).startSpan();
114113
assertThat(childSpan.getContext().isValid()).isTrue();
115114
assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId());
116115
assertThat(((SpanImpl) childSpan).toSpanData().getParentSpanId())
117116
.isEqualTo(rootSpan.getContext().getSpanId());
118-
assertThat(((SpanImpl) childSpan).toSpanData().getHasRemoteParent())
119-
.isFalse();
117+
assertThat(((SpanImpl) childSpan).toSpanData().getHasRemoteParent()).isFalse();
120118
assertThat(((SpanImpl) childSpan).getTimestampConverter())
121119
.isEqualTo(((SpanImpl) rootSpan).getTimestampConverter());
122120
}
@@ -164,6 +162,95 @@ public void startRemoteSpan() {
164162
assertThat(spanData.getHasRemoteParent()).isTrue();
165163
}
166164

165+
@Test
166+
public void startRootSpan_WithSpecifiedSampler() {
167+
// Apply given sampler before default sampler for root spans.
168+
Span rootSpan =
169+
SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions)
170+
.setSampler(Samplers.neverSample())
171+
.startSpan();
172+
assertThat(rootSpan.getContext().isValid()).isTrue();
173+
assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isFalse();
174+
}
175+
176+
@Test
177+
public void startRootSpan_WithoutSpecifiedSampler() {
178+
// Apply default sampler (always true in the tests) for root spans.
179+
Span rootSpan =
180+
SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions).startSpan();
181+
assertThat(rootSpan.getContext().isValid()).isTrue();
182+
assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isTrue();
183+
}
184+
185+
@Test
186+
public void startRemoteChildSpan_WithSpecifiedSampler() {
187+
Span rootSpan =
188+
SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions)
189+
.setSampler(Samplers.alwaysSample())
190+
.startSpan();
191+
assertThat(rootSpan.getContext().isValid()).isTrue();
192+
assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isTrue();
193+
// Apply given sampler before default sampler for spans with remote parent.
194+
Span childSpan =
195+
SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, rootSpan.getContext(), spanBuilderOptions)
196+
.setSampler(Samplers.neverSample())
197+
.startSpan();
198+
assertThat(childSpan.getContext().isValid()).isTrue();
199+
assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId());
200+
assertThat(childSpan.getContext().getTraceOptions().isSampled()).isFalse();
201+
}
202+
203+
@Test
204+
public void startRemoteChildSpan_WithoutSpecifiedSampler() {
205+
Span rootSpan =
206+
SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions)
207+
.setSampler(Samplers.neverSample())
208+
.startSpan();
209+
assertThat(rootSpan.getContext().isValid()).isTrue();
210+
assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isFalse();
211+
// Apply default sampler (always true in the tests) for spans with remote parent.
212+
Span childSpan =
213+
SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, rootSpan.getContext(), spanBuilderOptions)
214+
.startSpan();
215+
assertThat(childSpan.getContext().isValid()).isTrue();
216+
assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId());
217+
assertThat(childSpan.getContext().getTraceOptions().isSampled()).isTrue();
218+
}
219+
220+
@Test
221+
public void startChildSpan_WithSpecifiedSampler() {
222+
Span rootSpan =
223+
SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions)
224+
.setSampler(Samplers.alwaysSample())
225+
.startSpan();
226+
assertThat(rootSpan.getContext().isValid()).isTrue();
227+
assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isTrue();
228+
// Apply the given sampler for child spans.
229+
Span childSpan =
230+
SpanBuilderImpl.createWithParent(SPAN_NAME, rootSpan, spanBuilderOptions)
231+
.setSampler(Samplers.neverSample())
232+
.startSpan();
233+
assertThat(childSpan.getContext().isValid()).isTrue();
234+
assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId());
235+
assertThat(childSpan.getContext().getTraceOptions().isSampled()).isFalse();
236+
}
237+
238+
@Test
239+
public void startChildSpan_WithoutSpecifiedSampler() {
240+
Span rootSpan =
241+
SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions)
242+
.setSampler(Samplers.neverSample())
243+
.startSpan();
244+
assertThat(rootSpan.getContext().isValid()).isTrue();
245+
assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isFalse();
246+
// Don't apply the default sampler (always true) for child spans.
247+
Span childSpan =
248+
SpanBuilderImpl.createWithParent(SPAN_NAME, rootSpan, spanBuilderOptions).startSpan();
249+
assertThat(childSpan.getContext().isValid()).isTrue();
250+
assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId());
251+
assertThat(childSpan.getContext().getTraceOptions().isSampled()).isFalse();
252+
}
253+
167254
private static final class FakeRandomHandler extends RandomHandler {
168255
private final Random random;
169256

0 commit comments

Comments
 (0)