metrics_catalogue/prometheus/
mod.rs

1use crate::prometheus::utils::{write_metric_line, write_type_line, Label};
2use crate::{Counter, DiscreteGauge, Gauge, GaugeMetric, Histogram, HistogramMetric};
3use metrics_util::Summary;
4use std::iter::{empty, once};
5
6mod server;
7mod utils;
8
9pub use server::Server;
10
11pub const QUANTILES: [f64; 4] = [0.0, 0.5, 0.9, 0.99];
12
13pub trait StringRender {
14    fn render(&self, prefix: &str, name: &str, s: &mut String);
15}
16
17impl<S: StringRender> StringRender for &S {
18    #[inline]
19    fn render(&self, prefix: &str, name: &str, s: &mut String) {
20        <S as StringRender>::render(self, prefix, name, s)
21    }
22}
23
24impl<S: StringRender> StringRender for std::sync::Arc<S> {
25    #[inline]
26    fn render(&self, prefix: &str, name: &str, s: &mut String) {
27        <S as StringRender>::render(self, prefix, name, s)
28    }
29}
30
31impl StringRender for Counter {
32    #[inline]
33    fn render(&self, prefix: &str, name: &str, s: &mut String) {
34        // TODO: Process description
35        // if let Some(desc) = descriptions.get(name.as_str()) {
36        //     write_help_line(&mut output, name.as_str(), desc);
37        // }
38        write_type_line(s, prefix, name, "counter");
39
40        // TODO: process labels
41        let labels = empty();
42        write_metric_line::<&str, u64, _>(s, prefix, name, None, labels, self.read());
43        s.push('\n');
44    }
45}
46
47#[inline]
48fn render_gauge<G: GaugeMetric>(g: &G, prefix: &str, name: &str, s: &mut String) {
49    // TODO: Process description
50    // if let Some(desc) = descriptions.get(name.as_str()) {
51    //     write_help_line(&mut output, name.as_str(), desc);
52    // }
53
54    write_type_line(s, prefix, name, "gauge");
55    // TODO: process labels
56    let labels = empty();
57    write_metric_line::<&str, f64, _>(s, prefix, name, None, labels, g.read());
58    s.push('\n');
59}
60
61impl StringRender for Gauge {
62    #[inline]
63    fn render(&self, prefix: &str, name: &str, s: &mut String) {
64        render_gauge(self, prefix, name, s)
65    }
66}
67
68impl StringRender for DiscreteGauge {
69    #[inline]
70    fn render(&self, prefix: &str, name: &str, s: &mut String) {
71        render_gauge(self, prefix, name, s)
72    }
73}
74
75#[inline]
76fn render_histogram<H: HistogramMetric>(h: &H, prefix: &str, name: &str, s: &mut String) {
77    // TODO: Process description
78    // if let Some(desc) = descriptions.get(name.as_str()) {
79    //     write_help_line(&mut output, name.as_str(), desc);
80    // }
81
82    write_type_line(s, prefix, name, "histogram");
83    // TODO: process labels
84    let labels = empty();
85    let mut summary = Summary::with_defaults();
86    let samples = h.read();
87    let mut sum = 0.0;
88    let count = samples.len();
89    for sample in samples {
90        summary.add(sample);
91        sum += sample;
92    }
93    for q in QUANTILES {
94        let value = summary.quantile(q).unwrap_or(0.0);
95        write_metric_line(
96            s,
97            prefix,
98            name,
99            None,
100            labels.clone().chain(once(Label::KeyValue(("quantile", q)))),
101            value,
102        );
103    }
104    write_metric_line(s, prefix, name, Some("sum"), empty::<Label<usize>>(), sum);
105    write_metric_line(
106        s,
107        prefix,
108        name,
109        Some("count"),
110        empty::<Label<usize>>(),
111        count as u64,
112    );
113
114    s.push('\n');
115}
116
117impl<const RETENTION: u64> StringRender for Histogram<RETENTION> {
118    #[inline]
119    fn render(&self, prefix: &str, name: &str, s: &mut String) {
120        render_histogram(self, prefix, name, s)
121    }
122}