Dashboard Spec
The full Perses-compatible dashboard file format Everr validates and renders.
A dashboard file is a Perses-style resource with three top-level keys. Everr validates it on everr apply and again on read; the whole document is stored verbatim, so unknown Perses fields (at the top level or inside spec) survive a read/apply round-trip unchanged. (The folder path is the one piece of state kept outside the document: it's derived from the file's directory, not declared in the file.)
kind: Dashboard
metadata:
name: <slug>
project: platform # optional; defaults to "default"
spec:
{ ... }| Key | Type | Notes |
|---|---|---|
kind | "Dashboard" | Selects the reconciler. Required. |
metadata.name | string | The slug: identity within its project, and the URL segment. Set it explicitly; the file is named <slug>.dashboard.yaml to match. See Slug rules. |
metadata.project | string | Groups dashboards into a named set. Optional; defaults to default. Identity is project + slug, so two projects can share the same slug without colliding. |
spec | object | The dashboard contents, below. |
spec
| Field | Type | Required | Notes |
|---|---|---|---|
panels | map<string, Panel> | yes | Panel key → panel. Keys are referenced by layouts. |
layouts | [Grid] | yes | Placement of panels on the grid. |
display | Display | no | Dashboard title / description. |
variables | [Variable] | no | Template variables. |
timeRange | { from: string, to: string } | no | Default range in Everr date math, for example { from: now/M, to: now }. Seeds the time range. |
duration | string | no | Perses compatibility input, for example 1h or 24h. Everr normalizes it to timeRange when timeRange is absent. |
refreshInterval | string | no | Default auto-refresh (e.g. 30s, 1m). |
datasources | map<string, object> | no | Accepted for Perses compatibility; no runtime effect. |
Display
display:
name: API Latency # optional
description: ... # optionalPanel
<panel-key>:
kind: Panel
spec:
display: { name: ..., description: ... } # description optional
plugin:
kind: TimeSeriesChart | Table | StatChart
spec: { ... } # see Visualizations reference
queries: # optional
- kind: ClickHouseSQL
spec:
plugin:
kind: ClickHouseSQL
spec:
query: "SELECT ..."| Field | Type | Notes |
|---|---|---|
kind | "Panel" | Required. |
spec.display | Display | name shown as the panel title. |
spec.plugin.kind | string | Visualization kind. See Visualizations. |
spec.plugin.spec | object | Visualization options. |
spec.queries | [PanelQuery] | Optional list. Each query's SQL is at spec.plugin.spec.query; query kind is ClickHouseSQL. |
Query parameters
Every dashboard query (panel queries and variable options queries alike) is run with these ClickHouse parameters bound. They are always provided (referencing them never errors, and unreferenced parameters are ignored), but they are not injected into the SQL: the query must reference them. Usage guide: Time range parameters.
| Parameter | Value |
|---|---|
{from:String} / {to:String} | The dashboard's selected time range, as UTC datetimes in YYYY-MM-DD HH:MM:SS form. The start rounds down and the end rounds up to a whole second, so a DateTime column such as TimeUnix and a DateTime64 column such as Timestamp both accept a direct comparison. |
{step:UInt32} | Adaptive bucket width in seconds: the range divided by a ~500-point budget, snapped up to the next clock-aligned width: 1/2/5/10/15/20/30s, 1/2/5/10/15/30m, 1/2/3/6/12h, 1d, then whole days. |
Grid layout
layouts:
- kind: Grid
spec:
display: { title: ..., collapse: { open: true } } # optional
items:
- x: 0
y: 0
width: 12
height: 8
content: { $ref: "#/spec/panels/<panel-key>" }| Field | Type | Notes |
|---|---|---|
kind | "Grid" | Required. |
spec.items[].x / .y | number | Cell position. The grid is 24 columns wide. |
spec.items[].width / .height | number | Cell span. |
spec.items[].content.$ref | string | #/spec/panels/<panel-key>. A panel renders only if referenced here. |
Variables
A discriminated union on kind. Full guide: Variables.
TextVariable:
- kind: TextVariable
spec:
name: search
value: ""
display: { name: Search, hidden: false } # optional
constant: false # optionalListVariable:
- kind: ListVariable
spec:
name: service
display: { name: Service, hidden: false } # optional
defaultValue: "" # string, or [..] when allowMultiple (optional)
allowMultiple: false # optional
allowAllValue: false # optional
customAllValue: "" # optional; substituted when "All" is selected
sort: none # optional; see below
capturingRegexp: "" # optional; accepted, no runtime effect
plugin:
kind: StaticListVariable | ClickHouseSQLVariable
spec:
values: [a, b] # StaticListVariable
# query: "SELECT ..." # ClickHouseSQLVariable (first column = options)sort accepts: none, alphabetical-asc, alphabetical-desc, numerical-asc, numerical-desc, alphabetical-ci-asc, alphabetical-ci-desc.
Slug rules
The slug (from metadata.name; set it explicitly under the <slug>.dashboard.yaml naming convention) must:
- use only lowercase letters, digits, and hyphens,
- not start or end with a hyphen,
- be 1 to 200 characters.
A slug must be unique within a project; applying two files that resolve to the same slug within the same project fails.
Time defaults
Use timeRange for a dashboard's default range:
timeRange:
from: now/M
to: nowEverr date math supports fixed windows such as now-24h and calendar-aligned ranges such as now/M (the start of this month). Everr seeds missing URL time-range parameters from timeRange and refreshInterval. Explicit URL parameters always win, so shared links keep their exact range.
Perses dashboards that declare duration are still accepted. At the resource boundary, Everr converts duration: 24h to { from: now-24h, to: now }. If both fields are present, timeRange wins. Everr-authored dashboards should use timeRange.
Compatibility boundaries
The format mirrors Perses so files stay portable, but a few fields are accepted without runtime behavior in Everr today: datasources, variable capturingRegexp, and variable chaining/aliases (see Variables → Not supported). The only query plugin executed is ClickHouseSQL.