metrics/metrics-util/src/handle.rs

126 lines
3.5 KiB
Rust
Raw Normal View History

use crate::AtomicBucket;
use atomic_shim::AtomicU64;
use std::sync::{atomic::Ordering, Arc};
/// Basic metric handle.
///
/// Provides fast, thread-safe access and storage for the three supported metric types: counters,
/// gauges, and histograms.
#[derive(Clone)]
pub enum Handle {
/// A counter.
Counter(Arc<AtomicU64>),
/// A gauge.
Gauge(Arc<AtomicU64>),
/// A histogram.
Histogram(Arc<AtomicBucket<u64>>),
}
impl Handle {
/// Creates a counter handle.
///
/// The counter is initialized to 0.
pub fn counter() -> Handle {
Handle::Counter(Arc::new(AtomicU64::new(0)))
}
/// Creates a gauge handle.
///
/// The gauge is initialized to 0.
pub fn gauge() -> Handle {
Handle::Gauge(Arc::new(AtomicU64::new(0)))
}
/// Creates a histogram handle.
///
/// The histogram handle is initialized to empty.
pub fn histogram() -> Handle {
Handle::Histogram(Arc::new(AtomicBucket::new()))
}
/// Increments this handle as a counter.
///
/// Panics if this handle is not a counter.
pub fn increment_counter(&self, value: u64) {
match self {
Handle::Counter(counter) => {
counter.fetch_add(value, Ordering::SeqCst);
}
_ => panic!("tried to increment as counter"),
}
}
/// Updates this handle as a gauge.
///
/// Panics if this handle is not a gauge.
pub fn update_gauge(&self, value: f64) {
let unsigned = value.to_bits();
match self {
Handle::Gauge(gauge) => gauge.store(unsigned, Ordering::SeqCst),
_ => panic!("tried to update as gauge"),
}
}
/// Records to this handle as a histogram.
///
/// Panics if this handle is not a histogram.
pub fn record_histogram(&self, value: u64) {
match self {
Handle::Histogram(bucket) => bucket.push(value),
_ => panic!("tried to record as histogram"),
}
}
/// Reads this handle as a counter.
///
/// Panics if this handle is not a counter.
pub fn read_counter(&self) -> u64 {
match self {
Handle::Counter(counter) => counter.load(Ordering::Relaxed),
_ => panic!("tried to read as counter"),
}
}
/// Reads this handle as a gauge.
///
/// Panics if this handle is not a gauge.
pub fn read_gauge(&self) -> f64 {
match self {
Handle::Gauge(gauge) => {
let unsigned = gauge.load(Ordering::Relaxed);
f64::from_bits(unsigned)
}
_ => panic!("tried to read as gauge"),
}
}
/// Reads this handle as a histogram.
///
/// Panics if this handle is not a histogram.
pub fn read_histogram(&self) -> Vec<u64> {
match self {
Handle::Histogram(bucket) => bucket.data(),
_ => panic!("tried to read as histogram"),
}
}
/// Reads this handle as a histogram incrementally into a closure, and clears the histogram.
///
/// The closure `f` passed in is invoked multiple times with slices of values present in the
/// histogram currently. Once all values have been read, the histogram is cleared of all values.
///
/// Panics if this handle is not a histogram.
pub fn read_histogram_with_clear<F>(&self, f: F)
where
F: FnMut(&[u64]),
{
match self {
Handle::Histogram(bucket) => bucket.clear_with(f),
_ => panic!("tried to read as histogram"),
}
}
}