Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
1 change: 1 addition & 0 deletions sdk-extensions/incubator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies {
testImplementation(project(":exporters:zipkin"))
testImplementation(project(":sdk-extensions:jaeger-remote-sampler"))
testImplementation(project(":extensions:trace-propagators"))
testImplementation("edu.berkeley.cs.jqf:jqf-fuzz")
testImplementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator")
testImplementation("com.linecorp.armeria:armeria-junit5")

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.extension.incubator.trace.samplers;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.data.LinkData;
import java.util.List;
import java.util.function.Function;

enum ComposableAlwaysOffSampler implements ComposableSampler {
INSTANCE;

private static final SamplingIntent INTENT =
SamplingIntent.create(
ImmutableSamplingIntent.INVALID_THRESHOLD,
/* thresholdReliable= */ false,
Attributes.empty(),
Function.identity());

@Override
public SamplingIntent getSamplingIntent(
Context parentContext,
String traceId,
String name,
SpanKind spanKind,
Attributes attributes,
List<LinkData> parentLinks) {
return INTENT;
}

@Override
public String getDescription() {
return "ComposableAlwaysOffSampler";
}

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

package io.opentelemetry.sdk.extension.incubator.trace.samplers;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.data.LinkData;
import java.util.List;
import java.util.function.Function;

enum ComposableAlwaysOnSampler implements ComposableSampler {
INSTANCE;

private static final SamplingIntent INTENT =
SamplingIntent.create(
ImmutableSamplingIntent.MIN_THRESHOLD,
/* thresholdReliable= */ true,
Attributes.empty(),
Function.identity());

@Override
public SamplingIntent getSamplingIntent(
Context parentContext,
String traceId,
String name,
SpanKind spanKind,
Attributes attributes,
List<LinkData> parentLinks) {
return INTENT;
}

@Override
public String getDescription() {
return "ComposableAlwaysOnSampler";
}

@Override
public String toString() {
return getDescription();
}
}
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.sdk.extension.incubator.trace.samplers;

import static io.opentelemetry.sdk.extension.incubator.trace.samplers.ImmutableSamplingIntent.INVALID_THRESHOLD;
import static io.opentelemetry.sdk.extension.incubator.trace.samplers.ImmutableSamplingIntent.MIN_THRESHOLD;
import static io.opentelemetry.sdk.extension.incubator.trace.samplers.ImmutableSamplingIntent.isValidThreshold;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.data.LinkData;
import java.util.List;
import java.util.function.Function;

final class ComposableParentThresholdSampler implements ComposableSampler {

private final ComposableSampler rootSampler;
private final String description;

ComposableParentThresholdSampler(ComposableSampler rootSampler) {
this.rootSampler = rootSampler;
this.description = "ComposableParentThresholdSampler{rootSampler=" + rootSampler + "}";
}

@Override
public SamplingIntent getSamplingIntent(
Context parentContext,
String traceId,
String name,
SpanKind spanKind,
Attributes attributes,
List<LinkData> parentLinks) {
SpanContext parentSpanContext = Span.fromContext(parentContext).getSpanContext();
if (!parentSpanContext.isValid()) {
return rootSampler.getSamplingIntent(
parentContext, traceId, name, spanKind, attributes, parentLinks);
}

OtelTraceState otTraceState = OtelTraceState.parse(parentSpanContext.getTraceState());
if (isValidThreshold(otTraceState.getThreshold())) {
return ImmutableSamplingIntent.create(
otTraceState.getThreshold(),
/* thresholdReliable= */ true,
Attributes.empty(),
Function.identity());
}

long threshold =
parentSpanContext.getTraceFlags().isSampled() ? MIN_THRESHOLD : INVALID_THRESHOLD;
return ImmutableSamplingIntent.create(
threshold, /* thresholdReliable= */ false, Attributes.empty(), Function.identity());
}

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

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

package io.opentelemetry.sdk.extension.incubator.trace.samplers;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.data.LinkData;
import java.util.List;

/** A sampler that can be composed to make a final sampling decision. */
public interface ComposableSampler {
/** Returns a {@link ComposableSampler} that does not sample any span. */
static ComposableSampler alwaysOff() {
return ComposableAlwaysOffSampler.INSTANCE;
}

/** Returns a {@link ComposableSampler} that samples all spans. */
static ComposableSampler alwaysOn() {
return ComposableAlwaysOnSampler.INSTANCE;
}

/** Returns a {@link ComposableSampler} that samples each span with a fixed ratio. */
static ComposableSampler traceIdRatioBased(double ratio) {
return new ComposableTraceIdRatioBasedSampler(ratio);
}

/**
* Returns a {@link ComposableSampler} that respects the sampling decision of the parent span or
* falls back to the given sampler if it is a root span.
*/
static ComposableSampler parentThreshold(ComposableSampler rootSampler) {
return new ComposableParentThresholdSampler(rootSampler);
}

/** Returns the {@link SamplingIntent} to use to make a sampling decision. */
SamplingIntent getSamplingIntent(
Context parentContext,
String traceId,
String name,
SpanKind spanKind,
Attributes attributes,
List<LinkData> parentLinks);

/** Returns a description of the sampler implementation. */
String getDescription();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.extension.incubator.trace.samplers;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.data.LinkData;
import java.util.List;
import java.util.function.Function;

final class ComposableTraceIdRatioBasedSampler implements ComposableSampler {
private static long calculateThreshold(double ratio) {
return ImmutableSamplingIntent.MAX_THRESHOLD
- Math.round(ratio * (double) ImmutableSamplingIntent.MAX_THRESHOLD);
}

private final SamplingIntent intent;
private final String description;

ComposableTraceIdRatioBasedSampler(double ratio) {
long threshold = calculateThreshold(ratio);
String thresholdStr;
if (threshold == ImmutableSamplingIntent.MAX_THRESHOLD) {
thresholdStr = "max";

// Same as ComposableAlwaysOffSampler, notably the threshold is not considered reliable.
// The spec mentions returning an instance of ComposableAlwaysOffSampler in this case but
// it seems clearer if the description of the sampler matches the user's request.
this.intent =
SamplingIntent.create(
ImmutableSamplingIntent.INVALID_THRESHOLD,
/* thresholdReliable= */ false,
Attributes.empty(),
Function.identity());
} else {
StringBuilder sb = new StringBuilder();
OtelTraceState.serializeTh(threshold, sb);
thresholdStr = sb.toString();

this.intent =
SamplingIntent.create(
threshold, /* thresholdReliable= */ true, Attributes.empty(), Function.identity());
}
this.description =
"ComposableTraceIdRatioBasedSampler{threshold=" + thresholdStr + ", ratio=" + ratio + "}";
}

@Override
public SamplingIntent getSamplingIntent(
Context parentContext,
String traceId,
String name,
SpanKind spanKind,
Attributes attributes,
List<LinkData> parentLinks) {
return intent;
}

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

@Override
public String toString() {
return this.getDescription();
}
}
Loading
Loading