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}