Skip to content

Commit 2adaf96

Browse files
authored
Merge pull request #2742 from prometheus/beorn7/histogram
spec: Be explicit about invalidity of negative histograms
2 parents 5a0b8f8 + 96abc12 commit 2adaf96

File tree

1 file changed

+36
-19
lines changed

1 file changed

+36
-19
lines changed

docs/specs/native_histograms.md

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,13 @@ implementation.
157157
### General structure
158158

159159
Similar to a classic histogram, a native histogram has a field for the _count_
160-
of observations and a field for the _sum_ of observations. In addition, it
161-
contains the following components, which are described in detail in dedicated
162-
sections below:
160+
of observations and a field for the _sum_ of observations. While the count of
161+
observation is generally non-negative (with the only exception being
162+
[intermediate results in PromQL](#unary-minus-and-negative-histograms)), the
163+
sum of observations might have any float64 value.
164+
165+
In addition, a native histogram contains the following components, which are
166+
described in detail in dedicated sections below:
163167

164168
- A _schema_ to identify the method of determining the boundaries of any given
165169
bucket with an index _i_.
@@ -204,6 +208,13 @@ that the most common PromQL function applied to a counter histogram is `rate`,
204208
which generally produces non-integer numbers, so that results of recording
205209
rules will commonly be float histograms with non-integer values anyway.
206210

211+
PromQL expression may even create “negative” histograms (e.g. by multiplying a
212+
histogram with -1). Those negative histograms are only allowed as intermediate
213+
results and are otherwise considered invalid. They cannot be represented in any
214+
of the exchange formats (exposition formats, remote-write, OTLP) and they
215+
cannot be stored in the TSDB. Also see the [detailed section about negative
216+
histograms](#unary-minus-and-negative-histograms).
217+
207218
Treating native histograms explicitly as integer histograms vs. float histogram
208219
is a notable deviation from the treatment of conventional simple numeric
209220
samples, which are always treated as floats throughout the whole stack for the
@@ -351,13 +362,16 @@ positive bucket list is used, but repurposed for all buckets.
351362
Any unpopulated buckets MAY be excluded from the lists. (Which is the reason
352363
why the buckets are often called _sparse buckets_.)
353364

354-
For float histograms, the elements of the lists are float64 and
355-
represent the bucket population directly.
365+
For float histograms, the elements of the lists are float64 and represent the
366+
bucket population directly. Bucket populations are generally non-negative, with
367+
the only exception being [intermediate results in
368+
PromQL](#unary-minus-and-negative-histograms).
356369

357370
For integer histograms, the elements of the lists are signed 64-bit integers
358371
(short: int64), and each element represents the bucket population as a delta to
359372
the previous bucket in the list. The first bucket in each list contains an
360-
absolute population (which can also be seen as a delta relative to zero).
373+
absolute population (which can also be seen as a delta relative to zero). The
374+
deltas MUST NOT evalute to a negative absolute bucket population.
361375

362376
To map buckets in the lists to the indices as defined in the previous section,
363377
there are two lists of so-called _spans_, one for the positive buckets and one
@@ -431,7 +445,8 @@ standard schemas above. They are counted in a dedicated bucket called the _zero
431445
bucket_.
432446

433447
The number of observations in the zero bucket is tracked by a single uint64
434-
(for integer histograms) or float64 (for float histograms).
448+
(for integer histograms) or float64 (for float histograms). As for regular
449+
buckets, this number is generally non-negative.
435450

436451
The zero bucket has an additional parameter called the _zero threshold_, which
437452
is a float64 ≥ 0. If the threshold is set to zero, only observations of exactly
@@ -1775,8 +1790,10 @@ explicit counter reset detection will be thrown off by the inverted sign.
17751790
Generally, histograms with negative bucket populations or a negative count of
17761791
observations do not really make sense on their own and are only supposed to act
17771792
as intermediate results inside other expressions. They are always considered
1778-
gauge histograms within PromQL and when stored as the result of a recording
1779-
rule.
1793+
gauge histograms within PromQL. They cannot be persisted as a result of a
1794+
recording rule. (A rule evaluating to a negative histogram results in an
1795+
error.) It is impossible to represent negative histograms in any of the
1796+
exchange formats (exposition formats, remote-write, OTLP).
17801797

17811798
### Binary operators
17821799

@@ -2299,27 +2316,27 @@ Example for the text representation of a float histogram:
22992316
{count:3493.3, sum:2.349209324e+06, [-22.62741699796952,-16):1000, [-16,-11.31370849898476):123400, [-4,-2.82842712474619):3, [-2.82842712474619,-2):3.1, [-0.01,0.01]:5.5, (0.35355339059327373,0.5]:1, (1,1.414213562373095]:3.3, (1.414213562373095,2]:4.2, (2,2.82842712474619]:0.1}
23002317
```
23012318

2302-
## Remote write & read
2319+
## Remote-write & remote-read
23032320

2304-
The [protobuf specs for remote write &
2305-
read](https://github.com/prometheus/prometheus/blob/main/prompb) were extended
2306-
for native histograms as an experimental feature. Receivers not capable of
2307-
processing native histograms will simply ignore the newly added fields.
2308-
Nevertheless, Prometheus has to be configured to send native histograms via
2309-
remote write (by setting the `send_native_histograms` remote write config
2321+
The [protobuf specs for remote-write &
2322+
remote-read](https://github.com/prometheus/prometheus/blob/main/prompb) were
2323+
extended for native histograms as an experimental feature. Receivers not
2324+
capable of processing native histograms will simply ignore the newly added
2325+
fields. Nevertheless, Prometheus has to be configured to send native histograms
2326+
via remote-write (by setting the `send_native_histograms` remote-write config
23102327
setting to true).
23112328

2312-
In [remote write v2](https://prometheus.io/docs/specs/remote_write_spec_2_0/),
2329+
In [remote-write v2](https://prometheus.io/docs/specs/remote_write_spec_2_0/),
23132330
native histograms are a stable feature.
23142331

23152332
It might appear tempting to convert classic histograms to NHCBs while sending
23162333
or receiving them. However, this does not overcome the known consistency
2317-
problems classic histograms suffer from when transmitted via remote write.
2334+
problems classic histograms suffer from when transmitted via remote-write.
23182335
Instead, classic histograms SHOULD be converted to NHCBs during scraping.
23192336
Similarly, explicit OTel histograms SHOULD be converted to NHCBs during [OTLP
23202337
ingestion](#otlp) already.
23212338

2322-
TODO: A remaining possible problem with remote write is what to do if multiple
2339+
TODO: A remaining possible problem with remote-write is what to do if multiple
23232340
exemplars originally ingested for the same native histogram are sent in
23242341
different remote-write requests.
23252342

0 commit comments

Comments
 (0)