gasket_prometheus/
lib.rs

1use gasket::daemon::Daemon;
2use prometheus_exporter_base::{
3    prelude::ServerOptions, render_prometheus, MetricType, PrometheusInstance, PrometheusMetric,
4};
5use std::{io::Write, net::SocketAddr, sync::Arc};
6
7fn sanitize_stage_name(raw: &str) -> String {
8    raw.replace('-', "_")
9}
10
11fn write_counter(output: &mut impl Write, stage: &str, metric: &str, value: u64) {
12    let name = format!("{}_{}", sanitize_stage_name(stage), metric);
13    let help = format!("{} counter for stage {}", metric, stage);
14
15    let mut pc = PrometheusMetric::build()
16        .with_name(&name)
17        .with_metric_type(MetricType::Counter)
18        .with_help(&help)
19        .build();
20
21    pc.render_and_append_instance(
22        &PrometheusInstance::new()
23            .with_value(value)
24            .with_current_timestamp()
25            .expect("error getting the current UNIX epoch"),
26    );
27
28    writeln!(output, "{}", pc.render()).unwrap();
29}
30
31fn write_gauge(output: &mut impl Write, stage: &str, metric: &str, value: i64) {
32    let name = format!("{}_{}", sanitize_stage_name(stage), metric);
33    let help = format!("{} gauge for stage {}", metric, stage);
34
35    let mut pc = PrometheusMetric::build()
36        .with_name(&name)
37        .with_metric_type(MetricType::Counter)
38        .with_help(&help)
39        .build();
40
41    pc.render_and_append_instance(
42        &PrometheusInstance::new()
43            .with_value(value)
44            .with_current_timestamp()
45            .expect("error getting the current UNIX epoch"),
46    );
47
48    writeln!(output, "{}", pc.render()).unwrap();
49}
50
51pub async fn serve(addr: SocketAddr, source: Arc<Daemon>) {
52    let server_options = ServerOptions {
53        addr,
54        authorization: prometheus_exporter_base::prelude::Authorization::None,
55    };
56
57    render_prometheus(server_options, source, |_, options| async move {
58        let mut out = vec![];
59
60        for tether in options.tethers() {
61            for (key, metric) in tether.read_metrics().unwrap() {
62                match metric {
63                    gasket::metrics::Reading::Count(x) => {
64                        write_counter(&mut out, tether.name(), key, x);
65                    }
66                    gasket::metrics::Reading::Gauge(x) => {
67                        write_gauge(&mut out, tether.name(), key, x);
68                    }
69                    _ => (),
70                }
71            }
72        }
73
74        Ok(String::from_utf8(out).unwrap())
75    })
76    .await;
77}