otel_histogram_percentile
Aggregate that merges OpenTelemetry histogram data points and extracts one or more percentiles from the merged result.
Combines otel_histogram_merge + percentile extraction in a single step. Works in both summarize and make-series. Input is a dynamic propertybag containing histogram fields (e.g. $raw). The percentile parameter defaults to 50 if omitted.
Temporality-aware (#3429): when the input rows carry
aggregation_temporality, CUMULATIVE histogram snapshots are
delta-converted before the percentile is computed. Series are detected
via metric_hash, so a group holding many series (the usual multi-pod
dashboard bin) is handled correctly: each series' first snapshot is
subtracted from its last, a restarted epoch (start_time change) counts
in full — mirroring otel_rate — and the per-series window deltas merge.
The result is the per-window distribution, so percentiles binned over
time vary per bin instead of freezing at the lifetime-to-date values.
DELTA rows, and inputs with no temporality fields (plain histogram
bags), merge directly as before.
A percentile the data does not define is null, which is KQL's value for
"no result" and what isnotnull filters (#4985). That covers an empty group,
a group mixing both temporalities, CUMULATIVE rows missing
timestamp/start_time, and a bin holding only one snapshot of a series — a
single lifetime snapshot defines no window, so keep bins at least two export
intervals wide (otel_sample_interval measures that interval). ADX reports
null for an undefined percentile too. Only the unmergeable cases also raise
an AggregateDegraded warning; a plain gap is silent.
For the lifetime-to-date distribution use otel_histogram_merge plus the
scalar otel_histogram_percentile.
Variadic form mirrors KQL's percentiles(col, P1, P2, ...): a single call
emits one column per requested percentile. Default column names follow
Microsoft Kusto: percentile_<col>_<p>. A single alias only renames the
first output; tuple assignment names every output explicitly. The plural
alias otel_histogram_percentiles is provided for parity with KQL.
| summarize otel_histogram_percentile($raw, 50, 95, 99) by bin(timestamp, 1m)
// → percentile___raw_50, percentile___raw_95, percentile___raw_99
| summarize (p50, p95, p99) = otel_histogram_percentile($raw, 50, 95, 99)
// → p50, p95, p99Over $raw this is itself an aggregate: use it directly as a
summarize/make-series output — never nested inside another aggregate such
as avg(...) or sum(...). The scalar form (over an already-merged histogram
from otel_histogram_merge) is the one place it appears outside summarize,
in a later extend.
(bzrk extension)
Syntax
otel_histogram_percentile(histogram)Parameters
Prop
Type
Returns: real
Syntax
otel_histogram_percentile(histogram, percentile)Parameters
Prop
Type
Returns: real
Syntax
otel_histogram_percentile(histogram, percentile)Parameters
Prop
Type
Returns: dynamic
Examples
Example 1
OtelMetrics
| where metric_type == "histogram"
| summarize p99 = otel_histogram_percentile($raw, 99) by bin(timestamp, 1h)| timestamp (datetime) | p99 (real) |
|---|---|
| 2024-01-01T00:00:00Z | 931.25 |
Example 2
OtelMetrics
| where metric_type == "histogram"
| summarize (p50, p95, p99) = otel_histogram_percentile($raw, 50, 95, 99)
by bin(timestamp, 1h)| timestamp (datetime) | p50 (real) | p95 (real) | p99 (real) |
|---|---|---|---|
| 2024-01-01T00:00:00Z | 73.61111111111111 | 736.25 | 931.25 |
Example 3
OtelMetrics
| where metric_type == "histogram"
| make-series p99 = otel_histogram_percentile($raw, 99) on timestamp
from datetime(2024-01-01) to datetime(2024-01-02) step 1h| p99 (dynamic) | timestamp (dynamic) |
|---|---|
| [931.25,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null] | [2024-01-01T00:00:00Z,2024-01-01T01:00:00Z,2024-01-01T02:00:00Z,2024-01-01T03:00:00Z,2024-01-01T04:00:00Z,2024-01-01T05:00:00Z,2024-01-01T06:00:00Z,2024-01-01T07:00:00Z,2024-01-01T08:00:00Z,2024-01-01T09:00:00Z,2024-01-01T10:00:00Z,2024-01-01T11:00:00Z,2024-01-01T12:00:00Z,2024-01-01T13:00:00Z,2024-01-01T14:00:00Z,2024-01-01T15:00:00Z,2024-01-01T16:00:00Z,2024-01-01T17:00:00Z,2024-01-01T18:00:00Z,2024-01-01T19:00:00Z,2024-01-01T20:00:00Z,2024-01-01T21:00:00Z,2024-01-01T22:00:00Z,2024-01-01T23:00:00Z] |