Queries as Code#
Monitoring queries are authored once as YAML under packages/queries/, validated against a project-owned JSONSchema,
and rendered per backend query language.
A query is written for PromQL first; the other engines are translations of the same definition, carried in the same entry.
The audience for this section is repo contributors — the people adding a panel, an alert, or a metric to the registry. The audience for the rendered queries is the operator reading a dashboard, so the descriptions attached to each query are end-user voice; see Dashboard Style Guidelines for that.
In this section#
- Authoring Alerts — how an
alerts:entry becomes an installed Prometheus rule: the alerting context, capabilities, the default set, and whatgen-rulesrejects. - Authoring Recording Rules — how a
rules:entry becomes a recorded series: the naming convention, the normalizedext:*contract, and the install-time facts its adapters need. - Datadog Translations — the PromQL→Datadog mapping, the OTLP naming assumptions it rests on, and the gaps where Datadog’s language cannot express what the PromQL does.
Where things live#
| Sources | packages/queries/*.yaml — one registry per file |
| Schema | packages/mzmon-lib/schemas/query/mzmon-query.schema.yaml |
| Loader | packages/mzmon-lib/src/query/ — model, rendering, metric extraction, metric tiers |
The loader is deliberately lenient; structural strictness is the schema validator’s job.
The check-queries pre-commit hook runs it on every changed query file:
bin/mz-monitoring-check check-queries packages/queries/materialize-compute.yamlWhat a registry file holds#
Each file carries a description, a metricImportanceHint, and at least one of four content branches — queries,
rules (recording rules), alerts, or metricOverrides.
Alerts and recording rules reference a query either by queryId or by defining one inline, which is then promoted to a
top-level registry entry at load time.
Every query carries a stability level, and that level is a contract: changes to canonical and best-effort queries
are breaking changes, and both must be deprecated before removal.
experimental and playground queries can be removed outright.
The engines#
A query’s expression fields are the per-engine translations.
promQL is the source of truth; the rest are rendered from the same registry entry.
| Field | Engine | Notes |
|---|---|---|
promQL | Prometheus | The canonical form. Metric extraction and metric tiers parse this and only this. |
datadogQuery | Datadog | Metric query syntax, not DDSQL. See Datadog Translations. |
honeycombSQL | Honeycomb | Not yet populated. |
logQL | Loki | Log queries rather than metric queries. |
promQL and datadogQuery accept either one expression or a list of them, where a list means several distinct series on one panel.
Templating#
Expressions are templates, not literals.
%%{param} placeholders are filled by a TemplateContext, which supplies both the parameter values and the template
functions (orZero, mzClusterName, mzObjectName) — so the same registry entry renders differently per engine.
The parameter names are shared across engines; the values are not.
A PromQL context supplies label matchers (mzEnvironmentFilter → materialize_cloud_organization_name=~"…"), a
Datadog context supplies tag matchers (materialize_cloud_organization_name:…).
The permitted parameter names are an enum in the schema (knownParameter), and check-queries checks every %%{…}
against it, so a typo fails validation rather than rendering an empty string.
Every one of them must be implemented by the dashboard and extraction contexts, which a test reads from the schema to
enforce. The alerting context implements a subset on purpose; see Authoring Alerts.
Consumers#
Adding or changing a query has effects beyond the query itself:
Grafana dashboards take both their PromQL and their panel descriptions from the registry, through
mz_dashboards::grafana::queries— see Dashboards → SDKs and Schemas. A panel names a query id and gets the pair; nothing about a query is restated in the dashboard, so a change here reaches the rendered dashboards on the nextmake dashboards.Metric extraction (
mz-monitoring-build extract-metrics) parses the PromQL to derive the metric set, which lands indocs/assets/metrics/metrics.yamland backs Reference Metrics.Metric tiers (
mz-monitoring-build gen-metric-tiers) roll each query’sstabilityand importance up into the per-destination allowlists incharts/materialize-monitoring/pre-rendered/metrics/metric-tiers.yaml. This is why a new query can change what a deployment ships to a metered backend.A query is the only way a metric reaches a tier. The tiers are built by walking the registry’s queries, so
metricOverridesre-weights a metric some query already references and cannot introduce one — however many patterns match it. A family worth keeping therefore has to be named by a query even when no dashboard draws it.infra-loki.yamlonce carried six such queries for the Alloy-sideloki_*components; they moved toinfra-alloy.yamlwhen a dashboard came to draw them.The converse also holds, because tiers select by metric name. A query naming a generic family such as
go_goroutinesadmits every target’s copy of it, not only the copy the query was written for, which is whyinfra-alloy.yamlholds its Go runtime families atextended.Alerting and recording rules (
mz-monitoring-build gen-rules) render everyalerts:andrules:entry intocharts/materialize-monitoring/pre-rendered/rules/, which the chart installs asPrometheusRuleresources. A rule’s query renders through its own context and is held to stricter checks than a panel’s; see Authoring Alerts and Authoring Recording Rules.The docs read
packages/queries/directly: Hugo mounts it atassets/queries/, and thelist-queriesshortcode renders Common Queries from it. There is no generated intermediate to refresh.
Both generated outputs declare packages/queries/*.yaml as a prerequisite, so make metrics rebuilds them after a query change.
Note that make all covers only the metric tiers — the metrics.yaml docs asset is not in the synced chain, so run
make metrics when you have changed which metrics a query names.