Documentation menu
Query basics
Choose a query form, use IntelliSense, and filter, aggregate, and group metrics.
MetricQL is shared by Metrics Explorer, dashboard query series, saved queries, and health-rule conditions. Choose one of two forms:
- Metric selectors select a metric, filter its dimensions, and aggregate samples. Use these for a single measurement, counter rates, learned baselines, or arithmetic between metrics.
- Source pipelines start with
from, select several named measurements, correlate sources with explicit joins, and calculate outputs. Use these when you need CPU and memory together, or want to relate a process to its host.
metric_name{key="value", key2=~"regex"} | avg by (dim1, dim2)
Every part shown above is optional on its own, but a query needs at least a
metric name, a label matcher, or both; there is no query that matches
literally everything by accident. Two such queries can be combined with
+ - * /, covered in Arithmetic between queries
in that guide.
The source form makes the source and output name explicit:
from tests
| where target = "api.example.com"
| summarize p95(http_check_total_ms) as latency by agent_id
from tests accepts the same full metric names as metric selectors, across
check types and storage sources. latency is a result alias, not a new stored
metric. Source-local field names
such as cpu_percent belong inside their source’s summarize calls; a bare
metric selector uses the global name, such as host_process_cpu_percent.
Source pipelines use this stage order:
from SOURCE
[ | where DIM OP VALUE [and DIM OP VALUE ...] ]
| summarize AGG(FIELD) as ALIAS [, AGG(FIELD) as ALIAS ...]
[by DIM [, DIM ...]]
[ | join left|inner (SOURCE_QUERY) as NAME on (DIM [, DIM ...]) ... ]
[ | extend ALIAS = EXPRESSION [, ALIAS = EXPRESSION ...] ... ]
[ | order by ALIAS_OR_GROUP_DIMENSION [asc|desc] [ | limit INTEGER ] ]
Square brackets indicate optional syntax. Sources are tests, host_resources,
containers, kubernetes, and custom. Combine where predicates with and;
operators are =, !=, =~, !~, in, and not in. Values are quoted
strings (set operators take a parenthesized list of strings) or bare true and
false. Each measurement requires an as alias. For alert conditions, finish
with | pick ALIAS instead of ordering or limiting.
See Source pipelines for field selection,
grouping and limits, and Joins and calculations
for correlation and calculated outputs. AI and MCP clients can retrieve these
with get_query_language_spec(topic="sources") and
get_query_language_spec(topic="joins"); use get_metrics_catalog(view="sources")
to discover source fields and units, then validate_query before execution.
Writing queries with IntelliSense
The Explorer, dashboard Query language series, and individual alert
conditions share the same completion engine. Press Ctrl+Space to open
suggestions, use the arrow keys to select, Enter to accept, and Escape to
dismiss. Suggestions also open as you type and continue into the arguments
after you accept a stage or operator. In Explorer, Ctrl+Enter runs the query
(Cmd+Enter on macOS).
Start typing a metric name, or choose from and then a source. Source fields
show their measurement kind and unit, with descriptions where the catalog
provides them. After a filter key, choose an equality, regex, or set operator;
value suggestions include recent dimension values and your tenant’s current
agent and test names, shown alongside their IDs. Choose a name in an agent_id
or test_id filter to insert its stable ID, or in agent.name or test.name
to insert its name. At the start of a filter, an entity suggestion inserts a
complete ID filter. These names identify agents and test definitions (individual
checks); use test.group_id to filter the containing test group. Source
queries also offer the fixed resource_kind and monitored values. Quoted
values are escaped when inserted.
After summarize, suggestions guide aggregation functions, their source’s
fields, as, and grouping dimensions. Choose your own output alias after
as. Later stages offer those aliases, including qualified joined outputs
such as host.used, in calculations, ordering, and pick. Ordering also offers
retained grouping dimensions, such as agent.name or test_type; pick always
selects a numeric output. Join-key suggestions
come from the left grouping; the right query must group by exactly those keys.
Metric selectors offer counter conversions, valid second stages, baseline
profiles and statistics, and arithmetic operands. Second-stage grouping offers
only dimensions retained by the first aggregation. Dashboard variables appear
after ${ when the dashboard defines them.
Completion is an editing aid. Custom metric names and dimension values may be valid even when they have not been discovered yet; type them directly. An empty value menu does not mean the dimension is invalid or the metric is zero. Likewise, a configured test or agent appearing in suggestions does not prove that it has measurements in the selected time range. The server validates syntax, units, grouping, permissions, and query limits when the query runs.
Selector
The selector is the part before any |: an optional bare metric name,
followed by an optional {...} block of matchers.
http_check_total_ms
selects one metric name and every dimension it carries. Leave the name off and
filter by matchers instead to compare several metrics at once, typically
combined with by (metric_name) so they render as separate series rather than
one blended line:
{test_type="http_check"}
Both can be combined: a metric name narrows to that metric, and the matchers narrow further.
http_check_total_ms{target=~"api-.*"}
Matchers
A matcher is key, an operator, and a double-quoted string. Several matchers
inside one {...} block are joined with AND; there is no OR inside a
selector; run two queries instead.
| Operator | Meaning |
|---|---|
key="value" |
Exactly equal |
key!="value" |
Not equal |
key=~"regex" |
Matches a regular expression |
key!~"regex" |
Does not match a regular expression |
key in ("a", "b") |
Exactly equal to any value in the list |
key not in ("a", "b") |
Exactly equal to none of the values in the list |
key is any queryable dimension, see Dimensions
for the full list, which spans the record’s own identity, context the platform
stamps on every row, entity facts resolved after the fact, and your own
labels, promoted or not.
Regular expressions use RE2 (no backreferences or lookaround). Matching is
unanchored: use ^api-.*$ for a full-value match beginning with api-, or
api- to find that text anywhere in the value.
Values may contain a literal quote or backslash by escaping it:
{target="a\"b"}
Prefer in (...) over a regex alternation when you mean a fixed set of exact
values. target=~"a.example|b.example" treats each . as a wildcard and
matches axexample too, while target in ("a.example", "b.example") matches
exactly those two, and compiles to a plain set lookup rather than a regex
scan over every row. The list needs at least one value; in () is a syntax
error, on the assumption that it is a half-typed query rather than a
deliberate empty set.
Aggregation and grouping
An optional | stage follows the selector. Leaving it off is not the same as
skipping aggregation; it defaults to avg across everything the selector
matched, collapsed to one series.
http_check_total_ms{target=~"api-.*"}
is exactly
http_check_total_ms{target=~"api-.*"} | avg
The sample aggregations are:
| Aggregation | Answers |
|---|---|
avg |
The typical value across matching samples |
min |
The best case in the window |
max |
The worst case in the window, the one that matters for anything you’d page on |
sum |
The total across matching samples, for things meant to be added (bytes, counts) |
count |
How many samples landed in the window, independent of their value |
p50 |
The median sample, what a typical request saw, unmoved by a few outliers |
p90, p95, p99 |
The tail: the value 90/95/99% of samples stayed under. For latency this is the number that matters; a steady avg over a doubling p95 is the outage a mean hides, and max alone is too jumpy to read |
Each aggregation is computed per chart bucket over the raw samples that landed
in it, so a percentile here is a percentile of individual measurements, not of
some pre-averaged intermediate. Percentiles are approximate (ClickHouse’s
sampling quantile); the error is far smaller than a chart pixel.
by (...) splits the aggregation into one series per distinct combination of
the named dimensions, instead of collapsing everything into one line. Any
queryable dimension can appear here, including metric_name itself, useful
when the selector has no bare metric name and matches several:
{test_type="http_check"} | avg by (metric_name)
Group by more than one dimension to keep series distinct along more than one axis at once:
{region="us-east"} | max by (metric_name, target)
Repeating a key in by (...) has no extra effect; duplicates collapse to
one.