---
title: "Tracing (OpenTelemetry)"
description: "Opt-in OpenTelemetry tracing for STT, LLM, TTS, endpointing, barge-in, and tool calls."
icon: "chart-network"
---

Patter ships opt-in OpenTelemetry tracing that covers the hot spots on the voice pipeline: STT, endpointing, LLM, TTS, barge-in, and tool calls. Every span carries the current `getpatter.call.id` so you can group by call in your backend. Span names are identical across Python and TypeScript — one dashboard query covers both runtimes.

## Enable tracing

Tracing is disabled by default. Set the env flag and call `initTracing` once at process start:

```bash
export PATTER_OTEL_ENABLED=1
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318   # any OTLP/HTTP collector
```

```typescript
import { initTracing } from "getpatter";

initTracing({
  serviceName: "my-voice-bot",
  otlpEndpoint: "http://localhost:4318",
  resourceAttributes: { "deployment.environment": "staging" },
});
```

If `PATTER_OTEL_ENABLED` is not set, `initTracing` is a no-op and every span becomes a no-op — **zero cost** when disabled.

## Emitted spans

| Span name | Fires | Attributes |
|---|---|---|
| `getpatter.call` | One per call (root span) | `getpatter.call.id`, `getpatter.call.direction`, `getpatter.call.provider_mode` |
| `getpatter.stt` | One per final transcript | `getpatter.stt.text_len`, `getpatter.stt.confidence` |
| `getpatter.endpoint` | One per detected end-of-utterance | `getpatter.endpoint.silence_ms` |
| `getpatter.llm` | One per LLM iteration (incl. tool rounds) — wraps the pipeline LLM call so TTFT is measured per turn | `getpatter.llm.iteration`, `getpatter.llm.history_size`, `getpatter.llm.ttft_ms` |
| `getpatter.tts` | One per synthesized sentence | `getpatter.tts.text_len` |
| `getpatter.bargein` | One per barge-in event | `getpatter.bargein.cancelled_text_len` |
| `getpatter.tool` | One per tool invocation | `getpatter.tool.name`, `getpatter.tool.transport` |

## PII hygiene

Patter never exports user utterances, tool payloads, or LLM content as span attributes. Only sizes, counts, and identifiers are emitted — traces are safe to ship to a shared Jaeger / Honeycomb / Grafana Cloud instance.

## Shutdown

Call `shutdownTracing()` during graceful shutdown to flush any pending spans:

```typescript
import { shutdownTracing } from "getpatter";

await shutdownTracing();
```

## Troubleshooting

**No spans appear** → confirm `PATTER_OTEL_ENABLED=1` is set *in the process that calls `initTracing`*. Quick check:

```typescript
import { isTracingEnabled } from "getpatter";
console.log(isTracingEnabled());
```

**Collector refuses spans** → the endpoint defaults to OTLP/HTTP on port 4318. If you're running the gRPC-only OTel Collector image, switch to `otel/opentelemetry-collector-contrib` or enable the HTTP receiver in your collector config.
