Berserk Docs
Aggregate FunctionsPercentile & Sketch

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, p99

Over $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:00Z931.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:00Z73.61111111111111736.25931.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]

On this page