Sampling

Sampling is a process that restricts the amount of spans that are generated by a system. Which sampler to use depends on your needs. In general, decide which sampler to use at the start of a trace and allow the sampling decision to propagate to other services.

Default behavior

By default, all spans are sampled, resulting in 100% of traces being sampled. If your observability backend has constraints or budgetary restrictions on the amount of data ingested, you can introduce a sampler and adjust the sample rates accordingly. If you do not need to manage data volume, you don’t need to set a sampler and can use the default.

Environment variables

You can configure the sampler with environment variables or system properties. Reference the configuration documentation for the available options.

For example, to configure the SDK to sample spans such that only 10% of traces get created:

export OTEL_TRACES_SAMPLER="traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1"

Samplers

ParentBasedSampler

When sampling, the ParentBasedSampler is most often used for head sampling. It uses the sampling decision of the Span’s parent, or the fact that there is no parent, to know which secondary sampler to use.

If the parent span is sampled, the child span will also be sampled. Conversely, if the parent span is not sampled, the child span will not be sampled either. This ensures consistency in sampling decisions within a trace.

TraceIDRatioBasedSampler

The TraceIdRatioBasedSampler deterministically samples a percentage of traces that you pass in as a parameter.

This sampler is useful when you want to control the overall sampling rate across all traces, regardless of their parent spans. It provides a consistent rate of sampling for all traces initiated.

Configuration in code

A sampler can be set on the tracer provider using the setSampler method, as follows:

import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.samplers.Sampler;

public class Example {
  public static void main(String[] args) {
    // Configure the tracer provider with the desired sampler
    SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
      .setSampler(Sampler.alwaysOn()) // Set to always sample traces
      // or
      .setSampler(Sampler.alwaysOff()) // Set to never sample traces
      // or
      .setSampler(Sampler.traceIdRatioBased(0.5)) // Set to sample a fraction of traces
      .build();
  }
}

The alwaysOn value means that every span is sampled, while alwaysOff means that no span is sampled. When you’re getting started, or in a development environment, use alwaysOn.

Other samplers include:

  • traceIdRatioBased, which samples a fraction of spans, based on the fraction given to the sampler. If you set 0.5, half of all the spans are sampled. Currently, only the ratio of traces that are sampled can be relied on, not how the sampled traces are determined. Only use this sampler for root spans that use parentBased.
  • parentBased, which uses the parent span to make sampling decisions, if present. By default, the tracer provider uses a parentBased sampler with the alwaysOn sampler.