Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sampler and span processor prototype implementations for consistent sampling #226

Merged
merged 54 commits into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
7116c5e
sampler and exporter implementations for consistent sampling
oertl Feb 4, 2022
d8dd6e6
Merge branch 'main' into consistent-sampling
oertl Feb 7, 2022
6b4ba10
improved dependencies (in particular, removed dependency on guava)
oertl Feb 14, 2022
5ca2625
Merge remote-tracking branch 'origin' into consistent-sampling
oertl Feb 14, 2022
038f803
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sam…
oertl Feb 14, 2022
a686b3a
reverted some changes
oertl Feb 14, 2022
08bbc40
removed wrong immutable annotation
oertl Feb 15, 2022
9258ef4
added javadoc
oertl Feb 15, 2022
000ffea
avoid else statements when returning
oertl Feb 15, 2022
f7911c3
factory methods for consistent samplers, avoid exposure of implementa…
oertl Feb 15, 2022
b3459f9
added javadoc for AND and OR sampler composition
oertl Feb 15, 2022
0bbdb73
Merge remote-tracking branch 'origin' into consistent-sampling
oertl Feb 15, 2022
185f579
replaced use of synchronized by atomic reference
oertl Feb 15, 2022
abb7e71
simplified thread local initialization
oertl Feb 15, 2022
dd3df4e
removed consistent reservoir sampling
oertl Feb 16, 2022
90a2960
Merge branch 'open-telemetry:main' into consistent-sampling
oertl Mar 9, 2022
6f731b6
improved comment
oertl Mar 9, 2022
d40c0f1
removed unnecessary clipping of sampling probability
oertl Mar 10, 2022
775ca52
added javadoc explaining maths of implementation
oertl Mar 10, 2022
2ffe08f
Merge branch 'open-telemetry:main' into consistent-sampling
oertl Mar 10, 2022
a82eee6
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sta…
oertl Apr 9, 2022
6e8a38a
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sta…
oertl Apr 9, 2022
ae9670b
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sta…
oertl Apr 9, 2022
83c21f4
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sta…
oertl Apr 9, 2022
35d0373
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sam…
oertl Apr 19, 2022
348a240
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sam…
oertl Apr 19, 2022
0afaa2f
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sam…
oertl Apr 19, 2022
f63bb0b
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sam…
oertl Apr 19, 2022
aaffdd7
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sam…
oertl Apr 19, 2022
56eec39
added component owner for consistent sampling
oertl Apr 19, 2022
667e1f7
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sta…
oertl Apr 19, 2022
7910939
Merge branch 'consistent-sampling' of github.com:dynatrace-oss-contri…
oertl Apr 19, 2022
3fae630
removed nonnull annotation
oertl Apr 19, 2022
5040a74
renamed variable s -> pair
oertl Apr 19, 2022
e0041c0
renamed char parameter r -> c
oertl Apr 19, 2022
767e52f
renamed method isLowerCaseNum -> isDigit
oertl Apr 19, 2022
c18dcfe
use empty list instead of null for otherKeyValuePairs
oertl Apr 19, 2022
be68ff2
simplified isValueByte method
oertl Apr 19, 2022
30e42e3
Update consistent-sampling/src/main/java/io/opentelemetry/contrib/sta…
oertl Apr 19, 2022
d209258
Merge branch 'consistent-sampling' of github.com:dynatrace-oss-contri…
oertl Apr 19, 2022
7f58aa1
renamed variable sepPos -> separatorPos
oertl Apr 19, 2022
938382a
replaced 0. and 1. by 0.0 and 1.0
oertl Apr 19, 2022
630b157
improved readability as suggested by @trask
oertl Apr 19, 2022
1dca6f4
removed unused methods from RandomUtil
oertl Apr 19, 2022
09cc3a0
added javadoc
oertl Apr 19, 2022
15a8d50
renamed targetSpansPerNanosLimit -> targetSpansPerNanosecondLimit
oertl Apr 19, 2022
f70454a
throw IllegalArgumentException instead of returning NaN + added comments
oertl Apr 19, 2022
8d3a731
renamed tsStartPos -> startPos and eqPos -> colonPos
oertl Apr 19, 2022
3b7f045
improved readability of invariant check
oertl Apr 19, 2022
878c236
added some more test cases
oertl Apr 19, 2022
6fc45cd
fixed typo
oertl Apr 19, 2022
06cbeea
removed unused method
oertl Apr 19, 2022
edac8a9
refactored random generator
oertl Apr 19, 2022
da42018
made OtelTraceState and RandomGenerator package private and moved the…
oertl Apr 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/component_owners.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ components:
aws-xray:
- anuraaga
- willarmiros
consistent-sampling:
- oertl
samplers:
- anuraaga
- iNikem
Expand Down
12 changes: 12 additions & 0 deletions consistent-sampling/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
plugins {
id("otel.java-conventions")
id("otel.publish-conventions")
}

description = "Sampler and exporter implementations for consistent sampling"

dependencies {
api("io.opentelemetry:opentelemetry-sdk-trace")
testImplementation("org.hipparchus:hipparchus-core:2.0")
testImplementation("org.hipparchus:hipparchus-stat:2.0")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

import io.opentelemetry.contrib.state.OtelTraceState;
import javax.annotation.concurrent.Immutable;

@Immutable
final class ConsistentAlwaysOffSampler extends ConsistentSampler {

private ConsistentAlwaysOffSampler() {}

private static final ConsistentSampler INSTANCE = new ConsistentAlwaysOffSampler();

static ConsistentSampler getInstance() {
return INSTANCE;
}

@Override
protected int getP(int parentP, boolean isRoot) {
return OtelTraceState.getMaxP();
}

@Override
public String getDescription() {
return "ConsistentAlwaysOffSampler";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

import javax.annotation.concurrent.Immutable;

@Immutable
final class ConsistentAlwaysOnSampler extends ConsistentSampler {

private ConsistentAlwaysOnSampler() {}

private static final ConsistentSampler INSTANCE = new ConsistentAlwaysOnSampler();

static ConsistentSampler getInstance() {
return INSTANCE;
}

@Override
protected int getP(int parentP, boolean isRoot) {
return 0;
}

@Override
public String getDescription() {
return "ConsistentAlwaysOnSampler";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

import static java.util.Objects.requireNonNull;

import io.opentelemetry.contrib.state.OtelTraceState;
import javax.annotation.concurrent.Immutable;

/**
* A consistent sampler composed of two consistent samplers.
*
* <p>This sampler samples if both samplers would sample.
oertl marked this conversation as resolved.
Show resolved Hide resolved
*/
@Immutable
final class ConsistentComposedAndSampler extends ConsistentSampler {

private final ConsistentSampler sampler1;
private final ConsistentSampler sampler2;
private final String description;

ConsistentComposedAndSampler(ConsistentSampler sampler1, ConsistentSampler sampler2) {
this.sampler1 = requireNonNull(sampler1);
this.sampler2 = requireNonNull(sampler2);
this.description =
"ConsistentComposedAndSampler{"
+ "sampler1="
+ sampler1.getDescription()
+ ",sampler2="
+ sampler2.getDescription()
+ '}';
}

@Override
protected int getP(int parentP, boolean isRoot) {
int p1 = sampler1.getP(parentP, isRoot);
int p2 = sampler2.getP(parentP, isRoot);
if (OtelTraceState.isValidP(p1) && OtelTraceState.isValidP(p2)) {
return Math.max(p1, p2);
} else {
return OtelTraceState.getInvalidP();
}
}

@Override
public String getDescription() {
return description;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

import static java.util.Objects.requireNonNull;

import io.opentelemetry.contrib.state.OtelTraceState;
import javax.annotation.concurrent.Immutable;

/**
* A consistent sampler composed of two consistent samplers.
*
* <p>This sampler samples if any of the two samplers would sample.
*/
@Immutable
final class ConsistentComposedOrSampler extends ConsistentSampler {

private final ConsistentSampler sampler1;
private final ConsistentSampler sampler2;
private final String description;

ConsistentComposedOrSampler(ConsistentSampler sampler1, ConsistentSampler sampler2) {
this.sampler1 = requireNonNull(sampler1);
this.sampler2 = requireNonNull(sampler2);
this.description =
"ConsistentComposedOrSampler{"
+ "sampler1="
+ sampler1.getDescription()
+ ",sampler2="
+ sampler2.getDescription()
+ '}';
}

@Override
protected int getP(int parentP, boolean isRoot) {
int p1 = sampler1.getP(parentP, isRoot);
int p2 = sampler2.getP(parentP, isRoot);
if (OtelTraceState.isValidP(p1)) {
if (OtelTraceState.isValidP(p2)) {
return Math.min(p1, p2);
}
return p1;
} else {
if (OtelTraceState.isValidP(p2)) {
return p2;
}
return OtelTraceState.getInvalidP();
}
}

@Override
public String getDescription() {
return description;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

import static java.util.Objects.requireNonNull;

import io.opentelemetry.contrib.util.RandomGenerator;
import javax.annotation.concurrent.Immutable;

/**
* A consistent sampler that makes the same sampling decision as the parent and optionally falls
* back to an alternative consistent sampler, if the parent p-value is invalid (like for root
* spans).
*/
@Immutable
final class ConsistentParentBasedSampler extends ConsistentSampler {

private final ConsistentSampler rootSampler;

private final String description;

/**
* Constructs a new consistent parent based sampler using the given root sampler.
*
* @param rootSampler the root sampler
*/
ConsistentParentBasedSampler(ConsistentSampler rootSampler) {
this(rootSampler, RandomGenerator.getDefault());
}

/**
* Constructs a new consistent parent based sampler using the given root sampler and the given
* thread-safe random generator.
*
* @param rootSampler the root sampler
* @param threadSafeRandomGenerator a thread-safe random generator
*/
ConsistentParentBasedSampler(
ConsistentSampler rootSampler, RandomGenerator threadSafeRandomGenerator) {
super(threadSafeRandomGenerator);
this.rootSampler = requireNonNull(rootSampler);
this.description =
"ConsistentParentBasedSampler{rootSampler=" + rootSampler.getDescription() + '}';
}

@Override
protected int getP(int parentP, boolean isRoot) {
if (isRoot) {
return rootSampler.getP(parentP, isRoot);
} else {
return parentP;
}
}

@Override
public String getDescription() {
return description;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

import io.opentelemetry.contrib.util.RandomGenerator;
import javax.annotation.concurrent.Immutable;

/** A consistent sampler that samples with a fixed probability. */
@Immutable
final class ConsistentProbabilityBasedSampler extends ConsistentSampler {

private final int lowerPValue;
private final int upperPValue;
private final double probabilityToUseLowerPValue;
private final String description;

/**
* Constructor.
*
* @param samplingProbability the sampling probability
*/
ConsistentProbabilityBasedSampler(double samplingProbability) {
this(samplingProbability, RandomGenerator.getDefault());
}

/**
* Constructor.
*
* @param samplingProbability the sampling probability
* @param randomGenerator a random generator
*/
ConsistentProbabilityBasedSampler(double samplingProbability, RandomGenerator randomGenerator) {
super(randomGenerator);
if (samplingProbability < 0.0 || samplingProbability > 1.0) {
throw new IllegalArgumentException("Sampling probability must be in range [0.0, 1.0]!");
}
this.description =
String.format("ConsistentProbabilityBasedSampler{%.6f}", samplingProbability);

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

if (lowerPValue == upperPValue) {
probabilityToUseLowerPValue = 1;
} else {
double upperSamplingProbability = getSamplingProbability(lowerPValue);
double lowerSamplingProbability = getSamplingProbability(upperPValue);
probabilityToUseLowerPValue =
(samplingProbability - lowerSamplingProbability)
/ (upperSamplingProbability - lowerSamplingProbability);
}
}

@Override
protected int getP(int parentP, boolean isRoot) {
if (randomGenerator.nextBoolean(probabilityToUseLowerPValue)) {
return lowerPValue;
} else {
return upperPValue;
}
}

@Override
public String getDescription() {
return description;
}
}
Loading