Skip to content

Commit

Permalink
sampler and span processor prototype implementations for consistent s…
Browse files Browse the repository at this point in the history
…ampling (#226)

* sampler and exporter implementations for consistent sampling

* improved dependencies (in particular, removed dependency on guava)

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

Co-authored-by: Anuraag Agrawal <[email protected]>

* reverted some changes

* removed wrong immutable annotation

* added javadoc

* avoid else statements when returning

* factory methods for consistent samplers, avoid exposure of implementations

* added javadoc for AND and OR sampler composition

* replaced use of synchronized by atomic reference

* simplified thread local initialization

* removed consistent reservoir sampling

* improved comment

* removed unnecessary clipping of sampling probability

* added javadoc explaining maths of implementation

* Update consistent-sampling/src/main/java/io/opentelemetry/contrib/state/OtelTraceState.java

Co-authored-by: Joshua MacDonald <[email protected]>

* Update consistent-sampling/src/main/java/io/opentelemetry/contrib/state/OtelTraceState.java

Co-authored-by: Joshua MacDonald <[email protected]>

* Update consistent-sampling/src/main/java/io/opentelemetry/contrib/state/OtelTraceState.java

Co-authored-by: Joshua MacDonald <[email protected]>

* Update consistent-sampling/src/main/java/io/opentelemetry/contrib/state/OtelTraceState.java

Co-authored-by: Joshua MacDonald <[email protected]>

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

Co-authored-by: Trask Stalnaker <[email protected]>

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

Co-authored-by: Trask Stalnaker <[email protected]>

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

Co-authored-by: Trask Stalnaker <[email protected]>

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

Co-authored-by: Trask Stalnaker <[email protected]>

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

Co-authored-by: Trask Stalnaker <[email protected]>

* added component owner for consistent sampling

* Update consistent-sampling/src/main/java/io/opentelemetry/contrib/state/OtelTraceState.java

Co-authored-by: Trask Stalnaker <[email protected]>

* removed nonnull annotation

* renamed variable s -> pair

* renamed char parameter r -> c

* renamed method isLowerCaseNum -> isDigit

* use empty list instead of null for otherKeyValuePairs

* simplified isValueByte method

* Update consistent-sampling/src/main/java/io/opentelemetry/contrib/state/OtelTraceState.java

Co-authored-by: Trask Stalnaker <[email protected]>

* renamed variable sepPos -> separatorPos

* replaced 0. and 1. by 0.0 and 1.0

* improved readability as suggested by @trask

* removed unused methods from RandomUtil

* added javadoc

* renamed targetSpansPerNanosLimit -> targetSpansPerNanosecondLimit

* throw IllegalArgumentException instead of returning NaN + added comments

* renamed tsStartPos -> startPos and eqPos -> colonPos

* improved readability of invariant check

* added some more test cases

* fixed typo

* removed unused method

* refactored random generator

* made OtelTraceState and RandomGenerator package private and moved them to samplers package

Co-authored-by: Anuraag Agrawal <[email protected]>
Co-authored-by: Joshua MacDonald <[email protected]>
Co-authored-by: Trask Stalnaker <[email protected]>
  • Loading branch information
4 people committed Apr 20, 2022
1 parent 7ca173b commit 0b9ab8a
Show file tree
Hide file tree
Showing 17 changed files with 1,782 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/component_owners.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,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,30 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

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,51 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

import static java.util.Objects.requireNonNull;

import javax.annotation.concurrent.Immutable;

/**
* A consistent sampler composed of two consistent samplers.
*
* <p>This sampler samples if both samplers would sample.
*/
@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,57 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

import static java.util.Objects.requireNonNull;

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,61 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

import static java.util.Objects.requireNonNull;

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,69 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.samplers;

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

0 comments on commit 0b9ab8a

Please sign in to comment.