← Back to blog
Product 4 min read 炬鲸团队

From a Wall of Errors to a Single Conclusion: AI-Assisted Incident Triage

Error clustering, smart summarization and natural-language queries shrink a half-hour log investigation into minutes. How Observe's AI-assisted triage works, and how to adopt it without over-trusting the model.

Why "reading logs" gets messier the longer you look

When production breaks, the instinct is to open log search and query for ERROR. Thousands of lines come back. You read them one at a time, form one guess after another, and thirty minutes later your conclusion is still "it looks like order-service timed out." The bottleneck is rarely search speed — it's that there is more information than a human can process, especially at 3 a.m. when the on-call engineer is running on adrenaline and coffee.

Consider a typical outage: an upstream payment provider starts returning 502s, and the blast radius touches order, payment and notification services all at once. Each service emits its own stack traces, and a single engineer now faces tens of thousands of interleaved lines. Even a fast search engine can't help if you don't know what to search for. This is the "needle in a haystack that keeps growing" problem.

AI-assisted triage targets exactly this step. Instead of asking a person to read thousands of lines, it asks a model to cluster and summarize first, compressing the noise into a dozen conclusions, then asks the person to judge. The design decision is worth spelling out: the model never "fixes" anything. It shortens the distance between an alert and a hypothesis. The engineer still verifies against raw evidence; what changes is how much raw evidence has to be touched before the first good hypothesis appears.

How clustering actually works

Clustering groups errors by a normalized fingerprint, not by naive string equality. Volatile tokens — timestamps, request IDs, port numbers — are masked before hashing, so two stack traces that differ only in those fields collapse into the same cluster. The result is that "the same bug firing 400 times" shows up as one cluster with a count of 400, not 400 separate rows.

Cluster quality depends on two things: masking the right volatile fields, and picking a sensible time window. Too wide a window merges unrelated incidents; too narrow a window fragments one incident into many. Observe defaults to a rolling window and lets you adjust it.

Three steps: cluster, summarize, locate

  1. Error clustering. Errors inside the selected time window are grouped automatically by stack signature, error type and service name. Thousands of lines collapse into a dozen clusters, each carrying a count and a share of the total.
  2. Smart summarization. Each cluster gets a one-line conclusion. A good one reads: "order-service's payment callback endpoint has returned 502 since 14:20, accounting for 87% of the window, likely caused by an exhausted connection pool on upstream payment-gateway."
  3. Locate. Clicking a cluster drills into the matching logs, traces and metrics, stitching together the evidence chain from alert to root cause.
[cluster-3] 87% (412 events) order-service /pay/callback -> 502
  root cause hint: payment-gateway connection pool exhausted (max=50, waiters=312)
  related trace: 8f3a9c2e | first seen 14:20:03

The clustering step is where most of the time is saved. Instead of discovering "there are actually only three distinct failure modes here" after reading two hundred lines, you know it in the first five seconds.

Natural language to query (NL2Query)

Field names and SQL functions are easy to forget at 3 a.m. With NL2Query you type plain language — "show me the errors from pay-service in the last hour, sorted by count" — and the platform converts it to SQL-like syntax, executes it, and displays the generated SQL verbatim.

SELECT level, count(*) AS cnt
FROM logs
WHERE service = 'pay-service' AND ts > now() - 1h
GROUP BY level ORDER BY cnt DESC

Showing the SQL matters for two reasons. First, you can verify the query did what you meant — service = 'pay' versus service = 'pay-service' changes the result entirely. Second, it doubles as documentation for newcomers learning the schema: every natural-language query you run is a worked example of the correct syntax.

Practical advice and limits

  • Cluster first, drill down second. Resist the urge to open raw logs immediately; look at the clusters, then choose which one to expand.
  • Treat the summary as a lead, not a verdict. For critical branches, go back to the raw stack trace before declaring victory.
  • Feed the model. Confirm or correct clustering and summaries. The feedback loop is cheap — a tap per cluster — and it is what makes results improve over time.
  • Wire it into alerts. The highest-value placement is right in the alert payload: an alert that arrives with a pre-computed cluster and summary turns a "something's wrong" page into "this is probably what's wrong."

AI-assisted triage shines on high-volume, repetitive failures — the 502 storm, the N+1 query, the missing-config error that fires on every request. It is less useful for rare, one-off events where there is no cluster to form, or for problems that are deterministic but silent (a wrong business rule that logs nothing). Treat it as a triage accelerator, not a replacement for understanding your system. The engineers who get the most out of it are the ones who already know their architecture and use the summary to jump to the right place faster.