Documentation
Dashboards as code
cpum.ai dashboards are plain JSON. Export the dashboards you build in the UI, check them into git, and re-import them through the API on every commit. The contract is jsonnet-friendly: emit JSON, we validate and upsert by slug.
The schema (v1)
Every dashboard document is an object with schemaVersion: 1, a unique slug, a title, a description, an optional variables map, and an array of panels. Each panel has an id, a type, a 12-column layout (x, y, w, h), optional render options, and either a typed query reference or (for text panels) a markdown text body.
{
"schemaVersion": 1,
"slug": "checkout-overview",
"title": "Checkout overview",
"description": "Latency, error rate, and recent incidents for the checkout service.",
"variables": {},
"panels": [
{
"id": "p-mttr",
"type": "single_stat",
"title": "MTTR (last 30d)",
"layout": { "x": 0, "y": 0, "w": 4, "h": 3 },
"options": { "unit": "s" },
"query": {
"kind": "analytics_summary",
"field": "mttrSeconds",
"days": 30
}
},
{
"id": "p-cpu",
"type": "timeseries",
"title": "CPU %",
"layout": { "x": 4, "y": 0, "w": 8, "h": 3 },
"options": {},
"query": {
"kind": "metrics_history",
"metric": "cpu_percent",
"windowMin": 60
}
},
{
"id": "p-incidents",
"type": "table",
"title": "Recent incidents",
"layout": { "x": 0, "y": 3, "w": 12, "h": 5 },
"options": {},
"query": {
"kind": "incidents",
"days": 30,
"limit": 50
}
}
]
}Panel types
| type | description | supported queries |
|---|---|---|
| timeseries | Recharts line chart. One or more series over time. | metrics_history, analytics_trend |
| single_stat | Single big number with optional unit/precision in `options`. | summary, analytics_summary, logs_count, trace_latency |
| table | Tabular data; columns are determined by the bound query. | slos, analytics_by_service, incidents, logs_count, trace_latency |
| text | Markdown / plain-text note. No query — content lives in the `text` field. | — |
Query kinds
Each panel binds to one typed query. The set is additive across schema versions, so dashboards exported from older cpum.ai builds keep importing cleanly. Unknown kinds are rejected at import time so schema drift never silently disappears.
Host CPU/memory/disk/process count over the last 5m or 60m.
{ "kind": "metrics_history", "metric": "cpu_percent", "windowMin": 60 }Live single-host KPI (cpuPercent, memoryPercent, diskUtilPercent, …).
{ "kind": "summary", "field": "cpuPercent" }Incident analytics KPIs, daily trend, and per-service breakdown over the last N days.
{ "kind": "analytics_summary", "field": "mttrSeconds", "days": 30 }All SLOs for the account with current SLI and status.
{ "kind": "slos" }Recent incidents (any status) within the configured window.
{ "kind": "incidents", "days": 30, "limit": 50 }OTel logs grouped by severity_text over the last N hours. Optional `service` filter. Use as a single_stat (total, or pick one bucket via `options.severity`) or as a table.
{ "kind": "logs_count", "service": "checkout-api", "hours": 1 }OTel root-span p50/p95/p99 latency over the last N hours. Optional `service` filter. As a single_stat, pick a percentile via `options.percentile` ("p50" | "p95" | "p99", default p95); as a table, all three percentiles render side by side.
{ "kind": "trace_latency", "service": "checkout-api", "hours": 1 }Reference to another panel's query, looked up by `dashboardSlug` + `panelId`. Lets you build a library dashboard of canonical queries and reuse them everywhere. The host panel keeps its own `type` and `options`, so the same saved query can render as a stat in one dashboard and a table in another.
{ "kind": "saved_query", "dashboardSlug": "library", "panelId": "p-error-rate" }Round-trip (export ↔ import)
Export and import are guaranteed lossless: GET /api/dashboards/:id/export returns the canonical JSON for the dashboard (keys ordered, defaults filled in), and POST /api/dashboards/import upserts by slug under your account. Re-exporting an imported dashboard yields byte-identical bytes.
jsonnet → JSON → API
We don't bundle a jsonnet runtime. Compile your jsonnet locally (or in CI) and POST the resulting JSON. That keeps the contract stable across language ecosystems and works with any preprocessor that emits JSON.
# Compile jsonnet → JSON, then ship it through cpumctl jsonnet checkout.jsonnet > checkout.json # Validate locally first (no network) — perfect for a PR check cpumctl dashboards apply ./checkout.json --dry-run # Then upsert it for real (uses CPUM_API_KEY from the environment) cpumctl dashboards apply ./dashboards/*.json
Validation
The API validates every imported document against the v1 Zod schema. On failure you get a 400 with a fieldErrors map keyed by JSON path (e.g. panels.2.layout.w) so it's obvious where the document broke. Unknown top-level fields are rejected — surface schema drift early instead of silently dropping it.
GitHub Action
The cpum-ai/cpum-ai dashboard-diff action diffs every changed dashboard JSON file in a pull request against its base branch, posts a panel-level summary as a PR comment, and fails the job when any file fails schema validation. Use cpum-ai/cpum-ai/actions/dashboard-diff@v1 to ride the latest patch automatically.
The action is self-contained — no cpumctl install required. It uses git show <base-sha>:<path> to read the previous version of each file, so the only prerequisite is a checkout with enough history ( fetch-depth: 0).
Copy-paste workflow — save as .github/workflows/dashboard-diff.yml
name: Dashboard diff
on:
pull_request:
paths:
- "dashboards/**/*.json"
jobs:
diff:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # needed to post the diff comment
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history so git show <base-sha>:<file> works
- name: cpum.ai dashboard diff
uses: cpum-ai/cpum-ai/actions/dashboard-diff@v1
with:
files: "dashboards/**/*.json" # glob relative to repo root
strict: "true" # fail the job on schema errors
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}| input | default | description |
|---|---|---|
| files | dashboards/**/*.json | Glob of dashboard JSON files to diff (relative to repo root). |
| base-ref | PR base SHA / HEAD~1 | Git ref to diff against. Auto-detected from the pull_request event payload. |
| strict | true | Fail the job when any dashboard fails Zod schema validation. |
| comment-on-pr | true | Post the panel-level diff as a PR comment. Requires pull-requests: write permission. |
Starter templates
Three ready-to-use dashboard JSON files live in the dashboards/ directory of the cpum-ai repo. Copy one into your project, edit the slug and title, then apply it:
CPU, memory, disk, and I/O wait — 4 stat tiles + 4 trend charts.
Open incidents, MTTA/MTTR KPIs, daily trend, and a recent-incidents table.
Full compliance table for every SLO across all services.
# Copy a starter template and apply it
curl -fsSL https://raw.githubusercontent.com/cpum-ai/cpum-ai/main/dashboards/starter-server-health.json \
-o dashboards/my-server-health.json
# Edit the slug, then push to cpum.ai:
cpumctl dashboards apply dashboards/my-server-health.jsonGet started
Open the cpum.ai dashboard, click Dashboards, then either build a new dashboard visually and click Export JSON, or paste an existing JSON document into Import JSON. The same endpoints power both.
Open dashboard