Operating in Production: On-Call, Incident Command, and Reporting Clocks Module 5 · Learn

Reconstruct the Timeline

Last reviewed · content updated

Intermediate

What you'll learn

~16 min
  • Reconstruct an incident timeline from logs, traces, and chat that already exist, without adding new instrumentation mid-incident
  • Read a trace span that shows where a request's time actually went, and state what it proves versus what it does not
  • Record who drafted a timeline and who verified it, using the record's AI-drafted field

Before the detail — Decision: reconstruct the incident timeline from the logs, traces, and chat that already exist, rather than instrumenting mid-incident. Outcome: a monotonic, source-backed timeline with named gaps, ready for section 3 of the incident record. Artifact: the timeline entry and the trace excerpt that answers where the time went. Status of what follows: reusable guidance; the retention window it depends on is a binding evidence floor set elsewhere.

Prompt first: reconstruct from what you already have

Here are raw log lines from the incident window [paste JSON lines -
timestamps, route, status, duration_ms only; strip anything else].
Reconstruct a timeline table: Time (UTC) | What happened. Use ONLY
timestamps and values present in the lines I pasted. Where the gap
between two lines is longer than [our normal request interval],
insert a row: "MISSING - no log line between HH:MM:SS and HH:MM:SS."
Do not infer a cause, a duration, or an event with no line behind it.
If two lines could describe the same event, keep both and say so;
do not merge them into one guessed sentence.

Reconstruction is retrieval, not narration — the discipline that keeps a drafted timeline from becoming the first hypothesis dressed up as a fact.

Reconstruction, not instrumentation

This lesson never adds a log line, a metric, or a trace that was not already being emitted before the incident started; building that pipeline, and the evidence floor it sits on, belongs to Zero Trust 5.1 (a separate training in this series): six months searchable, twelve retrievable. What 5.2 owns is reading what is already there — the service’s own logs, a trace, and the chat where responders talked to each other — and turning it into one monotonic table.

A reconstruction built entirely from retained data is available during the review; one that requires new logging arrives after the incident it was meant to explain — calendar time is the difference.

What the replay shows

Meridian’s fielddesk-api simulator replays one incident byte-for-byte, and the shape it shows is the shape a slow-motion outage usually takes. At 14:00 the service is steady on version 1.14.2, requests landing in 18–190 ms. At 14:15:00Z, change CHG-2026-4402 rolls fielddesk-api@1.14.3 out to 100% of pods, and for the next several minutes nothing looks wrong: requests at 14:15 still return in 18–110 ms, and /healthz returns 200 in 2 ms.

By 14:24, most replayed application requests take 1,728–1,893 ms with the pool at 58 of 64. Successful GET requests return 200 and successful POST requests return 201, but one POST already returns 504 during that minute; /healthz still returns 200 in 3 ms because it bypasses the pool. By 14:39–14:40 the pool is at 64 of 64 and 504s are frequent. CHG-2026-4403 rolls back to 1.14.2 at exactly 14:40:00Z; the excerpt still shows failures afterward, and the simulator drains the pool over five minutes.

A healthy-looking probe and a large share of requests still succeeding conceal a ramp that has already taken the slowest requests from 190 ms to nearly two seconds — reading the replay end to end turns “when did this actually start” from a debate at the review into a timestamp anyone can point to.

The span that shows where the time went

The committed trace demo renders the same route in healthy and incident-shaped variants; its pinned trace ID and timestamp do not match a replay request. In the healthy 1.14.2 variant, db.pool.acquire lasts 1 ms. In the incident-shaped 1.14.3 variant, it lasts 1.975 s, ends with no connection available after 2000ms, and reports 64 of 64 connections in use. The parent request lasts exactly 2.000 s and returns 504.

Put the two spans side by side and the arithmetic does the explaining: 1.975 of the request’s 2.000 seconds were spent inside db.pool.acquire, waiting for a database connection that never came free. Almost none of that time was application logic. The trace demo pins its span and trace identifiers so the console output is byte-identical for every reader — say plainly that pinning an identifier like that has no place outside a demo, because a production trace needs those identifiers unique per request to be worth anything at all.

The federal shape of the same artifact already exists: M-17-12 (OMB’s 2017 breach-response memo — OMB being the White House budget office) carries a flow-down clause — it binds a subcontractor that never signed with the government — and requires the agency’s contract to make a contractor and its subcontractors capable of constructing “a timeline of user activity” when it applies; a span that names where 1.975 of 2.000 seconds went is exactly that kind of fact, built once and readable by both audiences.

The assistant drafts; the responder corrects

The prompt at the top of this lesson is the honest version of what an assistant is good for here: given the raw lines, it drafts a timeline table faster than a human typing it out by hand, and it marks a MISSING row instead of inventing a plausible-sounding bridge across a gap. What it must never do alone is finish the job — 3.4’s field records a draft identifier, the responder who verified it, and when, because an AI-drafted timeline is evidence about what a language model inferred from log lines, not yet a verified fact about the incident.

Citing an AI-drafted timeline to a regulator or a contracting officer without a named verifier attached is not a technicality — it converts a tool’s inference into the organization’s signed claim, and the exposure if that inference turns out wrong is Meridian’s, not the assistant’s.

Stop and escalate when the available logs and traces cannot be made into a monotonic timeline, or a gap longer than the platform’s normal request interval has no MISSING row and no explanation attached to it — escalate to the clock desk and the incident commander, because a timeline with a silent gap is not evidence; it is a story with a hole a reviewer will eventually find.

KNOWLEDGE CHECK

The trace excerpt shows the db.pool.acquire span running for 1.975 of a 2.000-second request before ending in an error, while the parent http.server span reports a 504 'upstream gateway timeout' at exactly 2.000 seconds. What does this pair of spans establish?

Key takeaway

A timeline is reconstructed from what the platform already logs, traces, and records in chat — never from instrumentation added mid-incident, which belongs to Zero Trust 5.1’s evidence floor and arrives too late for this one anyway. The replay shows the shape a slow-motion outage takes: latency climbs from tens of milliseconds to nearly two seconds while the health probe stays green and most requests still succeed; one 504 already appears at 58 of 64, and failures become frequent when the pool reaches 64 of 64. A single span — db.pool.acquire, holding 1.975 of a 2.000-second request — answers where the time went with more authority than either. An assistant can draft that reconstruction from pasted lines; a named responder corrects it, and the record keeps both names, because an unverified draft is not yet evidence. Lesson 5.3 turns from the timeline itself to what the review does with it: a corrective-action register that has to change something.

LEADERSHIP DECISION require every incident record's timeline to
cite its source lines - logs, traces, or chat
- never a memory of what happened
PRACTITIONER ACTION reconstruct from existing logs and traces
first, mark every gap MISSING, and have the
AI-drafted timeline named and corrected before
it is trusted
SUCCESS MEASURE every timeline row traceable to a source line
or marked MISSING, and zero AI-drafted
timelines entering the record without a named
verifier - assessor-hours, not a rebuild from
memory
Search lessons