Skip to content

OpenTelemetry Receiver

providers/genericotel receives OTLP/HTTP JSON metrics from AI coding agents and writes ai.usage.recorded events (otel-mode provenance, confidence 1.0) directly to the event store. It exists because local session history is subject to retention — live capture is the durable path for token and cost data.

Only the JSON encoding is supported: protobuf would pull heavy dependencies into core. Configure exporters with OTEL_EXPORTER_OTLP_PROTOCOL=http/json.

Usage

r, err := genericotel.New(genericotel.Options{
    Store:   s, // *store.Store, required
    Subject: omnidevx.SubjectRef{PersonID: "person:jane"},
})
http.ListenAndServe("127.0.0.1:4318", r.Handler())

Handler serves POST /v1/metrics (parsed) and POST /v1/logs (acknowledged and discarded — log bodies can contain prompt text and are never stored). For a ready-made daemon with launchd setup, a query API, and Grafana dashboards, see omnidevx-otel.

Recognized metrics

Metric Mapped to
claude_code.token.usage Token attributes by type datapoint attribute (input, output, cacheRead, cacheCreation)
claude_code.cost.usage cost_usd
codex.token.usage, codex.cost.usage Same mapping for Codex CLI

Unrecognized metrics are ignored — the receiver is additive, not a general metrics database. Datapoint model and session.id attributes carry through; resource attributes like user.email do not.

Claude Code configuration

~/.claude/settings.json:

{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_METRICS_EXPORTER": "otlp",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "http/json",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "http://127.0.0.1:4318"
  }
}

The SDK appends /v1/metrics to the endpoint; export interval defaults to 60s. Retried exports deduplicate via deterministic event IDs.