> ## 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.

# Telemetry pipeline

> Exporters, samplers, batching, and where data goes.

`@sedata-ai/mcp` runs an OpenTelemetry `NodeSDK` inside your process and exports
data over OTLP. This page covers the moving parts.

## Exporters

The exporter type is controlled by `config.exporterType`:

| Value       | Default? | Behavior                                                                    |
| ----------- | -------- | --------------------------------------------------------------------------- |
| `otlp-http` | ✅        | Sends traces to `<endpoint>/traces` and metrics to `<endpoint>/metrics`.    |
| `otlp-grpc` |          | gRPC trace exporter (metrics still HTTP).                                   |
| `console`   |          | `ConsoleSpanExporter` writes spans to stdout. No metric reader is attached. |

Endpoint composition:

```text theme={null}
exporterEndpoint = "https://otel.sedata-ai.tech/v1"
                       ↓
trace exporter URL  → https://otel.sedata-ai.tech/v1/traces
metric exporter URL → https://otel.sedata-ai.tech/v1/metrics
```

A trailing slash is normalized — both `https://host/v1` and `https://host/v1/`
work.

## Authentication headers

`exporterAuth` is converted to HTTP headers and applied to **both** the trace
and metric exporters:

| `type`   | Header(s) sent                                                |
| -------- | ------------------------------------------------------------- |
| `bearer` | `Authorization: Bearer <token>`                               |
| `apiKey` | `x-api-key: <apiKey>`                                         |
| `basic`  | *Currently disabled in the exporter (validated but not sent)* |

<Note>
  `basic` auth is permitted by `ConfigValidator` but the actual header is
  commented out in the OTLP setup. Use `bearer` or `apiKey` until that ships.
</Note>

## Sampling

```ts theme={null}
const config: TelemetryConfig = {
  samplingRate: 1.0, // default: keep everything
}
```

The sampler is `TraceIdRatioBasedSampler` — deterministic by trace id, head-based.
Out-of-range values throw on validation.

| Value | Effect                    |
| ----- | ------------------------- |
| `1.0` | All traces recorded.      |
| `0.1` | \~10% of traces recorded. |
| `0`   | No traces.                |

Metrics are not sampled — `enableMetrics` is the only switch for metrics.

## Batching

Trace exporter batching is delegated to OTel's standard `BatchSpanProcessor`
defaults.

The metric reader is a `PeriodicExportingMetricReader` with two knobs:

| Option                   | Default | Purpose                     |
| ------------------------ | ------- | --------------------------- |
| `metricExportIntervalMs` | `5000`  | How often to flush metrics. |
| `batchTimeoutMs`         | `2000`  | Per-batch export timeout.   |

## Resource detection

The SDK runs these resource detectors at startup:

* `envDetector` — picks up `OTEL_RESOURCE_ATTRIBUTES`.
* `hostDetector` — host name + arch.
* `osDetector` — OS name + version.
* `serviceInstanceIdDetectorSync` — generates a stable `service.instance.id`.

Plus the package adds:

* `service.name` from `config.serverName`
* `service.version` from `config.serverVersion`
* `mcp.session.id` (per-process UUID)

## Toggles

Every part of the pipeline is opt-out:

| Flag                       | Default | Effect                                              |
| -------------------------- | ------- | --------------------------------------------------- |
| `enableTracing`            | `true`  | Set `false` to skip the trace exporter and sampler. |
| `enableMetrics`            | `true`  | Set `false` to skip the metric reader.              |
| `enableArgumentCollection` | `false` | Add tool args to span attributes.                   |
| `enablePIISanitization`    | `true`  | Reserved — used by the data-processor pipeline.     |

## Custom data processors

You can mutate every attribute set right before export:

```ts theme={null}
const config: TelemetryConfig = {
  // ...
  dataProcessors: [
    (data) => {
      // remove anything matching a pattern
      const cleaned = { ...data }
      delete cleaned['mcp.request.argument.api_key']
      return cleaned
    },
  ],
}
```

Processors run in order and receive the merged attribute object (always
includes `mcp.session.id`). See [Data processors](/guides/data-processors).

## Shutdown

Always call `shutdown` on graceful exit so in-flight metrics flush:

```ts theme={null}
process.on('SIGTERM', async () => {
  await telemetry.shutdown()
  process.exit(0)
})
```

`shutdown()` records `mcp.server.session.duration` and then calls
`NodeSDK.shutdown()`, which flushes both the trace exporter and metric reader.

## Next

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/guides/authentication">
    All three auth shapes with examples.
  </Card>

  <Card title="Sampling" icon="filter" href="/guides/sampling">
    Choosing a rate that survives production.
  </Card>
</CardGroup>
