prometheus/
value.rs
1use crate::atomic64::{Atomic, Number};
5use crate::desc::{Desc, Describer};
6use crate::errors::{Error, Result};
7use crate::proto::{Counter, Gauge, LabelPair, Metric, MetricFamily, MetricType};
8
9#[derive(Debug, Copy, Clone, Eq, PartialEq)]
12pub enum ValueType {
13 Counter,
14 Gauge,
15}
16
17impl ValueType {
18 pub fn metric_type(self) -> MetricType {
20 match self {
21 ValueType::Counter => MetricType::COUNTER,
22 ValueType::Gauge => MetricType::GAUGE,
23 }
24 }
25}
26
27#[derive(Debug)]
32pub struct Value<P: Atomic> {
33 pub desc: Desc,
34 pub val: P,
35 pub val_type: ValueType,
36 pub label_pairs: Vec<LabelPair>,
37}
38
39impl<P: Atomic> Value<P> {
40 pub fn new<D: Describer>(
41 describer: &D,
42 val_type: ValueType,
43 val: P::T,
44 label_values: &[&str],
45 ) -> Result<Self> {
46 let desc = describer.describe()?;
47 let label_pairs = make_label_pairs(&desc, label_values)?;
48
49 Ok(Self {
50 desc,
51 val: P::new(val),
52 val_type,
53 label_pairs,
54 })
55 }
56
57 #[inline]
58 pub fn get(&self) -> P::T {
59 self.val.get()
60 }
61
62 #[inline]
63 pub fn set(&self, val: P::T) {
64 self.val.set(val);
65 }
66
67 #[inline]
68 pub fn inc_by(&self, val: P::T) {
69 self.val.inc_by(val);
70 }
71
72 #[inline]
73 pub fn inc(&self) {
74 self.inc_by(P::T::from_i64(1));
75 }
76
77 #[inline]
78 pub fn dec(&self) {
79 self.dec_by(P::T::from_i64(1));
80 }
81
82 #[inline]
83 pub fn dec_by(&self, val: P::T) {
84 self.val.dec_by(val)
85 }
86
87 pub fn metric(&self) -> Metric {
88 let mut m = Metric::default();
89 m.set_label(from_vec!(self.label_pairs.clone()));
90
91 let val = self.get();
92 match self.val_type {
93 ValueType::Counter => {
94 let mut counter = Counter::default();
95 counter.set_value(val.into_f64());
96 m.set_counter(counter);
97 }
98 ValueType::Gauge => {
99 let mut gauge = Gauge::default();
100 gauge.set_value(val.into_f64());
101 m.set_gauge(gauge);
102 }
103 }
104
105 m
106 }
107
108 pub fn collect(&self) -> MetricFamily {
109 let mut m = MetricFamily::default();
110 m.set_name(self.desc.fq_name.clone());
111 m.set_help(self.desc.help.clone());
112 m.set_field_type(self.val_type.metric_type());
113 m.set_metric(from_vec!(vec![self.metric()]));
114 m
115 }
116}
117
118pub fn make_label_pairs(desc: &Desc, label_values: &[&str]) -> Result<Vec<LabelPair>> {
119 if desc.variable_labels.len() != label_values.len() {
120 return Err(Error::InconsistentCardinality {
121 expect: desc.variable_labels.len(),
122 got: label_values.len(),
123 });
124 }
125
126 let total_len = desc.variable_labels.len() + desc.const_label_pairs.len();
127 if total_len == 0 {
128 return Ok(vec![]);
129 }
130
131 if desc.variable_labels.is_empty() {
132 return Ok(desc.const_label_pairs.clone());
133 }
134
135 let mut label_pairs = Vec::with_capacity(total_len);
136 for (i, n) in desc.variable_labels.iter().enumerate() {
137 let mut label_pair = LabelPair::default();
138 label_pair.set_name(n.clone());
139 label_pair.set_value(label_values[i].to_owned());
140 label_pairs.push(label_pair);
141 }
142
143 for label_pair in &desc.const_label_pairs {
144 label_pairs.push(label_pair.clone());
145 }
146 label_pairs.sort();
147 Ok(label_pairs)
148}