Dashboard
You shouldn’t need a separate console to know what jaque knows. The dashboard is a small SPA served by the binary itself — no Node process to run, no separate deploy.
Embedded, not a separate service
Section titled “Embedded, not a separate service”The dashboard’s assets are compiled in and served directly by the binary —
no separate deploy, no version to keep in sync. It hangs off the same
-listen port as the command API and /metrics — one flag turns all
three on or off together. Navigation is hash-based (#/overview,
#/hosts, …), and it refreshes by polling ListStatus every 5
seconds — there’s no websocket push yet, so what you see is at most 5
seconds stale.
Overview (#/overview)
Section titled “Overview (#/overview)”The landing page. Two rows of state tiles (total, ok, warning, critical,
unknown, pending) — one row for hosts, one for services — each tile
linking to the unfiltered #/hosts or #/services. Below that, two
tables: Unhandled problems (no ack, no active downtime — always
visible) and Handled problems (acked or downtimed) inside a
closed-by-default disclosure, so what actually needs attention isn’t
buried under what’s already being handled.
Hosts and Services (#/hosts, #/services)
Section titled “Hosts and Services (#/hosts, #/services)”The full object table: name, state (with SOFT/FLAPPING/UNREACHABLE qualifiers), output, last change, ack/downtime glance. Shows everything 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 as everywhere else (env=prod, team=redes). Applying it puts the
selector in the URL as a query param
(#/hosts?sel=env%3Dprod) — shareable as a link, and the browser’s back
button undoes it, since each apply is its own history entry. A selector
that fails to parse shows the error under the box instead of silently
falling back to unfiltered.
With a selector active, both pages also show a Bulk actions panel (acknowledge or schedule downtime against every matching object at once) — one command with a selector target, not one request per row.
Object detail (#/object/<host>, #/object/<host>/<service>)
Section titled “Object detail (#/object/<host>, #/object/<host>/<service>)”State, output, ack/downtime detail, and a recent-transitions timeline from
ListHistory. The same ack/downtime forms as the row-level panel, not a
separate version. A host’s detail page lists its services below; a
service’s detail page links its host name back to the host’s own detail
page, so you can walk up a level without losing context.
Labels as navigation
Section titled “Labels as navigation”Every row and detail view shows the object’s labels as clickable chips.
Clicking key=value navigates to #/hosts or #/services with that pair
already applied as a selector — the same mechanism as clicking a group
link from #/groups.
History (#/history)
Section titled “History (#/history)”The global transition feed via ListHistory, newest first, 100 by
default. Filterable by host, service (only meaningful once a host is set)
and limit; same 5-second poll as the rest of the SPA, plus an explicit
“Apply” for filter changes.
Downtimes (#/downtimes)
Section titled “Downtimes (#/downtimes)”Every scheduled downtime and every acknowledgement, across all hosts and
services, in one place — no need to visit each object individually to
review or clear them. Two tables (downtimes with a Delete button calling
DeleteDowntime; acknowledgements with a Remove button calling
RemoveAcknowledgement), plus a “New downtime” form that targets either a
specific object or a selector, without needing to start from a row.
Contacts and Groups (#/contacts, #/groups)
Section titled “Contacts and Groups (#/contacts, #/groups)”#/contacts lists every configured contact, its type, and its labels.
#/groups has no native groups to show — in jaque a “group” is labels and
selectors, not a first-class object (see Labels and
views) — so the page shows saved views
(name, selector, description, live member count) and a table of every
label seen across the fleet with its object count. Both the view member
count and each label’s count link straight into #/hosts with that
selector pre-applied.
Settings and the API token
Section titled “Settings and the API token”If jaque is running with -api-token, a “Settings” disclosure holds a
token field: saved to the browser’s localStorage, sent only as
Authorization: Bearer on command POSTs. Reads (ListStatus and
friends) never require it, matching the API’s own posture (see Command
and query service). No cookies,
no session — real authentication is the reverse proxy’s job, not the
dashboard’s.
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 it has one. Read-only — no runtime state (lag,
last write) shown here, that stays on /metrics.