diff --git a/src/lib.rs b/src/lib.rs index b3bebd0d..552af3c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -158,6 +158,7 @@ mod errors; mod gauge; mod histogram; mod metrics; +mod pulling_gauge; #[cfg(feature = "push")] mod push; mod registry; @@ -218,6 +219,7 @@ pub use self::histogram::DEFAULT_BUCKETS; pub use self::histogram::{exponential_buckets, linear_buckets}; pub use self::histogram::{Histogram, HistogramOpts, HistogramTimer, HistogramVec}; pub use self::metrics::Opts; +pub use self::pulling_gauge::PullingGauge; #[cfg(feature = "push")] pub use self::push::{ hostname_grouping_key, push_add_collector, push_add_metrics, push_collector, push_metrics, diff --git a/src/pulling_gauge.rs b/src/pulling_gauge.rs new file mode 100644 index 00000000..e1e35277 --- /dev/null +++ b/src/pulling_gauge.rs @@ -0,0 +1,75 @@ +use std::{collections::HashMap, fmt, sync::Arc}; + +use crate::{ + core::Collector, + proto::{Gauge, Metric, MetricFamily, MetricType}, +}; +use protobuf::RepeatedField; + +/// A prometheus gauge that reads the value from a provided function on every +/// collect run. Used to expose metrics that are better to be polled as opposed +/// to continuously set. +#[derive(Clone)] +pub struct PullingGauge { + desc: crate::core::Desc, + value: Arc f64 + Send + Sync>>, +} + +impl fmt::Debug for PullingGauge { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PullingGauge") + .field("desc", &self.desc) + .field("value", &"") + .finish() + } +} + +impl PullingGauge { + /// Create a new PullingGauge. + pub fn new, S2: Into>( + fq_name: S1, + help: S2, + value: Box f64 + Send + Sync>, + ) -> crate::Result { + Ok(PullingGauge { + value: Arc::new(value), + desc: crate::core::Desc::new(fq_name.into(), help.into(), Vec::new(), HashMap::new())?, + }) + } + + /// Create a new PullingGauge and register it with the global registry. + pub fn create_and_register, S2: Into>( + name: S1, + help: S2, + value: Box f64 + Send + Sync>, + ) -> crate::Result { + let metric = PullingGauge::new(name, help, value)?; + crate::register(Box::new(metric.clone())).map(|_| metric) + } + + fn metric(&self) -> Metric { + let mut gauge = Gauge::default(); + let getter = &self.value; + gauge.set_value(getter()); + + let mut metric = Metric::default(); + metric.set_gauge(gauge); + + metric + } +} + +impl Collector for PullingGauge { + fn desc(&self) -> Vec<&crate::core::Desc> { + vec![&self.desc] + } + + fn collect(&self) -> Vec { + let mut m = MetricFamily::default(); + m.set_name(self.desc.fq_name.clone()); + m.set_help(self.desc.help.clone()); + m.set_field_type(MetricType::GAUGE); + m.set_metric(RepeatedField::from_vec(vec![self.metric()])); + vec![m] + } +}