The traditional observability stack — Prometheus metrics, OpenTelemetry traces, Grafana dashboards — was built for deterministic systems. The same input produces the same output, the same request ID correlates across services, and a regression is a thing you can see in a span. That whole model breaks when the system is an LLM. The same prompt returns a different completion on every call, the same trace ID can describe semantically distinct flows, and a model can shift from 95% accuracy to 88% accuracy over six weeks without a single error event firing anywhere in your pipeline.

This is not a tooling gap that better dashboards will close. It is a different kind of system, and it needs a different observability discipline. NewStack's editorial team framed the gap in mid-2026 as probabilistic observability — a sub-discipline with its own primitives. The framing caught on because the failure modes it describes are the ones SREs have been filing under "this isn't really an alert, but something feels wrong" for two years. The primitives are:

  • Output distributions, not point values — track the full distribution of model outputs, not just the latest sample.
  • Semantic-similarity trace correlation, not exact-match — correlate traces by what the prompts meant, not what they said byte-for-byte.
  • Statistical regression detection (Kolmogorov-Smirnov, PSI), not "is this value above a threshold."
  • Hallucination-as-a-metric — a measurable signal, not a vibes check on a Slack channel.

None of these are brand-new ideas. The drift-detection and hallucination-monitoring tooling has existed in various forms since 2024. The novelty is the framing: these are not optional add-ons to a traditional observability stack, they are the foundation that the traditional stack has to sit on top of for AI workloads. This article is the pillar article for that framing — what the four primitives are, how to implement them on top of a Prometheus + Grafana + OpenTelemetry stack, and the tooling landscape that gives them a UI.

Why Traditional Observability Fails for AI

The bedrock assumption of traditional observability is that the system under observation is deterministic. Given the same input at the same code version, the system produces the same output. That assumption shows up everywhere — in trace correlation (the same span ID means the same operation), in metric semantics (a counter increment means an event happened), in alerting (a threshold crossing means a behavior change), and in dashboard interpretation (a percentile shift means a population shift).

An LLM application violates this assumption at every layer. The same prompt at the same model version, sampled at temperature 0.7, returns a different token sequence on every call. A counter that increments on "model returned a response" is meaningless — every model call returns a response, including the ones that hallucinated. A 99th-percentile latency shift does not mean what it means in a REST API, because the long tail is dominated by token streaming variability, not network variability. And an alert on "request count dropped 30%" is useless when the upstream traffic is the same — the LLM is just generating shorter responses for some prompts.

The practical consequence is that dashboards built on the traditional primitives look healthy right up until the moment the model is producing low-quality output. Every metric is in range. Every SLO is green. The on-call engineer gets paged for something else entirely, and the LLM degrades silently in the background. This is the failure mode that probabilistic observability is built to detect.

The "Slight Degradation" Failure Mode

The clearest example is a model that shifts from 95% task-completion accuracy to 88% task-completion accuracy over six weeks. Nothing else changed. The model version is the same. The traffic pattern is the same. The token throughput is the same. The latency p99 is the same. The error rate is 0% (no requests failed, they just produced worse outputs).

A traditional observability stack cannot detect this. None of the metrics moved. The alerting system never fires. By the time a human notices — usually via user complaints or a periodic review — the system has been producing degraded output for weeks. For a customer-facing chat assistant, the lost revenue and trust is not recoverable from the dashboards you would have had.

Probabilistic observability detects this by tracking the distribution of model outputs, not the latest sample. When the distribution shifts, the system fires. The shift can be detected even when every individual call looks normal, because the population of calls has changed.

The Four New Primitives

The traditional observability stack is built on three primitives: metrics, logs, and traces. The probabilistic observability stack adds four more, each addressing a specific gap that the traditional primitives leave open for AI workloads.

Primitive 1: Output Distributions, Not Point Values

The first primitive is to instrument model outputs as distributions rather than point values. A traditional metric like llm.output_tokens is a point value — the latest sample, or an aggregation over a window. For a deterministic service, that aggregation is meaningful. For an LLM, it discards the information that matters most: the shape of the output distribution.

The practical implementation is to compute statistical summaries of the output distribution in your metrics layer: the mean, the standard deviation, the percentiles, the skew. These are not new metric types — Prometheus already supports them via the summary and histogram types. What is new is treating the distribution itself as the first-class signal, not the aggregated point value.

# Track the output distribution, not just the latest sample
summary(
  "llm_output_tokens",
  len(completion),
  labels={"model": model_name, "prompt_class": prompt_class}
)
# Now alert on a shift in the distribution, not a single value
# See Primitive 3 for the statistical tests

The metric names that matter most for output distribution tracking in production LLM systems are: output token count (length of the completion), refusal rate (does the model decline to answer), response time-to-first-token (TTFT, separate from total latency), and confidence score (log-prob of the chosen token, or the entropy of the output distribution over the top-k tokens). None of these is a point value in the way a traditional metric is — they all need to be tracked as distributions to be useful.

Advertisement
Advertisement

Primitive 2: Semantic-Similarity Trace Correlation

Traditional trace correlation relies on exact-match. The same span ID means the same operation. The same trace ID means the same request. For a REST API, this is a fine assumption: if two traces have the same path and the same status code, they describe the same operation. For an LLM application, it is not. The same prompt can produce semantically distinct completions depending on the model version, the system prompt, the temperature, and the random seed. Two traces with the same span IDs can describe fundamentally different operations from the user's perspective.

The fix is to correlate traces by semantic similarity, not exact match. Embed the prompts (or the prompt summaries) and the completions (or the completion summaries) into a vector space, and group traces by similarity rather than by token-level identity. This gives you a "semantic trace tree" that clusters the same user intent together even when the literal token sequence differs.

# Embed the prompt for semantic trace correlation
prompt_embedding = embed_model.encode(trace.input_prompt)
trace.set_attribute("semantic.prompt_embedding_version", "v1")
trace.set_attribute("semantic.prompt_embedding_dim", 768)
# Store the embedding hash for grouping, not the full vector
trace.set_attribute("semantic.prompt_cluster", cluster_id_for(prompt_embedding))
# Later: query traces by semantic cluster, not by exact prompt

The tool that has invested the most in this pattern is Arize Phoenix, where embedding-based clustering of traces is the default view. WhyLabs takes a similar approach with their whylogs profiles. Langfuse adds it through the LangChain integration. The open-source path is to embed the prompts and completions yourself, store the cluster IDs as span attributes, and build the semantic tree in your existing observability backend.

Primitive 3: Statistical Regression Detection

Traditional alerting is threshold-based: a metric crosses a number, an alert fires. For an LLM, this is too brittle. A threshold alert on token count fires when the model shifts from generating 200-token responses to 199-token responses, even though the population is unchanged. A threshold alert on latency fires when one prompt class slows by 10ms for reasons unrelated to the model. Threshold alerts generate noise without catching the regressions that actually matter.

Statistical regression detection replaces thresholds with tests. The two most common in production LLM observability are:

  • Kolmogorov-Smirnov (KS) test — compares the empirical distribution of a metric in the current window to the distribution in a baseline window. If the two distributions differ by more than a critical value, the test fires. The KS test is non-parametric (it makes no assumption about the shape of the distribution) and works well for any continuous metric: token count, latency, refusal rate, log-prob.
  • Population Stability Index (PSI) — buckets the metric into bins, compares the bin frequencies in the current window to the baseline, and returns a single number summarizing the shift. PSI is widely used in credit scoring and fraud detection; it has been adopted in MLOps because the single-number output is easier to alert on than the full KS statistic. A PSI value over 0.2 is the conventional "significant shift" threshold.

Both tests are available in the standard Python statistics ecosystem. The implementation in a Prometheus context is to compute the test statistic in the application or in a sidecar, expose it as a Prometheus gauge, and alert on the value of the gauge rather than the underlying metric.

# Alert on KS test statistic, not on the raw metric
# (the test statistic is exposed by your application)
llm_ks_statistic_token_count{model="gpt-4o", prompt_class="customer-support"} > 0.15
# This fires when the distribution of output tokens for customer-support prompts
# has shifted significantly from the baseline, regardless of what the new mean is

The pitfall here is the baseline window. If the baseline includes the period when the regression started, the test will not fire. The standard practice is a rolling 14-day baseline, with the alert firing when the trailing 24-hour window diverges from it. The other pitfall is correlated metrics: a temperature change shifts every metric at once, and a single-metric KS test can fire on a change that is actually a deliberate config update. Pair the test with a deploy-tracking label so you can suppress alerts for the first 24 hours after a known config change.

Primitive 4: Hallucination-as-a-Metric

The fourth primitive is the most contested. Hallucination is hard to measure. There is no ground truth for "did the model hallucinate" available at inference time, and the existing detectors — LLM-as-a-judge, embedding distance from a reference, NER-based factual consistency — all have failure modes. The framing of "hallucination-as-a-metric" is not that the metric is perfect. It is that the metric is measurable, automated, and tracked over time. That is a categorical improvement over the default state, which is "no measurement at all."

The practical implementation is to run a hallucination detector on a sample of production traffic and expose the detector's score as a Prometheus metric. The detector can be:

  • LLM-as-a-judge — a separate model call that scores the response for factual consistency against the prompt. Expensive (adds a model call), but well-correlated with human judgment on most tasks.
  • Embedding-based grounding — measures the distance between the response embedding and the retrieved context (for RAG) or the prompt (for general prompts). Cheap, but catches only the gross hallucinations.
  • NER-based factual consistency — extracts named entities from the response and checks them against the retrieved context. Catches specific entity-level hallucinations (wrong dates, wrong names) that embedding distance misses.

The choice depends on the cost-accuracy trade-off the team is willing to accept. LLM-as-a-judge is the most accurate but doubles or triples the cost of the original inference. Embedding-based grounding is cheap but generates false positives. NER-based is in between. Most production teams use a combination: embedding-based grounding on 100% of traffic for real-time alerting, LLM-as-a-judge on 1-5% sampled traffic for trend analysis.

# Hallucination-as-a-metric: sample, score, expose
sampled_traces = sample_production_traces(sample_rate=0.02)
for trace in sampled_traces:
    score = llm_judge.hallucination_score(
        prompt=trace.input_prompt,
        response=trace.output_completion,
        context=trace.retrieved_context
    )
    summary(
      "llm_hallucination_score",
      score,
      labels={"model": trace.model, "prompt_class": trace.prompt_class}
    )
# Now alert on the distribution of hallucination scores, not on any single one

The metric should be tracked as a distribution, not a point value, for the same reason as Primitive 1. A single hallucination score on a single trace is noise. A shift in the distribution of hallucination scores across thousands of traces is signal. Pair the score with the statistical test from Primitive 3 and you have a regression detector that fires on quality changes, not on noise.

Advertisement
Advertisement

Implementing the Primitives on Prometheus + Grafana + OpenTelemetry

The existing Prometheus + Grafana + OpenTelemetry stack is the right substrate for probabilistic observability. The primitives described above are not new metric types — they are new label conventions, new aggregations, and new alerting patterns. The implementation is mostly in the application layer, with the storage and visualization staying on the existing stack.

Label Conventions for Probabilistic Signals

The label schema is the foundation. Every LLM span should carry a consistent set of attributes that the probabilistic layer can group by. The minimum set, based on the OpenTelemetry AI semantic conventions plus the additions this article recommends:

# Required OTel attributes for probabilistic observability
gen_ai.system: "openai"           # or "anthropic", "bedrock", "vllm"
gen_ai.request.model: "gpt-4o"
gen_ai.request.max_tokens: 4096
gen_ai.request.temperature: 0.7
gen_ai.usage.input_tokens: 2340
gen_ai.usage.output_tokens: 892
gen_ai.response.finish_reason: "stop"
# Probabilistic observability extensions
probabilistic.prompt_class: "customer-support"
probabilistic.prompt_cluster: "p_7a3f"
probabilistic.semantic_version: "prompt_v42"
probabilistic.deploy_id: "deploy_2026_06_06_001"

The prompt_class label is the most important. It groups spans by their semantic intent, not their literal text. A customer-support trace, a sales-research trace, and a code-review trace all hit the same model with different prompts, and the regression-detection layer needs to group by intent to detect shifts in any one class. If you do not have an existing intent taxonomy, the easiest place to start is a small set of human-defined classes (3-7) that match your application's high-level use cases.

The deploy_id label is the regression-test suppression key. Pair it with a deploy-tracking system so the alerting layer knows which window includes a known config change.

Metric Aggregation Patterns

The aggregations in the metrics layer should match the primitives. The four patterns this article recommends:

  1. Distribution summary per prompt_class per model: llm_output_tokens{model, prompt_class} as a histogram, with KS-test gauges computed in the application.
  2. Latency summary per prompt_class: llm_ttft_seconds{model, prompt_class} and llm_total_latency_seconds{model, prompt_class} as histograms. The TTFT histogram is the one that matters most for user experience.
  3. Quality score summary per prompt_class: llm_hallucination_score{model, prompt_class} as a summary. The score itself is a number 0-1; the summary tracks the distribution.
  4. Refusal and error rate: llm_refusal_total{model, prompt_class} and llm_error_total{model, error_type} as counters. Refusals are an LLM-specific failure mode that traditional error metrics miss.

All four patterns are implemented in standard Prometheus exporters. The application code emits the histograms and summaries; Prometheus aggregates and stores them; Grafana visualizes. The non-standard piece is the KS-test gauge, which is computed in the application (or in a sidecar that has access to the raw values) and exposed as a Prometheus gauge.

Grafana Dashboards for Probabilistic Observability

The Grafana dashboard for probabilistic observability is structurally different from a traditional Grafana dashboard. The top-level panels are not metric values — they are the four primitive-level signals, each with its own panel:

  1. Output distribution panel: a heatmap of llm_output_tokens over time, with the baseline mean and standard deviation overlaid. A shift in the heatmap is the first signal of a regression.
  2. Semantic cluster panel: a stacked area chart of trace counts per prompt_class, with a panel-level alert if any one class grows or shrinks by more than 30% in a 1-hour window. A class that disappears entirely is usually a routing or prompt-template regression.
  3. KS test statistic panel: a line chart of the KS statistic for each (model, prompt_class) combination, with an alert threshold at 0.15. The KS panel is the early-warning system for distribution shifts that no other panel will catch.
  4. Hallucination score panel: a histogram of hallucination scores per (model, prompt_class), updated in 15-minute windows, with a KS-test overlay. A shift in the hallucination score distribution is the most actionable signal the system produces.

Below these four panels, the traditional panels (latency p50/p95/p99, error rate, throughput) sit as supporting context. They are useful for debugging once a regression is detected, but they are not the panels that detect the regression in the first place. The new SRE on the team needs to learn to look at the four primitive panels first.

The Tooling Landscape

No single tool in 2026 ships the full probabilistic observability stack out of the box. The pieces are spread across four tools, each of which does a different subset of the primitives well. The right choice depends on which primitives the team needs first.

Arize Phoenix: The Embedding-First Tool

Arize Phoenix is the strongest tool for Primitive 1 (output distributions) and Primitive 2 (semantic trace correlation), because the platform was built around the embedding-based drift detection layer that those primitives depend on. The drift dashboard surfaces embedding-distance shifts between query distributions and the indexed corpus, the trace view clusters semantically similar prompts, and the REST API exports token counts and quality scores for integration with Prometheus.

The limitation is guardrails and cost attribution. Phoenix has zero guardrail features (no PII detection, no prompt-injection prevention) and does not ship user-level cost attribution. If the team needs those, Phoenix pairs with a separate layer (Guardrails AI for guardrails, Helicone or LiteLLM for cost).

WhyLabs: The Statistical-First Tool

WhyLabs is the strongest tool for Primitive 3 (statistical regression detection). The whylogs profiler library generates statistical profiles of any DataFrame — including the per-trace telemetry coming out of an LLM pipeline — and the WhyLabs platform tracks the profile over time with KS-test, PSI, and chi-squared built in. The implementation is mostly Python: profile the trace data, upload the profile, alert on the platform's regression detection.

The limitation is depth on the LLM-specific primitives. WhyLabs is a general-purpose data monitoring platform that happens to work well for LLM traces. It does not have an LLM-aware trace view the way Phoenix does, and it does not ship a hallucination detector. The team typically uses WhyLabs for the statistical layer and pairs it with a separate hallucination-detection component.

Langfuse: The Trace-First Tool

Langfuse is the strongest tool for end-to-end trace correlation, particularly for LangChain and LlamaIndex pipelines. The trace view breaks down every step in a multi-step agent loop, the regression detection is built around trace-level comparisons (this trace vs. last week's traces for the same prompt class), and the integration with the LangChain ecosystem is the deepest in the open-source world.

The limitation is that the regression detection is trace-comparison-based, not statistically rigorous in the way WhyLabs' KS test is. For teams that need formal statistical regression detection on the metrics layer, Langfuse pairs with a separate statistical layer. For teams that primarily need trace-level debugging, Langfuse is the right starting point.

Helicone: The Cost-and-Quality-First Tool

Helicone is the strongest tool for per-trace cost-and-quality tracking. The platform's differentiator is the per-trace cost dashboard (broken down by user, by model, by prompt class) combined with the quality scoring layer. For teams whose primary need is "where is my LLM budget going, and is the quality holding," Helicone is the right starting point.

The limitation is depth on the embedding-drift and statistical-regression primitives. Helicone ships a quality-scoring layer, but the embedding-drift detection is shallow compared to Phoenix, and the statistical-regression detection is not as rigorous as WhyLabs. The team uses Helicone for cost and quality, Phoenix or WhyLabs for the deeper primitives.

The Composite Stack

Most production teams running AI workloads in 2026 end up with a composite of two or three of these tools, plus the existing Prometheus + Grafana + OpenTelemetry stack as the substrate. A common pattern is Phoenix for the embedding-drift and semantic-trace layer, WhyLabs or a custom KS-test gauge for the statistical-regression layer, and the existing Prometheus alerting for the SLO layer. The tools are not mutually exclusive; they layer.

Advertisement
Advertisement

The Operational Patterns

The primitives are the foundation, but the operational patterns are what make them work in practice. Four patterns this article has seen work in production deployments of probabilistic observability:

Pattern 1: The KS-Test-as-Alert Loop

The primary regression-detection signal is the KS-test gauge. The application computes the KS statistic for each (model, prompt_class, metric) tuple on a rolling basis, exposes it as a Prometheus gauge, and Grafana alerts when the gauge crosses 0.15. The alert is routed to the SRE on-call, and the runbook is "look at the four primitive panels, identify the shifted distribution, and check whether the shift corresponds to a known deploy." The alert fires on distribution shifts, not on threshold crossings, which dramatically reduces false positives compared to a traditional threshold alert. SLO design and budget-burn policy for these gauges is the same problem space covered in our AI SLO and SLA contracts article — the KS-test gauge is the signal, the SLO is the policy that decides when to page.

Pattern 2: The Daily Distribution Report

A daily report that compares the trailing 24-hour distribution of every output metric against the trailing 14-day baseline. The report is generated by a cron job that queries Prometheus, computes the KS statistic and PSI for each metric, and emails a summary to the engineering team. The report is the layer behind the alerts — alerts catch the fast shifts, the daily report catches the slow drifts that no single 24-hour window will trigger on. The drift detection covered in our LLM model drift detection article is the deeper dive on this pattern.

Pattern 3: The Hallucination Sampling Loop

Sample 1-5% of production traffic, run the hallucination detector, expose the score as a Prometheus summary, and alert on the distribution. The sampling rate is a cost decision: LLM-as-a-judge doubles the inference cost on the sampled traffic, embedding-based grounding is cheap. Most teams start at 1% with embedding-based grounding and ramp to 5% LLM-as-a-judge once the budget is justified. The hallucination-as-a-metric primitive covered earlier is the foundation for this pattern.

Pattern 4: The Semantic-Cluster Routing

Group traces by semantic cluster, route alerts by cluster, and use the cluster view as the primary debugging surface. The implementation is to embed every prompt, assign a cluster ID, store the cluster ID as a span attribute, and build the dashboard view around clusters rather than individual traces. The cluster view is the layer that turns "I have 50,000 traces" into "I have 12 semantic clusters, and 3 of them are regressing." Phoenix's trace view is the canonical implementation of this pattern.

When Probabilistic Observability Is the Wrong Frame

The framing is not universal. Three situations where the traditional observability stack is the right tool and the probabilistic primitives are over-engineering:

  • Deterministic AI pipelines: A classification model with a fixed output schema (yes/no, sentiment label) is closer to a traditional software service than to a generative LLM. The output distribution is a small set of discrete values, the embedding-based primitives do not apply, and the traditional SLO-and-alert pattern works fine.
  • Pre-production evaluation: The probabilistic primitives are designed for production traffic. For pre-production model evaluation, the right tooling is Braintrust, RAGAS, or a custom evaluation pipeline — the goal is to score a model offline, not to monitor it in real time.
  • Cost-only monitoring: If the primary need is "where is my LLM budget going," Helicone or LiteLLM is the right starting point. The probabilistic primitives add cost without adding value if the team is not yet at the regression-detection stage.

For everything else in the AI observability space — generative AI in production, agentic systems, RAG pipelines, multi-step LLM workflows — the probabilistic primitives are the layer the traditional stack has to sit on top of. The framing is not a replacement for the traditional stack. It is the layer that makes the traditional stack work for AI. Related reading: LLMOps Observability Blueprint, LLM Hallucinations: Five Production Detection Methods, AI Incident Postmortem Template, AI SLO and SLA Contracts, and LLM Security Hardening.

What to Ship First

If this article is the moment the team is starting to think about probabilistic observability, the order of operations that minimizes time-to-value is:

  1. Add the label conventions to your existing OpenTelemetry instrumentation. The prompt_class and deploy_id labels are the foundation for every other primitive. The implementation is a span attribute set in the application code; it does not require a new metric type or a new tool.
  2. Track the four output metrics as histograms, not counters: output tokens, TTFT, total latency, hallucination score. The change is one line in the Prometheus client library; the value is the ability to compute the distribution in the dashboard layer.
  3. Implement one KS-test gauge for the highest-traffic prompt class. The gauge is computed in a sidecar that has access to the raw metric values. The alert is on the gauge, not on the underlying metric. This is the primitive that catches the "slight degradation" failure mode.
  4. Stand up a semantic-cluster view. Embed the prompts, store the cluster IDs, build the view. Phoenix is the fastest path; a custom implementation in your existing observability backend is the cheaper path.
  5. Add the hallucination detector on a 1% sample. Embedding-based grounding is the right starting point. The metric should be tracked as a summary from day one, not as a point value.

That sequence ships the foundation in a week for a small team, and it catches the failure mode that the traditional observability stack is structurally unable to catch. From there, the team can ramp to the full four-primitive stack over the next quarter as the value becomes clear.

Tool Spotlight Arize AI

Open source LLM observability with embedding-based drift detection

Tool Spotlight WhyLabs

Statistical monitoring with KS-test and PSI built in

Tool Spotlight Grafana Cloud

Hosted Prometheus, Tempo, and Loki — the substrate for probabilistic observability