prometheus/
pulling_gauge.rs1use std::{collections::HashMap, fmt, sync::Arc};
2
3use crate::{
4 core::Collector,
5 proto::{Gauge, Metric, MetricFamily, MetricType},
6};
7
8#[derive(Clone)]
29pub struct PullingGauge {
30 desc: crate::core::Desc,
31 value: Arc<Box<dyn Fn() -> f64 + Send + Sync>>,
32}
33
34impl fmt::Debug for PullingGauge {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 f.debug_struct("PullingGauge")
37 .field("desc", &self.desc)
38 .field("value", &"<opaque>")
39 .finish()
40 }
41}
42
43impl PullingGauge {
44 pub fn new<S1: Into<String>, S2: Into<String>>(
46 name: S1,
47 help: S2,
48 value: Box<dyn Fn() -> f64 + Send + Sync>,
49 ) -> crate::Result<Self> {
50 Ok(PullingGauge {
51 value: Arc::new(value),
52 desc: crate::core::Desc::new(name.into(), help.into(), Vec::new(), HashMap::new())?,
53 })
54 }
55
56 fn metric(&self) -> Metric {
57 let mut gauge = Gauge::default();
58 let getter = &self.value;
59 gauge.set_value(getter());
60
61 Metric::from_gauge(gauge)
62 }
63}
64
65impl Collector for PullingGauge {
66 fn desc(&self) -> Vec<&crate::core::Desc> {
67 vec![&self.desc]
68 }
69
70 fn collect(&self) -> Vec<crate::proto::MetricFamily> {
71 let mut m = MetricFamily::default();
72 m.set_name(self.desc.fq_name.clone());
73 m.set_help(self.desc.help.clone());
74 m.set_field_type(MetricType::GAUGE);
75 m.set_metric(vec![self.metric()]);
76 vec![m]
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use crate::metrics::Collector;
84 #[cfg(feature = "protobuf")]
85 use crate::proto_ext::MessageFieldExt;
86
87 #[test]
88 fn test_pulling_gauge() {
89 const VALUE: f64 = 10.0;
90
91 let gauge =
92 PullingGauge::new("test_gauge", "Purely for testing", Box::new(|| VALUE)).unwrap();
93
94 let metrics = gauge.collect();
95 assert_eq!(metrics.len(), 1);
96
97 assert_eq!(VALUE, metrics[0].get_metric()[0].get_gauge().get_value());
98 }
99}