Add ParentOrElse Sampler (#1444)

* Fix bug where Sampling status would not propagate from parent to child correctly

* use generic parentorelse sampler instead

* bring back alwayson as default sampler
This commit is contained in:
MitchellDumovic 2020-07-22 16:20:45 -07:00 committed by GitHub
parent 810379f88b
commit 23b27d7d97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 139 additions and 0 deletions

View File

@ -139,6 +139,21 @@ public final class Samplers {
return AlwaysOffSampler.INSTANCE;
}
/**
* Returns a {@link Sampler} that always makes the same decision as the parent {@link Span} to
* whether or not to sample. If there is no parent, the Sampler uses the provided Sampler delegate
* to determine the sampling decision.
*
* @param delegateSampler the {@code Sampler} which is used to make the sampling decisions if the
* parent does not exist.
* @return a {@code Sampler} that follows the parent's sampling decision if one exists, otherwise
* following the delegate sampler's decision.
* @since 0.7.0
*/
public static Sampler parentOrElse(Sampler delegateSampler) {
return new ParentOrElse(delegateSampler);
}
/**
* Returns a new Probability {@link Sampler}. The probability of sampling a trace is equal to that
* of the specified probability.
@ -195,6 +210,40 @@ public final class Samplers {
}
}
@Immutable
static class ParentOrElse implements Sampler {
private final Sampler delegateSampler;
ParentOrElse(Sampler delegateSampler) {
this.delegateSampler = delegateSampler;
}
// If a parent is set, always follows the same sampling decision as the parent.
// Otherwise, uses the delegateSampler provided at initialization to make a decision.
@Override
public Decision shouldSample(
@Nullable SpanContext parentContext,
TraceId traceId,
String name,
Kind spanKind,
ReadableAttributes attributes,
List<Link> parentLinks) {
if (parentContext != null) {
if (parentContext.getTraceFlags().isSampled()) {
return EMPTY_SAMPLED_DECISION;
}
return EMPTY_NOT_SAMPLED_DECISION;
}
return this.delegateSampler.shouldSample(
parentContext, traceId, name, spanKind, attributes, parentLinks);
}
@Override
public String getDescription() {
return String.format("ParentOrElseSampler-%s", this.delegateSampler.getDescription());
}
}
/**
* We assume the lower 64 bits of the traceId's are randomly distributed around the whole (long)
* range. We convert an incoming probability into an upper bound on that value, such that we can

View File

@ -193,6 +193,96 @@ public class SamplersTest {
assertThat(Samplers.alwaysOff().getDescription()).isEqualTo("AlwaysOffSampler");
}
@Test
public void parentOrElseSampler_AlwaysOn() {
// Sampled parent.
assertThat(
Samplers.parentOrElse(Samplers.alwaysOn())
.shouldSample(
sampledSpanContext,
traceId,
SPAN_NAME,
SPAN_KIND,
Attributes.empty(),
Collections.emptyList())
.isSampled())
.isTrue();
// Not sampled parent.
assertThat(
Samplers.parentOrElse(Samplers.alwaysOn())
.shouldSample(
notSampledSpanContext,
traceId,
SPAN_NAME,
SPAN_KIND,
Attributes.empty(),
Collections.emptyList())
.isSampled())
.isFalse();
// Null parent.
assertThat(
Samplers.parentOrElse(Samplers.alwaysOn())
.shouldSample(
null,
traceId,
SPAN_NAME,
SPAN_KIND,
Attributes.empty(),
Collections.emptyList())
.isSampled())
.isTrue();
}
@Test
public void parentOrElseSampler_AlwaysOff() {
// Sampled parent.
assertThat(
Samplers.parentOrElse(Samplers.alwaysOff())
.shouldSample(
sampledSpanContext,
traceId,
SPAN_NAME,
SPAN_KIND,
Attributes.empty(),
Collections.emptyList())
.isSampled())
.isTrue();
// Not sampled parent.
assertThat(
Samplers.parentOrElse(Samplers.alwaysOff())
.shouldSample(
notSampledSpanContext,
traceId,
SPAN_NAME,
SPAN_KIND,
Attributes.empty(),
Collections.emptyList())
.isSampled())
.isFalse();
// Null parent.
assertThat(
Samplers.parentOrElse(Samplers.alwaysOff())
.shouldSample(
null,
traceId,
SPAN_NAME,
SPAN_KIND,
Attributes.empty(),
Collections.emptyList())
.isSampled())
.isFalse();
}
@Test
public void parentOrElseSampler_GetDescription() {
assertThat(Samplers.parentOrElse(Samplers.alwaysOn()).getDescription())
.isEqualTo("ParentOrElseSampler-AlwaysOnSampler");
}
@Test
public void probabilitySampler_AlwaysSample() {
Samplers.Probability sampler = Samplers.Probability.create(1);