
- Sampling decisions are normally made at span creation time (head-based sampling). Making decisions at the source reduces the amount of telemetry transmitted and processed.
- The sampling decision affects child spans and downstream services—propagating a consistent decision prevents partial traces from being stored.
- Delaying decisions (tail-based sampling) allows using whole-trace attributes to make smarter sampling choices but requires collecting more data up-front and is typically implemented in the Collector.

- The sampler evaluates the current span at creation time and decides whether it should be recorded.
- Sampling decisions commonly propagate to child spans: if a parent is not sampled, child spans are typically dropped to keep trace consistency.
- Trace flags (for example, the sampled bit in the trace context) carry the sampling choice across process boundaries so the distributed system respects the decision end-to-end.

| Sampler | Purpose / Use Case | Example |
|---|---|---|
| AlwaysOnSampler | Records every span. Best for development, debugging, or short-lived environments where full visibility is required. | AlwaysOnSampler() |
| AlwaysOffSampler | Records no spans. Useful to keep instrumentation hooks enabled while disabling telemetry. | AlwaysOffSampler() |
| TraceIdRatioBasedSampler | Samples a fixed fraction of traces (head-based). Good for scalable production sampling (e.g., 10% or 20%). | TraceIdRatioBased(0.2) |
| ParentBasedSampler | Adopts the parent’s sampling decision if present; otherwise falls back to a configured root sampler. Useful for distributed systems to maintain consistent downstream behavior. | ParentBased(root=TraceIdRatioBased(0.2)) |

- Configure TraceIdRatioBased sampler at the SDK level for 20% sampling:
- Combine ParentBased with TraceIdRatioBased as a fallback (parent decision preferred):
Head-based sampling makes the decision at span creation time (in the SDK). Tail-based sampling can make decisions later based on whole-trace information; tail-based sampling is typically implemented in the OpenTelemetry Collector.
Avoid AlwaysOn in high-volume production unless you have capacity for the inbound throughput, storage, and query costs. Use rate-limited or ratio-based sampling for scalable production environments.
- Use AlwaysOn for complete visibility during development and troubleshooting.
- Use AlwaysOff to disable tracing while keeping instrumentation code intact.
- Use TraceIdRatioBased or ParentBased with a ratio fallback for production to reduce telemetry volume while preserving representative traces.
- Prefer making sampling decisions as close to the source as possible to minimize unnecessary network and backend load. If you need whole-trace signals (for anomaly detection or root-cause across entire traces), consider tail-based sampling implemented in the Collector.

- OpenTelemetry Tracing Concepts: https://opentelemetry.io/docs/concepts/signals/traces/
- OpenTelemetry Collector: https://opentelemetry.io/docs/collector/
- SDK sampling configuration: https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/