Home
cd ../playbooks
Developer ToolsAdvanced

Datadog Error Triage to PR

Take Datadog Error Tracking issues from raw occurrence counts to a reviewable, tested PR — a five-class bug taxonomy that filters out infra noise and deploy-skew before ranking, a recency premium that catches fresh regressions early, a mandatory approval gate before any fix is written, and a test-first fix workflow that generalizes past the one reported occurrence.

10 minutes
By LatitudeSource
#datadog#observability#error-tracking#debugging#incident-response#developer-tools

The highest-occurrence error in your Datadog dashboard is usually not a code bug — it's a timeout, a rate limit, or an expected retry, and triaging by raw count alone means you'll spend an investigation on infrastructure noise while a smaller, rising, genuinely fixable regression sits unranked below it.

Who it's for: engineering teams using Datadog Error Tracking who want a repeatable triage-to-fix workflow, on-call or platform engineers tired of manually classifying which high-count errors are actually fixable code bugs, teams wanting an approval gate between investigation and code changes for production error fixes, anyone who wants a Datadog issue's fix traced back to its introducing commit automatically

Example

"Find and fix our most impactful production errors this week" → Error Tracking issues pulled and classified into a five-bucket taxonomy (genuine bug, infra/transient, deploy skew, expected noise, upstream) so only real candidates get investigated, ranked by impact × trend × fix-confidence with extra weight for new-and-rising regressions, a plan presented for approval with file:line evidence and the introducing commit identified via git blame, then a failing test written before the fix and a PR opened only after confirmation

CLAUDE.md Template

New here? 3-minute setup guide → | Already set up? Copy the template below.

# Datadog Error Tracking Triage to PR

Take Datadog Error Tracking issues to a reviewable PR — investigate, classify, root-cause, get approval, fix, and ship. Written to be restartable across separate sessions: a fixed error simply stops receiving new occurrences, and (where possible) a comment on the resolved issue lets the next run skip re-analysis.

## The Pipeline

```
0. Setup & disambiguate → 1. Navigate Datadog → 2. Pick an issue → 3. Root-cause in code
   → 4. ⛔ CONFIRM PLAN WITH USER → 5. Reproduce with tests + fix → 6. Comment on the issue → 7. Open a PR
```

**Hard gate at step 4:** investigate freely, but do not write a fix, create a branch, or open a PR until the user has seen the plan and approved it. The only exception is explicit pre-authorization ("just fix it and PR it").

Don't try to fix every issue in one pass. Scope a PR by size and risk: one large or critical bug gets its own PR; a few small, independent, thematically related bugs may share one PR (cap around 4).

## Step 0: Setup and Critical Disambiguations

Get these right before doing anything else:

- **"Incidents" almost always means Error Tracking *issues*, not a formal Incident Management system.** When a user says incidents, errors, "most occurrences," or "newest," they mean Error Tracking — errors grouped into issues with occurrence counts and trends.
- **Only the services your team actually owns are fixable from this repo.** If the codebase spans multiple deployable services, derive the live, in-scope service list from the actual directory structure (e.g. `ls apps/`) rather than a stale hardcoded list, and confirm any service outside that list is genuinely out of scope before touching it.
- **Production only**, unless the user hands you a specific staging issue. Error Tracking buckets by environment — filter `env:production` explicitly.
- **Don't confuse your own app's error tracking with a different product surface** that happens to share vocabulary (e.g. a "listIssues" tool from an unrelated integration). Confirm which tool/API actually reads your production runtime errors before using it.
- **Confirm the error-tracking capability is actually available** before relying on it — if a required toolset or integration looks disabled, say so and fall back to whatever raw span/log querying is still available rather than silently producing an incomplete triage.

## Step 1: Navigate Datadog

### Start With Discovery

Before querying, check whether Datadog (or your APM tool) ships built-in query-syntax guides or skill documentation for your specific setup — span query syntax and attribute naming vary enough between accounts that guessing is expensive. Load it once per session.

### The Lay of the Land

Identify your org's site/domain, the full service list (apps, DB adapters, external hosts), and note that a span's `service.version` tag is typically the deployed git commit SHA — this is gold, since it maps an error directly to the commit and deploy that introduced it.

### Where Error Tracking Issues Live

An issue is a fingerprinted group of error occurrences. Use two paths:

**(a) Error Tracking tools, if available** — a get-issue-by-id call and a list/search call are the minimum; there may also be a state-update or comment tool. Confirm the real tool names and schemas before relying on them.

**(b) Span aggregation, which always works** even without a dedicated Error Tracking toolset — issues are stamped onto error spans via custom attributes like an issue ID, first-seen timestamp, first-seen deploy version, and age, alongside the standard error type/message/stack/resource/service tags.

**Find the heavy hitters** (the workhorse query):

```
aggregate_spans(
  query    = "status:error env:production",
  from     = "now-7d", to = "now",
  computes = [{field:"*", aggregation:"COUNT", output:"count", sort:"desc"}],
  group_by = {fields:["service","@error.type"], limit:40}
)
```

Then narrow into messages/resources for the candidates that matter:

```
aggregate_spans(query="service:workers status:error env:production @error.type:(TypeError OR RepositoryError)",
  group_by={fields:["@error.message","resource_name"], limit:25}, computes=[COUNT desc])
```

### Query Pitfalls

- A free-text error-message field is often not reliably wildcard/full-text searchable — group by it in an aggregation, or filter by error type plus resource name and read messages from raw spans instead.
- Reserved attributes (service, resource name, status, type, trace ID) typically take no prefix; span-level custom attributes typically need one (e.g. `@error.type`, `@http.status_code`). Check your platform's actual syntax.
- Group multi-value filters correctly (`@error.type:(A OR B)`), not as separate OR'd field expressions.

## Step 2: Pick an Issue

### If the User Named One

Target it directly (by ID, slug, URL, or a quoted error message resolved via the queries above) and skip straight to root-causing.

### Otherwise: Classify Before Ranking

**Occurrence count alone is a trap.** Most high-count "errors" aren't fixable code bugs.

**Stage A — scope gate** (cheap): production, your in-scope services, the last 7 days. Inspect the top ~15 by count. Ignore anything under roughly 5 occurrences in the window unless it's new-and-rising or user-specified.

**Stage B — classify each candidate** by reading its message and stack:

| Class | Signatures | Default action |
|---|---|---|
| A. Genuine code bug | TypeError, null/undefined deref, validation/logic errors, encoding/parsing issues | **Candidate to fix** |
| B. Infra / transient | Timeout, connection reset, deadlock, rate limit, pool exhaustion | Usually not a code fix — note and skip |
| C. Deploy / version skew | Stale-client errors where the first-seen version differs from current deployed version | Framework-level handling, not a logic bug |
| D. Expected / not-an-error | A retried queue error, a not-found that callers already handle | Noise — ignore |
| E. Upstream / third-party | External provider errors with correct handling on your side | Not yours to fix |

Only Class A proceeds. For B–E, leave a one-line verdict if you can comment on the issue, then move on.

**Stage C — rank the Class-A bugs** on three axes, then pick the top:
1. **Impact** — customer-facing beats background; data corruption/loss beats a transient failure; a silently-wrong result beats a loud failure; does it block a user flow?
2. **Volume × trend** — occurrences *and* direction; a rising/new issue beats a flat/decaying one at equal count.
3. **Fix confidence × blast radius** — a clear, bounded root cause with a small change is high ROI; a sprawling or unclear one should be deferred.

Pick the highest (impact × trend) among the confidently fixable candidates.

### The Recency Premium

Weight new-and-rising issues extra even at a lower absolute count. "New" means first-seen within roughly the last 72 hours, or the first-seen deploy version is one of the last one or two deploys. A recent first-seen usually means a fresh regression — the first-seen version plus the deploy history around it often hands you the culprit commit directly, both making the fix faster and catching the regression before it piles up more occurrences. An old, flat, high-count issue is a yellow flag worth investigating eventually, not an automatic top pick.

### Batching

Solo PR for anything critical, large, touching core/shared code, or with a non-trivial root cause. Group 2–4 into one PR only if all are small, independent, low-risk, *and* thematically related (same subsystem, one reviewer context). Never mix a risky fix with trivial ones; cap around 4.

## Step 3: Root-Cause in Code

- **Generalize past the observed symptom.** One reported issue is often one instance of a broader bug — two seemingly unrelated errors in different services can share a single upstream root cause (e.g. unsanitized input hitting two different sinks). Fix the source, and look for sibling call sites with the same flaw.
- **Map the error to code from the span**: service → the corresponding app directory; resource name (a queue job, an HTTP route) → the handler; stack frames → the throwing module. Confirm the deployed version you're reading matches what actually produced the error.
- **Find the commit that introduced it.** The first-seen deploy version is the SHA of the deploy that introduced the regression — once you've located the faulty line(s), use `git blame`/`git log -S` to name the culprit commit and check it against the deploy history for context. Capture both the file:line and the commit SHA for the plan.
- **Decide fixability honestly.** If it turns out to be Class B–E in disguise, or needs a product/infra decision beyond code, say so and record it rather than forcing a fake fix.
- Fix at the architecturally correct layer for the codebase's existing conventions — search for an existing helper at that layer before writing a new one.

## Step 4: Checkpoint — Confirm the Plan (Do Not Skip)

**Stop here.** Everything up to now is read-only investigation. Present the plan and wait:

1. **Issues found** — a short table of candidates: error signature, service, occurrence count and trend, class, a link to the issue, and a one-line description of what it actually is (not just the raw message). Note which ones were ruled out and why.
2. **What you're focusing on and why** — impact × trend × confidence, plus what was deliberately skipped and its class-based reason.
3. **Hypothesis** — root cause in plain language, backed by file:line references (and sibling call sites, if it generalizes), the introducing commit where findable, and whether this is one instance of a broader bug.
4. **Proposed fix** — what changes, at which layer, the blast radius, and the test plan.
5. **PR plan** — single PR vs. grouped, and the target base branch.
6. **Blockers or decisions needed** — anything ambiguous, missing access, or larger/riskier than expected.

Wait for confirmation and adjust before proceeding. **Pre-authorization escape hatch:** if the user already said to fix and PR without checking back, state the plan briefly and proceed — but still stop for a genuine blocker, an ambiguous choice, or a fix that turns out materially larger than described.

## Step 5: Reproduce With Tests, Then Fix

1. **Write a failing test first** that reproduces the bug *and* new, different inputs exercising the same root cause — not just the one occurrence observed. This pins the specific bug and guards the general case.
2. **Confirm the test fails without the fix** — sanity-check it actually targets the bug (temporarily revert the fix, or assert the pre-fix behavior).
3. **Apply the fix at the root cause**, not just at the observed symptom's call site.
4. **Confirm the new tests pass and existing tests still pass.**

## Step 6: Comment on the Issue

Where the tooling supports it, leave a one-line summary of the root cause and fix on the resolved issue — so a future, context-free session doesn't redo the same analysis if the same error class resurfaces.

## Step 7: Open the PR

Target the project's standard base branch. Reference the Datadog issue link(s) in the PR description, along with the root-cause summary and test plan already drafted in Step 4's approved outline.

Get new playbooks like this one

One email a week with new Claude Code workflows. Free, like everything here.

No spam. Unsubscribe anytime.

README.md

What This Does

An end-to-end workflow for turning Datadog Error Tracking noise into a shipped, tested fix — built around the single most useful insight in production error triage: occurrence count alone is a trap, because most high-count "errors" aren't fixable code bugs at all. A five-class taxonomy (genuine code bug, infra/transient, deploy-version skew, expected-and-already-handled, upstream/third-party) filters candidates before any ranking happens, so a Class A bug — a real TypeError or validation failure — doesn't get lost behind a noisy connection-timeout that nobody should spend investigation time on. Surviving candidates get ranked on three axes (customer-facing impact, volume × trend, and fix-confidence × blast radius), with an explicit "recency premium" that weights a new-and-rising issue over an old flat one at the same count — because a fresh regression's first-seen deploy version usually hands you the introducing commit directly via git blame, making it both faster to fix and more valuable to catch early.

The workflow enforces a hard approval gate between investigation and code changes: everything through root-cause analysis is read-only, and the agent presents a structured plan (issues found and ruled out, chosen focus with reasoning, file:line evidence for the hypothesis, the proposed fix and its blast radius, PR scoping) and waits for explicit confirmation before writing a single line — with a pre-authorization escape hatch for "just fix it" workflows that still stops for a genuine blocker. The fix itself is test-first: a failing test that reproduces the bug and covers the general root cause (not just the one observed input) before any fix code is written, confirmed to fail without the fix and pass with it.


Quick Start

Step 1: Create a Project Folder

mkdir datadog-triage && cd datadog-triage

Step 2: Download the Template

Click Download above, then:

mv ~/Downloads/CLAUDE.md ./

Step 3: Triage Production Errors

claude

Ask Claude to find and fix your most impactful Datadog errors, or point it at a specific issue. It will classify candidates before ranking them, present a plan for approval before writing any code, then follow a test-first fix workflow and open a PR referencing the original issue.


Tips & Best Practices

  • Adjust the service-scoping and environment-filtering details in Step 0 to match your actual deployment structure — the workflow deliberately derives the in-scope service list from the real codebase layout rather than a hardcoded list, so it stays accurate as services are added or removed.
  • Take the recency premium seriously even when a resurfacing issue has a lower absolute count than an old chronic one — catching a regression within its first few deploys is both cheaper to fix and prevents the occurrence pile-up that makes root-causing harder later.
  • Never skip the Step 4 approval checkpoint under time pressure — the plan format (evidence, chosen focus, proposed fix, blast radius) exists specifically so a reviewer can catch a wrong root-cause hypothesis before it becomes a wrong fix in production code.

Limitations

  • Built around Datadog's Error Tracking and span-aggregation model specifically — the classification taxonomy and ranking logic transfer conceptually to other APM/observability tools, but the actual query syntax will need translating.
  • Assumes git-based deployments where a span's version tag maps to a commit SHA — an environment without that mapping loses the "find the introducing commit automatically" capability and needs manual root-cause tracing instead.
  • The batching guidance (solo PR vs. grouping up to ~4 small related fixes) is a starting heuristic; a team's own PR-size conventions should take precedence where they differ.

$Related Playbooks

Developer Tools

Documentation Review System

Mode-routed documentation review that diagnoses a page against its doc type and seven quality dimensions before touching a sentence, then picks the intervention level — maintenance, improve, rewrite, author, or strategy — that actually matches what's wrong.

10 minutes
Intermediate
Developer Tools

Designer's Figma-to-Production Workflow

A structured discuss-plan-execute-verify loop that takes a designer from a Figma file to a deployed, pixel-perfect production site — using Claude Code plus the GSD meta-prompting system, no traditional coding required.

20 minutes
Intermediate
Developer Tools

Distinctive Frontend Design

Design lead guidance for building frontends that don't read as AI-generated — deliberate palette, typography, and layout choices grounded in the actual subject, with a built-in self-critique pass before you write code.

5 minutes
Intermediate
Developer Tools

Continue Claude Work

Recover actionable context from local .claude session artifacts and continue interrupted work — without running claude --resume — by inspecting history first.

10 minutes
Intermediate
Developer Tools

Network Issue Debugging

Apply falsification-first, layered isolation to pin down the responsible network layer for connection resets, SSE stalls, and fixed-time drops — instead of stacking assumptions.

20 minutes
Advanced
Developer Tools

Docs Cleaner

Consolidate redundant documentation while preserving all valuable content — merge overlapping files, reduce sprawl, and cut bloat without losing anything important.

10 minutes
Beginner
Developer Tools

Database Sync Manager

Automate database synchronization, replication, migration, and cross-platform data integration

10 minutes
Advanced
Developer Tools

Developer Presentation Builder

Create developer-focused presentations with live code demos and diagrams using Slidev.

10 minutes
Advanced
Developer Tools

DevOps Automation Assistant

DevOps and IT Ops automation - CI/CD, monitoring, incident management, and infrastructure workflows

10 minutes
Advanced
Developer Tools

Discord Bot Builder

Discord bot development - community management, moderation, notifications, and AI integration

10 minutes
Advanced
Developer Tools

ETL Pipeline Builder

Design and automate Extract, Transform, Load data pipelines for data integration and analytics

10 minutes
Advanced
Developer Tools

Composio SDK with Claude Code: Connect 250+ APIs in Minutes

Connect Claude Code to 250+ APIs using Composio SDK. Build AI agents that send emails, create GitHub issues, and post to Slack — not just generate text.

15 minutes
Advanced

Browse all Developer Tools playbooks →