Skip to main content

MeasurementHistogram

Struct MeasurementHistogram 

Source
pub struct MeasurementHistogram<const N: usize> { /* private fields */ }
Expand description

Canonical shared arithmetic for local diagnostic summaries and distributions.

Re-exported so callers can name returned summaries without selecting a separate Metrics dependency. This is the shared type, with no local wrapper or arithmetic. Fixed-size histogram of observations in one consumer-selected unit.

N strictly increasing inclusive upper bounds define N disjoint buckets. The first bucket includes zero; later buckets exclude the preceding bound. Values above the last bound go into a separate overflow bucket. With no bounds, every observation goes into overflow. A final bound of u64::MAX is valid and leaves overflow empty.

Each observation updates one bucket and the accompanying MeasurementAggregate. Counts clip independently at u64::MAX, with sticky flags for actual overflow; exactly reached caps remain exact. Unsaturated bucket counts remain useful after the aggregate’s total overflows. Overflow can prevent bucket counts from summing to the aggregate’s sample count. Buckets describe ranges, not exact percentiles; no latest value is retained.

Storage is fixed arrays, overflow state and one aggregate, with no heap allocation. Recording searches at most N bounds. Consumers choose bounds, units, sample admission, identity and reset boundaries. Bounds are immutable after construction; report encoding and persistence remain consumer-owned.

use ic_metrics::MeasurementHistogram;

let mut histogram = MeasurementHistogram::new([10, 100])?;
for value in [0, 10, 11, 101] {
    histogram.record(value);
}
assert_eq!(histogram.bucket_counts(), &[2, 1]);
assert_eq!(histogram.overflow(), 1);
assert_eq!(histogram.aggregate().samples(), 4);

Implementations§

Source§

impl<const N: usize> MeasurementHistogram<N>

Source

pub const fn new( upper_bounds: [u64; N], ) -> Result<MeasurementHistogram<N>, HistogramBoundsError>

Construct an empty histogram with inclusive upper bounds.

Bounds and observations must use the same unit. A bound of zero and an empty bounds array are valid.

§Errors

Returns HistogramBoundsError for the first duplicate or descending bound. The error identifies the right-hand bound in that pair.

Source

pub const fn record(&mut self, value: u64)

Record one completed observation, including zero.

Updates the aggregate and exactly one disjoint bucket. Every observation must use the same unit as the bounds and earlier observations.

Source

pub const fn upper_bounds(&self) -> &[u64; N]

Immutable inclusive upper bounds corresponding to Self::bucket_counts.

Source

pub const fn bucket_counts(&self) -> &[u64; N]

Disjoint bucket counts, each saturating independently at u64::MAX.

These exclude overflow and are not cumulative counts. Inspect Self::bucket_saturation before using clipped counts as exact values.

Source

pub const fn overflow(&self) -> u64

Count above the last bound, saturating independently at u64::MAX.

With no bounds, this counts all observations. Inspect Self::overflow_saturated before treating the clipped count as exact.

Source

pub const fn bucket_saturation(&self) -> &[bool; N]

Sticky actual-overflow flags corresponding to Self::bucket_counts.

Source

pub const fn overflow_saturated(&self) -> bool

Whether the overflow bucket’s count has actually overflowed.

Source

pub const fn aggregate(&self) -> MeasurementAggregate

Mergeable aggregate of all observations, including overflow.

Source

pub const fn merge( &mut self, other: &MeasurementHistogram<N>, ) -> Result<(), HistogramMergeError>

Combine a distribution with exactly the same finite bounds.

Consumers establish matching units and deliberate sample attribution. This adds observations without deduplication or ordering. Source overflow propagates independently for each count and the aggregate.

§Errors

Returns HistogramMergeError for the first differing bound, leaving the entire destination unchanged. Different bound counts are different Rust types and cannot be merged.

Source

pub const fn cumulative_count( &self, index: usize, ) -> Result<u64, HistogramQueryError>

Count observations at or below the finite upper bound at index.

Sums disjoint buckets through that index, excluding overflow. Empty histograms return zero for valid indices. Later buckets, overflow and aggregate saturation do not invalidate an otherwise exact prefix count. Arbitrary thresholds inside a bucket cannot be answered exactly.

§Errors

Returns HistogramQueryError::BucketOutOfBounds when index >= N, or HistogramQueryError::SaturatedCount when a contributing count or sum has actually overflowed; an exactly reached u64::MAX is valid.

Source

pub const fn quantile_bucket( &self, numerator: u64, denominator: u64, ) -> Result<Option<HistogramRange>, HistogramQueryError>

Locate the bucket containing the nearest-rank quantile numerator / denominator.

The one-based rank is ceil(samples * numerator / denominator), with 0 < numerator <= denominator. Returns None for no observations and otherwise a range, including overflow. It never interpolates an exact percentile value. Recording and retained state are unchanged.

§Errors

Returns HistogramQueryError::InvalidQuantile first for an invalid fraction, or HistogramQueryError::SaturatedCount if the sample count or any bucket count has actually overflowed. A saturated value total does not invalidate a distribution whose counts remain exact.

use ic_metrics::MeasurementHistogram;
let mut histogram = MeasurementHistogram::new([10, 100])?;
for value in [0, 10, 11, 101] { histogram.record(value); }
assert_eq!(histogram.cumulative_count(0)?, 2);
let median = histogram.quantile_bucket(1, 2)?.unwrap();
assert_eq!(median.upper_inclusive(), Some(10));
assert_eq!(histogram.quantile_bucket(95, 100)?.unwrap().upper_inclusive(), None);

Trait Implementations§

Source§

impl<const N: usize> Clone for MeasurementHistogram<N>

Source§

fn clone(&self) -> MeasurementHistogram<N>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<const N: usize> Copy for MeasurementHistogram<N>

Source§

impl<const N: usize> Debug for MeasurementHistogram<N>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<const N: usize> Eq for MeasurementHistogram<N>

Source§

impl<const N: usize> PartialEq for MeasurementHistogram<N>

Source§

fn eq(&self, other: &MeasurementHistogram<N>) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<const N: usize> StructuralPartialEq for MeasurementHistogram<N>

Auto Trait Implementations§

§

impl<const N: usize> Freeze for MeasurementHistogram<N>
where [u64; N]: Freeze, [bool; N]: Freeze,

§

impl<const N: usize> RefUnwindSafe for MeasurementHistogram<N>

§

impl<const N: usize> Send for MeasurementHistogram<N>
where [u64; N]: Send, [bool; N]: Send,

§

impl<const N: usize> Sync for MeasurementHistogram<N>
where [u64; N]: Sync, [bool; N]: Sync,

§

impl<const N: usize> Unpin for MeasurementHistogram<N>
where [u64; N]: Unpin, [bool; N]: Unpin,

§

impl<const N: usize> UnsafeUnpin for MeasurementHistogram<N>
where [u64; N]: UnsafeUnpin, [bool; N]: UnsafeUnpin,

§

impl<const N: usize> UnwindSafe for MeasurementHistogram<N>
where [u64; N]: UnwindSafe, [bool; N]: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.