Skip to content

feat(crashdump): add Crashdump pillar browsing erl_crash.dump files#59

Merged
thiagoesteves merged 4 commits into
mainfrom
thiagoesteves/crashdump-viewer
Jul 13, 2026
Merged

feat(crashdump): add Crashdump pillar browsing erl_crash.dump files#59
thiagoesteves merged 4 commits into
mainfrom
thiagoesteves/crashdump-viewer

Conversation

@thiagoesteves

@thiagoesteves thiagoesteves commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

The last big item from the observer_cli / OTP-observer gap-closing plan: a web crash dump browser - something no BEAM web tool offers today.

Pick an erl_crash.dump from the allowlisted directories, watch the parse progress live, then:

  • Slogan front and center (the reason anyone opens a dump), plus the VM's counters at crash time (node, OTP, processes, ETS tables, timers, atoms, memory).
  • Every dumped process: sortable by memory/reductions/message queue, searchable by name or pid, top-250 display cap.
  • Per-process drill-down: state, links, monitors, dictionary, message queue and the full stack dump.

How it works

  • Reuses OTP's own parser: :crashdump_viewer (observer app) is a plain gen_server behind the wx GUI - this feature drives it headless, so the notoriously tricky dump format is never reimplemented. No GUI/wx is ever started.
  • ObserverWeb.Crashdump.Server owns the parser lifecycle: starts it on demand, serializes loads, and receives progress through a small linked relay process holding the registered name the parser reports to (a process can carry only one registered name). Progress is re-broadcast over PubSub → live progress bar for multi-GB dumps.
  • Records decode by zipping documented field orders over tuples - tolerant of OTP record evolution - and pids round-trip through the parser's own textual form.

Safety & availability

  • No free path input: only files found in config :observer_web, crashdump_dirs: [...] are browsable; with no configuration the page stays off. Documented with an explicit production-data warning (dumps hold process states, message queues, app data at crash time).
  • Parsing happens on the dashboard node only - nothing fetched from remote nodes.
  • Hosts without the :observer app in their release get a graceful notice; dev/test load it via Mix.ensure_application!/1 (Mix ≥1.15 path pruning).

Risk assessment

Area Change Risk Mitigation
Production data exposure Dumps contain everything the VM held at crash High as product concern, mitigated by design Allowlist-only directories, off by default, read-only, documented warning, existing auth resolver applies
Coupling to :crashdump_viewer internals Its GUI-facing API + record shapes + progress protocol Medium API stable across releases (same contract the wx GUI uses); field-zip decode degrades on shape drift; full pipeline tested against a real dump generated by a crashed peer node
Parser resource usage Large dumps take time/memory to parse on the dashboard node Medium Serialized loads (one at a time), live progress, explicit LOAD action - never automatic
Registered-name interplay The relay holds cdv_progress_handler; clash if the cdv GUI is open on the same node Low Detected and reported as an error instead of silently missing progress
Dialyzer ignore entries :crashdump_viewer calls invisible to the PLT (path pruning) Low Ignore-listed with rationale; every call behind available?/0 and covered by real-dump tests
New pillar wiring Additive (nav, icon, route) Low Standard suite; 393 tests green ×3 seeds

Checklist

  • mix format, credo --strict, dialyzer (exit 0), full suite 393 green ×3 seeds
  • Full pipeline tested against a real erl_crash.dump from a crashed peer node
  • README + guides entries; crashdump_dirs documented with security warning
  • guides/static/crashdump_dash.png screenshot (needs a capture from a dev node before merge - configure crashdump_dirs and crash a peer, or point it at any dump you have around)

🤖 Generated with Claude Code

Adds a web crash dump browser - the last big item from the
observer_cli / OTP-observer gap-closing plan. Pick a dump, watch the
parse progress live, then read the crash slogan, the VM's counters at
crash time, and every dumped process: sortable by memory, reductions
or message queue, searchable, with a drill-down showing the full
per-process record including the stack dump and message queue.

Parsing reuses OTP's own crashdump_viewer gen_server (observer app)
instead of reimplementing the dump format - no GUI/wx is ever started.
A dedicated ObserverWeb.Crashdump.Server owns the parser: it starts it
on demand, serializes loads, and receives the parser's progress
reports through a small linked relay process registered under the
name the parser reports to (a process can only carry one registered
name), re-broadcast over PubSub so the page renders a live progress
bar. Records are decoded by zipping documented field orders over the
tuples, degrading gracefully across OTP record evolution, and pids
round-trip through the parser's own textual form.

Safety and availability follow the established patterns: there is no
free path input - only files in explicitly allowlisted crashdump_dirs
are browsable, and with no configuration the page stays off (dumps
hold everything the VM had at crash time; documented with a warning).
Hosts without the observer application get a graceful notice; dev and
test load it via Mix.ensure_application!/1. Dialyzer cannot see the
pruned observer app, so the crashdump_viewer calls are ignore-listed
with a comment explaining why they are safe.

Tests exercise the full pipeline against a real crash dump generated
by halting a peer node - listing, allowlist rejection, progress,
general info (slogan), process summaries, details round-trip, and the
page flow from LOAD to the stack dump panel.
Addresses the concern about the :observer dependency by making the whole
feature - including its navigation tab - opt-in behind a single flag,
and by adding file upload so a dump can be inspected without any
server-side directory:

  * config :observer_web, crashdump: true gates the pillar. Off by
    default the tab never appears; the page (if reached directly)
    explains how to enable it. When on but :observer isn't in the
    release, it explains that instead.
  * Upload an erl_crash.dump straight from the browser (e.g. one pulled
    off a crashed Nerves device) - it is copied to a temporary path the
    parser re-reads for the session and the previous upload is cleaned
    up. The directory listing is kept as a second, optional path and no
    longer required.

The crashdump_dirs allowlist still governs host-side browsing (no free
path input); uploads are size-capped and consumed to a controlled temp
file. The nav also moves Crashdump ahead of Metrics so Metrics stays
last. Enabled in the dev server for convenience.

Real-upload parsing is covered end to end at the context level
(load_upload/1 against a dump from a crashed peer node); the page test
covers the upload UI and the validate/empty-submit handlers, since
simulating the upload channel through the nested LiveComponent hits a
test-harness limitation.
@thiagoesteves thiagoesteves moved this to In Progress in Observer Web Jul 13, 2026
@thiagoesteves thiagoesteves merged commit 578e7cf into main Jul 13, 2026
5 of 6 checks passed
@thiagoesteves thiagoesteves deleted the thiagoesteves/crashdump-viewer branch July 13, 2026 13:05
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Observer Web Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant