1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::counter::{Atomic, Counter};
use crate::registry::Registry;
use prost::bytes::BufMut;
use prost::Message;
mod open_metrics_proto {
include!(concat!(env!("OUT_DIR"), "/openmetrics.rs"));
}
pub fn encode<B: BufMut, M: ToMetrics>(mut buf: &mut B, registry: &Registry<M>) {
let families = registry
.iter()
.map(|(desc, metric)| {
open_metrics_proto::MetricFamily {
name: desc.name().to_string(),
r#type: 0,
unit: "".to_string(),
help: desc.help().to_string(),
metrics: metric.to_metrics(),
}
})
.collect();
let set = open_metrics_proto::MetricSet {
metric_families: families,
};
set.encode(&mut buf).unwrap();
}
pub trait ToMetrics {
fn to_metrics(&self) -> Vec<open_metrics_proto::Metric>;
}
impl<A> ToMetrics for Counter<A>
where
A: Atomic,
<A as Atomic>::Number: Into<f64>,
{
fn to_metrics(&self) -> Vec<open_metrics_proto::Metric> {
let value = open_metrics_proto::metric_point::Value::CounterValue(
open_metrics_proto::CounterValue {
created: None,
exemplar: None,
total: Some(open_metrics_proto::counter_value::Total::DoubleValue(
self.get().into(),
)),
},
);
let metric = open_metrics_proto::Metric {
labels: vec![],
metric_points: vec![open_metrics_proto::MetricPoint {
timestamp: None,
value: Some(value),
}],
};
vec![metric]
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::registry::Descriptor;
use std::sync::atomic::AtomicU32;
#[test]
fn encode_counter_family() {
let mut registry = Registry::new();
let counter = Counter::<AtomicU32>::new();
registry.register(
Descriptor::new("counter", "My counter", "my_counter"),
counter.clone(),
);
counter.inc();
let mut encoded = Vec::new();
encode(&mut encoded, ®istry);
println!("encoded: {:?}", encoded);
}
}