The dashboard is a small single-page application compiled into the jaque
binary and served from the same -listen address as the command API and
/metrics. It reads projections through the query service and submits
commands through the command service; it holds no state of its own beyond
an optional API token in the browser. It exists so that knowing what
jaque knows never requires a second deployment, and its cost is a poll:
every page refreshes by calling ListStatus every 5 seconds, so what is
shown is at most 5 seconds behind the event log.
Status: there is no push channel; live updates are on the roadmap, and until then the 5-second poll is the freshness bound. The dashboard does not authenticate users; see section 9 and the status page.
1. Embedded, not a separate service
The assets are compiled into the binary and served directly by it: no
node process, no separate deploy, no version to keep in sync with the
engine. One flag, -listen, turns the dashboard, the command API and
/metrics on or off together. Navigation is hash-based (#/overview,
#/hosts, ...), so every view is a URL and a reverse proxy needs no
rewrite rules.
The dashboard follows the operating system's color scheme by default: paper in light mode, graphite in dark mode. A toolbar switch can override this; see Theme below. The five state colors are the same ones the documentation uses, and a state is always shown as its color and its word, so a screenshot keeps its meaning without the color.
2. Overview (#/overview)
The landing page. Two rows of state tiles, one for hosts and one for
services, counting total, ok, warning, critical, unknown and pending;
each tile links to the unfiltered #/hosts or #/services. Below them
two tables: Unhandled problems, with no acknowledgement and no active
downtime, always visible; and Handled problems, acknowledged or in
downtime, inside a disclosure that is closed by default. What needs
attention is not buried under what is already being handled.
3. Hosts and services (#/hosts, #/services)
The full object table: name, state with its SOFT, FLAPPING and UNREACHABLE qualifiers, output, last change, and an acknowledgement and downtime glance. Everything is shown by default; a "Problems only" toggle filters and sorts by severity without changing what no filter means.
A selector box above the table takes the same
label selector grammar used everywhere
else (env=prod, team=redes). Applying it writes the selector into the
URL as a query parameter (#/hosts?sel=env%3Dprod), so a filtered table
is a shareable link and each apply is its own history entry that the
browser's back button undoes. A selector that fails to parse shows the
error under the box instead of silently showing the unfiltered table.
With a selector active, both pages show a Bulk actions panel that acknowledges or schedules downtime against every matching object at once. That is one command with a selector target, not one request per row.
4. Object detail (#/object/<host>, #/object/<host>/<service>)
State, output, acknowledgement and downtime detail, and a timeline of
recent transitions from ListHistory. The timeline can be filtered by
the resulting status and by state type, and re-ordered oldest-first with
a toggle on the At column; times are shown in the browser's local time,
with the raw timestamp available as a tooltip. The acknowledgement and
downtime forms are the same ones the row-level panel uses. A host's
detail lists its services; a service's detail links back to its host, so
the reader can walk up one level without losing context.
5. Labels as navigation
Every row and every detail view shows the object's labels as clickable
chips. Clicking key=value navigates to #/hosts or #/services with
that pair applied as a selector. It is the same mechanism as clicking a
group link from #/groups: a group in jaque is a selector, and a label
is a one-term selector.
6. History (#/history)
The global transition feed from ListHistory, newest first, 100 by
default. Filterable by host, by service once a host is set, and by limit;
the same 5-second poll as every other page, plus an explicit "Apply" for
filter changes so a half-typed filter does not fire. The timeline itself
can also be filtered by the resulting status and by state type, and
re-ordered oldest-first with a toggle on the At column; times are shown
in the browser's local time, with the raw timestamp available as a
tooltip.
7. Downtimes (#/downtimes)
Every scheduled downtime and every acknowledgement across all hosts and
services in one place, so reviewing or clearing them does not mean
visiting each object. Two tables: downtimes with a Delete button that
calls DeleteDowntime, and acknowledgements with a Remove button that
calls RemoveAcknowledgement. A "New downtime" form targets either one
object or a selector, without starting from a row.
8. Contacts and groups (#/contacts, #/groups)
#/contacts lists every configured contact with its type and labels.
#/groups has no native groups to show, because jaque has none: a group
is labels and selectors, not a first-class object (see
Labels and views). The page shows the
saved views with name, selector, description and live member count, and a
table of every label seen across the fleet with its object count. Both
kinds of count link into #/hosts with that selector applied.
9. Settings and the API token
When jaque runs with -api-token, a "Settings" disclosure holds a token
field. The token is saved to the browser's localStorage and sent only as
Authorization: Bearer on command POSTs. Reads (ListStatus and the
rest of the query service) never require it, matching the API's own
posture described in
Command and query service. There
are no cookies and no session.
10. Sinks
When at least one sink is configured, a "Sinks" disclosure next to
Settings lists every sink ListSinks reports: name, type, input
(metrics or events) and selector when one is set. It is read-only and
shows no runtime state; lag and write errors stay on /metrics, where a
collector can see them.
11. Security considerations
The dashboard is served on -listen with no authentication of its own.
-api-token protects commands, not reads: anyone who can reach the
listener can see every object, its output and its labels. The token lives
in the browser's localStorage in clear. Put the listener behind a
reverse proxy that terminates TLS and authenticates users, or bind it to
an address only that proxy can reach; see
Security.
Theme
The toolbar carries a three-state theme switch next to Problems only and Settings: Auto, Light, Dark. Auto follows the operating system's color preference; Light and Dark override it. The choice is stored in the browser and applies immediately, charts included.
Command palette
The palette opens with / or with Ctrl-K (Cmd-K on a Mac), and from the
"Search" button in the toolbar. Typing filters views, panels, and every host
and service the dashboard currently knows about; arrows move, Enter goes,
Escape closes.
What it lists comes from the same 5-second poll as the rest of the page, so an object that appeared seconds ago may not be there yet. It also carries two actions that have no page of their own: toggling Problems only, and cycling the theme.