The dashboard
What each page of /sailfish shows, and the two gates that decide who sees it.
The dashboard lives at /sailfish. It is self-contained (Blade, Alpine and uPlot, served by the package
itself), so there is nothing to build or publish for it, and it runs under a Content-Security-Policy without
'unsafe-eval'. Who can open it is up to the gates described in
installation.
Every rate on it is what moved over the seconds the snapshots cover, never a raw delta. After a gap, one snapshot covers hours, and its rows are spread over them rather than drawn as one spike.
Overview#
Open events, rows read through an index against rows read by full scans, the five most scanned tables, and markers on the charts for MySQL restarts and schema changes. This is the page to open after a deploy.
Server#
Connections against max_connections, statements, time waiting for row locks, buffer pool misses,
temporary tables and sorts spilling to disk, and InnoDB's history list. It also shows the buffer pool's size against
the data being watched, which answers whether the working set still fits in memory.
Activity#
Read live when you open it, and never stored. It shows who is blocking whom, as trees from the session everyone
waits for, over row locks and table metadata locks. The classic case is an ALTER TABLE stuck behind
an idle transaction, with every query on that table queued behind the ALTER. It also lists open
transactions oldest first, flagging those idle in a transaction, and the statements running now.
It needs nothing beyond SELECT on performance_schema. Statements are shown with each
literal replaced by ? unless the viewer passes the viewSailfishQueryText gate.
Indexes#
Every index with its status, its last use, its size, its columns and 30 days of reads and writes. The status is one of:
| Status | Meaning |
|---|---|
| hot | Last fetched within the last 7 days |
| cold | Fetched before, but not in the last 7 days |
| never used | No fetch in the history Sailfish has |
| dropped | Gone from the schema, kept with its history |
PRIMARY and unique keys are hidden until you ask for them: they enforce a constraint, so "unused" means little. Each index has a page with its full history and the indexes that cover it, and a redundant one shows how to drop it.
Tables#
Rows fetched through an index against rows scanned, over time and broken down by index, with the time spent waiting for table locks. Size and row count are read once a day and charted beside them.
Errors#
Errors the server raised over time, the most frequent, and when each was first seen. Deadlocks (1213), lock wait timeouts (1205) and duplicate keys (1062) are pointed out. Errors are counted server-wide, not per schema.
Events#
The full record of every event, open and resolved, filterable by type. This is where an event is acknowledged, which stops its reminders, or muted until a date or for good. Detectors still waiting for enough history say here how many more days each one needs.