Skip to content

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.

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.

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.

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.

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.

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.

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.

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.