Skip to main content

Anatomy of AI Observability

Traces, metrics, evals, drift detection, and regression alarms.

Observability

Traces, metrics, evaluations, drift detection, and regression alarms β€” turning your AI system from a black box into something you can trust, scale, and continuously improve.


TL;DR​

  • AI observability has 5 pillars: Logs Β· Traces Β· Metrics Β· Evaluations Β· Alerts.
  • Trace every user request end-to-end with a single trace_id so you can debug across model calls, tools, and subagents.
  • Track performance, usage, cost, quality, and adoption metrics β€” at least one from each category.
  • Run evaluations continuously β€” a living eval suite is your regression net.
  • Drift is silent: detect it with rolling averages, canaries, and shadow traffic before users do.
  • Alert on impact, not noise. Tie every alert to an action.

Why this matters​

You can't improve what you can't see. AI systems fail in subtle, drifty, expensive ways β€” a quiet 5% accuracy drop, a 10Γ— cost spike from a chatty prompt, a hallucination in production. Observability is what turns those silent failures into actionable signals.

Bottom line: Observability isn't about data. It's about understanding β€” and understanding is what lets you ship AI with confidence.


The Big Picture β€” Full-Stack AI Observability​

Bottom line: Logs, Traces, Metrics, Evaluations, Events all flow through one trace_id and end up stored, correlated, visualized, and alerted on.


The 5 Observability Pillars​

PillarPurposeExamples
πŸ“„ LogsRaw events & structured logsEverything important that happened
πŸ”— TracesEnd-to-end request flowServices, models, tools, timing, dependencies
πŸ“Š MetricsAggregated numbers over timeLatency, tokens, cost, errors, quality
⭐ EvaluationsQuality measured continuouslyCorrectness, factuality, safety, coherence
🚨 AlertsNotify on issues & regressionsThresholds, anomalies, drift, SLA breaches

Properties every pillar must have:

  • βœ… Everything important is captured
  • βœ… Immutable
  • βœ… Searchable
  • βœ… Auditable

πŸ’‘ Tip: Start with traces + cost/latency metrics + a small eval suite. Add the rest as you mature.


End-to-End Trace Example​

One user request through an agentic workflow:

SpanService / stepLatencyTokens (in / out)
🟒 Total RequestUser: "How do I add SSO?"8.21s5,420 / 1,842
β–Έ Orchestrator (planner)Plan steps, choose tools420 ms812 / 98
β–Έ Model call (claude-sonnet-4)Reasoning & planning1.82 s1,120 / 256
β–Έ Tool: codebase searchSearch docs & code680 ms0 / 312
β–Έ Model call (claude-sonnet-4)Synthesis2.11 s1,340 / 612
β–Έ Tool: read file (auth/README.md)Read integration guide230 ms0 / 128
β–Έ Tool: git diff (main…HEAD)Inspect recent changes310 ms0 / 156
β–Έ Model call (claude-sonnet-4)Final answer2.47 s1,980 / 456
β–Έ Response deliveredTo user200 msβ€”

πŸ’‘ Tip: Use trace IDs to jump from metrics β†’ traces β†’ logs for root cause.


Instrumentation β€” Log Schema​

A consistent schema is half the battle. Use this as your baseline:

{
"ts": "2025-05-20T10:30:00.123Z",
"trace_id": "c7f3wabu2",
"span_id": "a1b2-d-sonnet-4",
"parent_id": null,
"user_id": "u_123",
"session_id": "abc123",
"model": "claude-sonnet-4",
"input_tokens": 21000,
"output_tokens": 832,
"cost_usd": 0.0187,
"cache_hit": false,
"status": "success",
"task": "code_review",
"latency_ms": 8214,
"tool_calls": [
{ "tool": "git.diff", "ms": 310, "ok": true },
{ "tool": "fs.read", "ms": 230, "ok": true }
],
"tags": { "tier": "prod", "files_changed": 8 }
}

Required fields (the "irreducible minimum"):

  • ts, trace_id, span_id, parent_id
  • model, input_tokens, output_tokens, cost_usd
  • latency_ms, status
  • task, user_id, session_id

πŸ’‘ Tip: Standardize this schema across all services. It's the single highest-leverage thing you can do for AI observability.


Key Metrics β€” What to Measure​

Start with one metric from each category. Add more as the system matures.

CategoryMetricWhy it mattersExample target
⚑ PerformanceLatency (P50 / P95)User experienceP95 < 5 s
⚑ PerformanceTime to First TokenPerceived speedP95 < 2 s
⚑ PerformanceThroughput (RPS)Capacity planningAs needed
⚑ PerformanceError rateReliability< 1%
πŸ“Š UsageInput tokensCost driverTrack trend
πŸ“Š UsageOutput tokensCost driverTrack trend
πŸ“Š UsageContext window %Risk of truncation< 80%
πŸ“Š UsageCache hit rateCost optimization> 60%
πŸ’° CostCost per requestUnit economics< $0.02
πŸ’° CostCost per user / dayBudget controlSet budget
πŸ’° CostTotal daily / monthlyTotal spendWithin budget
βœ… QualityCorrectness (eval score)Are we right?> 0.85
βœ… QualityHallucination rateFactuality< 1%
βœ… QualitySafety / policy violationsGuardrails0 tolerance
βœ… QualityUser satisfaction (CSAT)Happy users> 4.5/5
πŸ“ˆ AdoptionAcceptance rateAI output used> 50%
πŸ“ˆ AdoptionRe-ask / rework rateFriction< 15%

πŸ’‘ Tip: Start with a small set. Add more as you mature. Tracking everything tracks nothing.


Evaluations & Testing​

Build a living eval suite and run it continuously β€” every change to prompts, models, or tools.

Eval types​

TypeQuestion it answers
βœ… CorrectnessIs it factually right?
πŸ”Ž FactualityAre claims grounded in source?
πŸ›‘οΈ SafetyClear & consistent boundaries?
πŸ’¬ HelpfulnessDoes it solve the task?
🧷 GroundednessDoes it use provided context?

Example eval case (YAML)​

id: sso_setup_basic
description: Explain how to add SSO
tags: [docs, auth]

input:
- "How do I configure SSO with Okta?"

expected:
must_contain:
- "Okta"
- "redirect_uri"
- "clientId"
- "claims"
must_not_contain:
- "hardcoded secrets"
- "outdated endpoints"

rubric:
- name: correctness weight: 0.4
- name: groundedness weight: 0.3
- name: safety weight: 0.2
- name: adverse weight: 0.1
  • On every PR that touches prompts, agents, or skills (CI gate).
  • Nightly against a representative sample of production traffic.
  • Weekly full sweep across your "canary set".
  • Before any model bump (Sonnet β†’ Opus, version rollover, etc.).

πŸ’‘ Tip: Run evals on every change to prompts, models, or tools. It's your AI regression test suite.


Drift Detection β€” Catching Silent Failures​

Drift = quality degrading slowly over time. By the time users complain, you've lost trust.

Drift signals to watch​

  • πŸ“‰ Eval score drop
  • πŸ€– Increase in hallucinations
  • πŸ” Spike in user re-asks
  • ⏱️ Change in latency
  • πŸ”„ Change in token usage
  • ❗ Higher error rates
  • πŸ›‘οΈ New safety violations

Detection methods​

MethodWhat it doesWhen to use
Statistical β€” rolling average & control chartsTrend over timeAlways
Anomaly detection (z-score, EWMA)Outlier spikesProduction at scale
Canary evals with fixed test set"Did anything change?"Every deploy
Shadow traffic comparisonOld vs new in parallelMajor prompt/model changes
Distribution shift (KL divergence)Input or output distribution changedMature monitoring

Visualizing drift​

A simple rolling chart of your eval score with a threshold line is enough to start:

Eval Score over time
1.0 ─●●●●●●●●
0.9 ─ ●●●●●
0.8 ─- - - - - - - - threshold - - - - -
0.7 ─ ●●●●●
0.6 ─ ●●●● ← drift!
└─────────────────────────────
Apr 20 May 4 May 18

🚨 Alert example: "Eval score fell below 0.85 for 3 consecutive days."


Alerting & Auto-Response​

Notify the right people, take action automatically where safe.

Alert examples​

SeverityTrigger
πŸ”΄ CriticalEval score < 0.80
πŸ”΄ CriticalSafety violation detected
🟑 WarningError rate > 2%
🟑 WarningLatency P95 > 10 s
πŸ”΅ InfoNew model deployed
πŸ”΅ InfoDaily cost > $100

Auto-response playbook​

  1. Page on-call (critical only).
  2. Rollback to last known good prompt / model.
  3. Switch to fallback model.
  4. Reduce context / enable cache.
  5. Throttle traffic if needed.
  6. Open incident + notify team.

πŸ’‘ Tip: Alert on impact, not noise. Every alert needs a runbook.


Dashboards to Build​

A small set of dashboards is enough for 80% of value:

  • πŸ“Š Requests / Day β€” traffic shape
  • ⏱️ P95 Latency β€” user experience
  • πŸ’° Total Cost (USD) β€” money
  • ⭐ Eval Score (avg) β€” quality
  • ❌ Error Rate (%) β€” reliability
  • πŸ’Ύ Cache Hit Rate (%) β€” efficiency
  • πŸ₯§ Top Routes by Cost β€” where the money goes
  • πŸ”’ Tokens In / Out β€” usage trend

πŸ’‘ Tip: One glance should tell you if the system is healthy.


Step-by-Step Setup​

1. Pick a backend​

  • OpenTelemetry β†’ Grafana / Tempo / Loki (open, portable).
  • Datadog / Honeycomb / New Relic (managed).
  • LangSmith / Langfuse / Helicone / Phoenix (AI-native).

2. Standardize the log schema​

Put the JSON schema above in a shared library (@org/ai-logger) and use it everywhere.

3. Add a tracing wrapper​

Instrument every model call, tool call, and subagent invocation with the same trace_id.

// pseudo-TS
const traceId = uuid();
await withSpan(traceId, "model.call", { model, input_tokens }, async () => {
const res = await client.complete(prompt);
log({ ts, trace_id: traceId, model, input_tokens, output_tokens: res.tokens, cost_usd: priceOf(res) });
return res;
});

4. Emit metrics​

Use Prometheus / StatsD / OTel meters for the metrics table above.

5. Build the eval suite​

Start with 20 hand-picked test cases. Grow as you find real failures.

6. Wire CI evals​

Run the eval suite on every PR that touches prompts, agents, or models. Fail the build below threshold.

7. Configure drift & alerts​

Rolling average over 7 days; alert when N consecutive days breach threshold.

8. Document runbooks​

Every alert links to a runbook with: symptom β†’ likely cause β†’ first action.


Variants for Different Team Settings​

πŸ‘€ Solo developer​

  • One JSONL log file, daily rotation.
  • 5-case eval set, run before every prompt change.
  • Email alert on cost > daily budget.

πŸ‘₯ Small team (2–10)​

  • OTel + Grafana (or Honeycomb free tier).
  • 20–50 case eval suite in CI.
  • Slack alerts: cost + safety only.
  • Weekly review of the eval-score chart.

🏒 Enterprise / regulated​

  • Full audit trail + immutable storage (S3 + Object Lock).
  • PII redaction in logs at write time.
  • SIEM integration for safety + auth events.
  • Eval suite versioned, peer-reviewed, signed.
  • On-call rotation for AI quality, not just uptime.

🌍 Open-source / community​

  • Public dashboards (with PII stripped).
  • Anonymized eval results published.
  • Community-contributed eval cases.

Bottom line: Same pillars, escalating discipline.


Common Patterns & Recipes​

Pattern 1 β€” Universal trace ID​

const traceId = req.headers["x-trace-id"] ?? uuid();
// Pass to every model call, tool call, and subagent.

Pattern 2 β€” Sampled deep logging​

1% of requests β†’ full prompt + response logged
Everyone β†’ metrics + trace skeleton only

Pattern 3 β€” Canary evals on deploy​

# .github/workflows/eval.yml
on: [push]
jobs:
eval:
steps:
- run: npm run eval:canary
- if: failure()
run: ./scripts/rollback.sh

Pattern 4 β€” Shadow comparison​

On 1% of prod traffic:
- Call current model AND candidate model
- Compare eval scores
- Block promotion if delta > threshold

Pattern 5 β€” Cost anomaly detection​

-- alert if today's cost > 2Γ— 7-day average
SELECT day, sum(cost_usd) AS spend
FROM ai_events
GROUP BY day
HAVING spend > 2 * avg_7d

Pattern 6 β€” Hallucination spike detector​

window: 1 hour
threshold: hallucination_rate > 1.5Γ—7d_avg
action: page + auto-switch to deterministic fallback

Pattern 7 β€” Eval-driven prompt PRs​

PR template:
- [ ] Eval suite ran
- [ ] Score change: Β±__%
- [ ] No regression on safety set
- [ ] Cost change: Β±__%

Best Practices βœ…β€‹

  • πŸ“ Measure everything with context (trace IDs, tags).
  • πŸ†” Use consistent trace IDs across the stack.
  • 🏷️ Version prompts & models (always know what produced what).
  • πŸ§ͺ Maintain a living eval suite.
  • πŸ›°οΈ Detect drift early.
  • 🎯 Alert on impact, not noise.
  • πŸ“ˆ Keep dashboards simple & actionable.
  • πŸ“’ Document runbooks for every alert.

Anti-Patterns βŒβ€‹

  • 🚫 No instrumentation ("we'll add it later").
  • 🚫 Only alerting on errors β€” miss quality drift entirely.
  • 🚫 Eval suite is stale or tiny.
  • 🚫 Ignoring small degradations.
  • 🚫 No rollback strategy.
  • 🚫 Dashboards nobody looks at.
  • 🚫 Ad-hoc experiments in prod without logging.
  • 🚫 Blindly trusting outputs.

Troubleshooting​

SymptomLikely causeFix
"It got worse last week"No drift detectionAdd rolling-avg alert
Cost spike, no idea whyNo per-task cost logAdd task tag + log cost_usd
Can't reproduce a bad answerNo prompt/version loggedLog prompt hash + model version
Eval suite always greenSuite too narrowAdd adversarial + edge cases
Alerts ignoredToo many, no runbooksCut 80%; write runbooks for the rest
Trace gapstrace_id not propagatedEnforce via wrapper / middleware
PII in logsNo redaction at writeAdd PII scrubber before persist

Quick-Start Checklist​

  • βœ… Standard log schema deployed
  • βœ… Trace IDs propagated end-to-end
  • βœ… 4 metrics live (latency, cost, error, quality)
  • βœ… Eval suite (β‰₯ 20 cases) running in CI
  • βœ… Drift alert on eval score
  • βœ… Cost alert at 80% of daily budget
  • βœ… One unified dashboard
  • βœ… Runbook for every alert

🧠 Mantra: Prevent · Detect · Fix · Learn.


Starter Configs​

Minimal log emitter (TypeScript)​

import { performance } from "node:perf_hooks";

export function logAIEvent(e: AIEvent) {
console.log(JSON.stringify({
ts: new Date().toISOString(),
trace_id: e.traceId,
span_id: e.spanId,
parent_id: e.parentId ?? null,
model: e.model,
input_tokens: e.inputTokens,
output_tokens: e.outputTokens,
cost_usd: e.costUsd,
latency_ms: e.latencyMs,
status: e.status,
task: e.task,
user_id: e.userId,
session_id: e.sessionId,
cache_hit: e.cacheHit ?? false,
tags: e.tags ?? {}
}));
}

Eval runner (skeleton)​

for (const c of cases) {
const out = await runAgent(c.input);
const score = grade(out, c.rubric);
results.push({ id: c.id, score });
}
report({
avg: avg(results.map(r => r.score)),
failing: results.filter(r => r.score < 0.8)
});

Alert rule (Prometheus / Grafana)​

- alert: AIEvalScoreLow
expr: avg_over_time(ai_eval_score[3d]) < 0.85
for: 1d
labels: { severity: critical }
annotations:
summary: "AI eval score dropped"
runbook: "https://runbooks/ai-eval-score"

Glossary​

  • Span β€” One unit of work in a trace (a model call, a tool call).
  • Trace β€” All spans for one user request, linked by trace_id.
  • Eval (evaluation) β€” Scored test of model output against a rubric.
  • Drift β€” Slow change in model behavior or input distribution.
  • Canary β€” Small, controlled test against a fixed set.
  • Shadow traffic β€” Calling a new model in parallel for comparison without affecting users.
  • Rubric β€” Weighted set of criteria used to score outputs.
  • Runbook β€” Documented response for an alert.
  • CSAT β€” Customer Satisfaction score.
  • TTFT β€” Time to First Token.

Further Reading​

  • Search: "OpenTelemetry semantic conventions for GenAI"
  • Search: "LLM evaluation harness HumanEval MMLU"
  • Search: "drift detection statistical methods EWMA"
  • Search: "AI observability platforms 2026 comparison"

πŸͺ™ Goal & Pillars​

  • 🎯 The goal: Ship high-quality AI-powered features with predictable cost and zero surprises.
  • πŸ›‘οΈ Prevent β€” Catch issues early with smart gates.
  • πŸ” Detect β€” See what's going on in real time.
  • πŸ”§ Fix β€” Resolve fast with context and automation.
  • 🧠 Learn β€” Continuously improve models, prompts, and workflows.

"Observability is not about data. It's about understanding." β€” Charity Majors