> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sedata-ai.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Sampling

> Trim trace volume without losing signal.

The package exposes one knob for trace sampling: `samplingRate`. It maps
directly to OpenTelemetry's `TraceIdRatioBasedSampler`.

## How it works

`TraceIdRatioBasedSampler(rate)` keeps a deterministic fraction of traces by
hashing the trace id. Same trace → same decision across services, which keeps
distributed traces consistent.

| Rate   | Kept               |
| ------ | ------------------ |
| `1.0`  | 100% (default)     |
| `0.5`  | \~50%              |
| `0.1`  | \~10%              |
| `0.01` | \~1%               |
| `0`    | none (sampler off) |

## Setting it

```ts theme={null}
const config: TelemetryConfig = {
  serverName: 'my-server',
  serverVersion: '1.0.0',
  exporterEndpoint: 'https://otel.sedata-ai.tech/v1',
  samplingRate: 0.1, // keep 10%
}
```

`ConfigValidator` rejects anything outside `[0, 1]`:

```text theme={null}
Error: samplingRate must be between 0 and 1
```

## What gets sampled

| Signal                 | Sampled by `samplingRate`?                                     |
| ---------------------- | -------------------------------------------------------------- |
| Spans (traces)         | ✅                                                              |
| Metrics                | ❌ — metrics are aggregations, sampling doesn't apply           |
| Safety-check API calls | ❌ — every call to a `safetyCheck`-wrapped handler hits the API |

If you need to reduce safety-check load, you have to gate the wrapper itself
(e.g. only wrap a few high-risk tools).

## Recommended starting points

<CardGroup cols={3}>
  <Card title="Local dev" icon="laptop">
    `samplingRate: 1.0` — see everything.
  </Card>

  <Card title="Staging" icon="server">
    `samplingRate: 1.0` — keep volume comparable to prod's signal-to-noise.
  </Card>

  <Card title="Production" icon="rocket">
    `samplingRate: 0.1`–`0.25` — adjust by tool volume and storage budget.
  </Card>
</CardGroup>

## Tail sampling instead?

`samplingRate` is **head-based** — the decision is made when the trace starts.
If you want to keep all errored traces while dropping most successes, you'll
want **tail sampling**, which lives in an OpenTelemetry Collector, not the
SDK. Point `exporterEndpoint` at a collector with the `tail_sampling`
processor configured.

```yaml otel-collector.yaml theme={null}
processors:
  tail_sampling:
    decision_wait: 5s
    policies:
      - name: errors
        type: status_code
        status_code: { status_codes: [ERROR] }
      - name: slow
        type: latency
        latency: { threshold_ms: 500 }
      - name: sample-rest
        type: probabilistic
        probabilistic: { sampling_percentage: 5 }
```

Then run `@sedata-ai/mcp` with `samplingRate: 1.0` so the collector receives
everything and makes the call.

## Disabling tracing entirely

If you want metrics-only:

```ts theme={null}
const config: TelemetryConfig = {
  // ...
  enableTracing: false,
}
```

This skips the trace exporter and sampler — no span allocations at all.

## Next

<CardGroup cols={2}>
  <Card title="Telemetry pipeline" icon="signal-stream" href="/concepts/telemetry-pipeline">
    Where samplers fit in the broader export path.
  </Card>

  <Card title="Production deployment" icon="rocket" href="/guides/production-deployment">
    Pre-flight checklist for prod.
  </Card>
</CardGroup>
