Local-first CLI · MySQL ROW binlogs · Open source

Turn MySQL ROW binlogs into incident-ready reports

BinlogViz helps DBAs and on-call engineers move from raw binlog events to a clear account of what was written, where, and when. Find hot tables, large transactions, write spikes, and incident-window changes, compare current versus baseline, and hand the result to your team. Reads ROW-format binlogs; STATEMENT and MIXED events are not counted.

$ binlogviz analyze --from-dir /var/lib/mysql --prefix mysql-bin. --start 2026-03-15T10:00:00Z --end 2026-03-15T10:30:00Z --format json --snapshot-name incident-current --workload-id orders-production $ binlogviz analyze --from-dir /var/lib/mysql --prefix mysql-bin. --start 2026-03-14T10:00:00Z --end 2026-03-14T10:30:00Z --format json --snapshot-name incident-previous --workload-id orders-production $ binlogviz analyze --from-dir /var/lib/mysql --prefix mysql-bin. --start 2026-03-08T10:00:00Z --end 2026-03-08T10:30:00Z --format json --snapshot-name baseline-weekly-orders --workload-id orders-production $ binlogviz trend --from-snapshots 'incident-*' --baseline-snapshot baseline-weekly-orders --format html > trend.html
4Output formats
1×Streaming pipeline
0Hosted services required
HTMLBrowser-shareable report

Answer the operator questions that matter before the incident room loses patience

BinlogViz does not replace low-level binlog tooling. It sits one layer above it: aggregating workload shape, surfacing abnormal moments, and packaging the result so it can move cleanly into an incident review, issue thread, or postmortem.

◎

Hot tables first

See where writes concentrated instead of scanning raw row events line by line.

!

Large transactions surfaced

Find outsized transactions before they disappear into a long stream of ordinary noise.

↗

Spike-aware investigation

Optional spike detection points attention at the minute most likely to explain impact.

Start where real binlog investigations actually begin

The value of BinlogViz is clearest at the moment somebody already has binlogs and needs answers fast: validate one file, widen to an incident window, undo the rows that should not have been written, then export something a teammate can read without replaying the whole investigation.

🗂

Validate one file quickly

Use a single binlog to prove the path, preview the default report, and sanity-check event volume fast.

⏱

Constrain the incident window

Use time, schema, and table filters to reduce noise and keep the report focused on the event you care about.

📄

Undo or replay the bad rows

Print SQL that reverses the selected INSERT, UPDATE, and DELETE row images, or replays them forward. You review the script and apply it yourself; the tool never connects to write.

Resolve files, aggregate in a streaming pass, render the answer in the right surface

The architecture stays intentionally direct: parse, normalize, analyze, finalize, render. That makes the tool easier to reason about and keeps the product story focused on fast-to-insight investigation instead of infrastructure complexity.

Provide inputfile, directory range, pipe, or live server
→
Apply filterstime, schema, table, object focus
→
Get a reportalerts, summaries, charts, exports

Streaming by design

Parsing, normalization, analysis, finalization, and rendering flow forward rather than collecting every event into one giant in-memory buffer first.

Automation-safe I/O contract

Reports stay on stdout while progress and runtime status stay on stderr, so redirecting output into files or pipelines remains predictable.

Analyze locally, compare when needed, hand off in the right surface

Output format is part of the product. Analyze can end as text, JSON, Markdown, or self-contained HTML. Compare turns two exported JSON reports into a text summary, structured JSON delta, or chart-based HTML review artifact.

Preview the reporting surfaces teams actually use

Use the tabs below to see how an incident answer moves across terminals, automation, docs, and browser-based review. The output shown is a real run against the sample binlog, not a mockup. Compare reuses text, JSON, and HTML once two snapshots or analyze JSON reports exist.

$ binlogviz analyze testdata/minimal.binlog --format text

=== Summary ===
  Time Range: 2026-03-15 14:10:26 UTC - 2026-03-15 14:10:26 UTC
  Timestamps: UTC (binlog)
  Format: ROW images / logical rows (STATEMENT/MIXED Query-DML is not counted)
  primary key presence unknown (binlog_row_metadata is not FULL)
  Total Transactions: 4
  Partial Transactions: 0
  Unknown Transactions: 0
  Total Rows: 4
  Total Events: 22
  DDL Timeline: 1 (CREATE TABLE)
  Input File Size: 1.5KB
  Counted Event Bytes: 342B
  Largest txn: 289B
  Top txn bytes: txn-4 289B, txn-2 269B, txn-3 267B
  Top table bytes: testdb.users 342B

Why visual compare expands the product story

HTML is no longer just a prettier analyze export. It also gives DBAs a browser-ready compare view for current-versus-baseline review, with charts that make workload changes easier to scan together.

  • Interactive charts summarize workload shape and current-versus-baseline deltas without requiring CLI context.
  • Compare HTML exposes table shifts, operation mix changes, and alert additions or removals in one review surface.
  • Markdown stays useful when the next destination is a wiki or incident note.
  • JSON remains stable for automation, downstream processing, and compare inputs.

Trust the contract, not just the parser

Reports follow a documented contract, so you can script against them and hand them to a teammate without caveats.

📘

Documented behavior

CLI flags, output formats, exit codes, and limitations are documented, and binlogviz schema prints the JSON Schema of every JSON output.

📄

One analysis, four formats

Text for the terminal, JSON for scripts, Markdown for a ticket, HTML for review in a browser. Every format reports the same findings.

📦

Predictable failures

Every error has a kind and a documented exit code, so a script can tell a filter that matched nothing from a truncated file.

🧭

Focused scope

A binlog analysis CLI, not a general observability platform. It runs locally and needs no hosted service.

Install once, validate one file, widen only when the question demands it

Install the binary, analyze one binlog, then move to directory ranges and named snapshots when you need a baseline to compare against.

Quick start

# macOS only (Homebrew cask) $ brew tap Fanduzi/binlogviz $ brew install --cask binlogviz # Linux: install.sh writes to /usr/local/bin, which needs root $ curl -fsSLO https://raw.githubusercontent.com/Fanduzi/BinlogVisualizer/main/install.sh $ sudo sh ./install.sh # or, without root, a directory you own $ sh ./install.sh --bin-dir ~/.local/bin # verify install with the sample ROW binlog $ curl -fsSLO https://raw.githubusercontent.com/Fanduzi/BinlogVisualizer/main/cmd/binlogviz/testdata/minimal.binlog $ binlogviz analyze minimal.binlog # save current + baseline snapshots, inspect them as JSON, then open a visual compare report $ binlogviz analyze --from-dir /var/lib/mysql --prefix mysql-bin. --start "2026-03-15T10:00:00Z" --end "2026-03-15T10:30:00Z" --format json --snapshot-name incident-current --workload-id orders-production $ binlogviz analyze --from-dir /var/lib/mysql --prefix mysql-bin. --start "2026-03-08T10:00:00Z" --end "2026-03-08T10:30:00Z" --format json --snapshot-name baseline-weekly-orders --workload-id orders-production $ binlogviz snapshot show incident-current --format json $ binlogviz compare --current-snapshot incident-current --baseline-snapshot baseline-weekly-orders --format html > compare.html

What a good first session looks like

  • Validate one file to confirm the default report shape.
  • Use --from-dir and --prefix when the window spans multiple binlogs.
  • Add --start, --end, schema, or table filters to cut noise.
  • Save named snapshots when you need a baseline, inspect them as JSON when automation needs context, then use compare --format html for browser-based review.

What changed in each version: release notes and CHANGELOG.

Make the next binlog investigation easier to explain

BinlogViz gives you a local-first path from raw MySQL ROW binlogs to an answer the rest of the incident room can actually read.