#[non_exhaustive]pub struct Histogram {
pub schema: i8,
pub zero_threshold: f64,
pub zero_count: f64,
pub count: f64,
pub sum: f64,
pub positive: Vec<Bucket>,
pub negative: Vec<Bucket>,
pub custom_values: Vec<f64>,
pub reset_hint: ResetHint,
}Expand description
A distribution captured as one sample.
See the module documentation for the model and the two representation decisions.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.schema: i8Bucket resolution — see CUSTOM_BUCKETS_SCHEMA, MIN_SCHEMA, MAX_SCHEMA.
zero_threshold: f64Half-width of the zero bucket, which covers [-t, +t] inclusive.
zero_count: f64Observations in the zero bucket.
count: f64Total observations, including the zero bucket.
sum: f64Sum of all observations. May be NaN if any observation was.
positive: Vec<Bucket>Buckets for positive observations, ascending by index, none zero.
negative: Vec<Bucket>Buckets for negative observations, ascending by index, none zero.
Index i covers [-base^i, -base^(i-1)) — the mirror of the positive
side, so larger indices are more negative.
custom_values: Vec<f64>Upper-inclusive boundaries, when schema == CUSTOM_BUCKETS_SCHEMA.
Ascending. Bucket i of positive covers
(custom_values[i-1], custom_values[i]], with -Inf below the first
and +Inf above the last.
reset_hint: ResetHintWhat is known about counter resets before this sample.
Implementations§
Source§impl Histogram
impl Histogram
Sourcepub const fn has_custom_buckets(&self) -> bool
pub const fn has_custom_buckets(&self) -> bool
Whether the boundaries are listed rather than computed.
Sourcepub fn base(schema: i8) -> f64
pub fn base(schema: i8) -> f64
The growth factor between consecutive exponential bucket bounds.
2^(2^-schema). Meaningless for CUSTOM_BUCKETS_SCHEMA.
Sourcepub fn index_for(schema: i8, value: f64) -> i32
pub fn index_for(schema: i8, value: f64) -> i32
The index of the bucket an observation falls in.
From the specification’s boundary rule — bucket i covers
(base^(i-1), base^i] — inverted: i = ⌈log₂(v) · 2^schema⌉.
value must be finite and strictly positive; callers route zero and
near-zero observations to the zero bucket first.
Sourcepub fn bucket_bounds(&self, index: i32, negative: bool) -> (f64, f64)
pub fn bucket_bounds(&self, index: i32, negative: bool) -> (f64, f64)
The (lower, upper) bounds of a bucket, lower exclusive, upper inclusive.
For the negative side, pass negative = true: index i then covers
[-base^i, -base^(i-1)).
Sourcepub fn bound(schema: i8, index: i32) -> f64
pub fn bound(schema: i8, index: i32) -> f64
The upper bound of bucket index: 2^(index / 2^schema).
Computed without a transcendental, which is the point. powf and
powi are not correctly rounded and their last bit is not specified by
IEEE 754 or by Rust, so the same stored histogram could report
different boundaries on two machines — and a bucket boundary is a
storage-format semantic, not a display detail. It showed up as
bucket_bounds(0) returning 0.4999999999999999 instead of 0.5 at
schema 0, where the answer is an exact power of two.
Instead, index is split as index = q · 2^schema + r, giving
2^q · 2^(r / 2^schema). The first factor is built straight from the
IEEE exponent field, and the second from repeated sqrt — the one
root operation IEEE 754 does require to be correctly rounded. Every
step is exact or correctly rounded, so the result is identical on
every platform.
Sourcepub fn observe(&mut self, value: f64)
pub fn observe(&mut self, value: f64)
Record one observation.
Present so a histogram can be built in a test or by a connector that receives raw values; ingest from Prometheus or OTLP builds the buckets directly.
Sourcepub fn canonicalise(&mut self)
pub fn canonicalise(&mut self)
Put the histogram in canonical form: sorted by index, no empty buckets.
Merges duplicate indices rather than dropping one, because a wire decoder that produced two entries for one bucket meant their sum.
Sourcepub fn validate(&self) -> Result<(), HistogramError>
pub fn validate(&self) -> Result<(), HistogramError>
Check every invariant the rest of the engine relies on.
§Errors
See HistogramError. The checks are the ones whose violation would
produce a plausible wrong number rather than a crash: an unsorted
bucket list interpolates to the wrong quantile, and a count smaller
than its buckets makes every rank fraction exceed one.
Sourcepub fn variance(&self) -> f64
pub fn variance(&self) -> f64
Variance of the observations, estimated from bucket representatives.
Sourcepub fn quantile(&self, q: f64) -> f64
pub fn quantile(&self, q: f64) -> f64
The φ-quantile of the observations.
Follows Prometheus’s histogramQuantile: q < 0 is -Inf, q > 1 is
+Inf, and an empty histogram or a NaN φ is NaN. The value is
found by walking buckets in ascending order until the cumulative count
reaches q · count, then interpolating inside that bucket.
Sourcepub fn fraction(&self, lower: f64, upper: f64) -> f64
pub fn fraction(&self, lower: f64, upper: f64) -> f64
The fraction of observations in [lower, upper).
NaN for an empty histogram or a NaN bound; 0 when the interval is
empty or inverted.
Sourcepub fn classic_buckets(&self) -> Vec<(f64, f64)>
pub fn classic_buckets(&self) -> Vec<(f64, f64)>
The classic le-bucketed view of this histogram.
Returns (le, cumulative_count) pairs ascending, ending at +Inf.
This is what makes a dashboard written against foo_bucket keep
working once the storage holds a native histogram — the classic
exposition is a view, not a second stored form, which is also
upstream’s direction for composite samples.
Sourcepub fn merge(&mut self, other: &Self) -> Result<(), HistogramError>
pub fn merge(&mut self, other: &Self) -> Result<(), HistogramError>
Add other into self.
Defined only for histograms that share a schema and zero threshold —
two different resolutions cannot be added without re-bucketing, and
re-bucketing to the coarser of the two is a decision rather than
something to do silently inside +.
§Errors
HistogramError::CustomValues when the schemas or boundaries differ.