# `Otel.Trace.Sampler`
[🔗](https://github.com/yangbancode/otel/blob/main/lib/otel/trace/sampler.ex#L1)

Hard-coded `ParentBased(root=AlwaysOn)` sampler — the spec
default per `trace/sdk.md` L421 and the only sampler this
SDK ships.

Decision matrix (`trace/sdk.md` §ParentBased L584-590 with
default delegates L579-582):

| Parent              | Decision           |
|---------------------|--------------------|
| absent (root)       | `record_and_sample`|
| sampled (any)       | `record_and_sample`|
| not sampled (any)   | `drop`             |

The full 5-branch ParentBased decorator is collapsed because
every branch resolves to `AlwaysOn` (sampled) or `AlwaysOff`
(not sampled) — local/remote distinction has no behavioural
effect with default delegates.

## Public API

| Function | Role |
|---|---|
| `should_sample/6` | **SDK** (OTel API MUST) — `trace/sdk.md` §ShouldSample L342-L406 |
| `description/0` | **SDK** (OTel API MUST) — `trace/sdk.md` §GetDescription L408-L417 |

All functions are safe for concurrent use, satisfying spec
`trace/sdk.md` L1284 — *"Sampler — ShouldSample and
GetDescription MUST be safe to be called concurrently."*

## References

- OTel Trace SDK §Sampler: `opentelemetry-specification/specification/trace/sdk.md` L329-L460
- OTel Trace SDK §Built-in samplers: same file L418-L590

# `primitive`

```elixir
@type primitive() ::
  String.t() | {:bytes, binary()} | boolean() | integer() | float() | nil
```

# `primitive_any`

```elixir
@type primitive_any() ::
  primitive() | [primitive_any()] | %{required(String.t()) =&gt; primitive_any()}
```

# `sampling_decision`

```elixir
@type sampling_decision() :: :drop | :record_only | :record_and_sample
```

# `sampling_result`

```elixir
@type sampling_result() ::
  {sampling_decision(), %{required(String.t()) =&gt; primitive_any()},
   Otel.Trace.TraceState.t()}
```

# `description`

```elixir
@spec description() :: String.t()
```

**SDK** (OTel API MUST) — `GetDescription`
(`trace/sdk.md` §GetDescription L408-L417).

Returns the spec-style ParentBased descriptor with all five
delegate branches enumerated. ParentBased itself has no MUST
format; this format mirrors the description the previous
composable implementation produced, so external observers
(debug pages, log lines) see no string change.

# `should_sample`

```elixir
@spec should_sample(
  ctx :: Otel.Ctx.t(),
  trace_id :: Otel.Trace.TraceId.t(),
  links :: [Otel.Trace.Link.t()],
  name :: String.t(),
  kind :: Otel.Trace.SpanKind.t(),
  attributes :: %{required(String.t()) =&gt; primitive_any()}
) :: sampling_result()
```

**SDK** (OTel API MUST) — `ShouldSample`
(`trace/sdk.md` §ShouldSample L342-L406).

Returns `record_and_sample` for root spans and any span
whose parent has the sampled bit set; `drop` for spans whose
parent has the bit unset. Tracestate is propagated from the
parent unchanged.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
