init4_bin_base/utils/
metrics.rs

1use crate::utils::from_env::{FromEnv, FromEnvErr, FromEnvVar};
2use metrics_exporter_prometheus::PrometheusBuilder;
3
4use super::from_env::EnvItemInfo;
5
6/// Metrics port env var
7const METRICS_PORT: &str = "METRICS_PORT";
8
9/// Prometheus metrics configuration struct.
10///
11/// Uses the following environment variables:
12/// - `METRICS_PORT` - optional. Defaults to 9000 if missing or unparseable.
13///   The port to bind the metrics server to.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[non_exhaustive]
16pub struct MetricsConfig {
17    /// `METRICS_PORT` - The port on which to bind the metrics server. Defaults
18    /// to `9000` if missing or unparseable.
19    pub port: u16,
20}
21
22impl Default for MetricsConfig {
23    fn default() -> Self {
24        Self { port: 9000 }
25    }
26}
27
28impl From<Option<u16>> for MetricsConfig {
29    fn from(port: Option<u16>) -> Self {
30        Self {
31            port: port.unwrap_or(9000),
32        }
33    }
34}
35
36impl From<u16> for MetricsConfig {
37    fn from(port: u16) -> Self {
38        Self { port }
39    }
40}
41
42impl FromEnv for MetricsConfig {
43    type Error = std::num::ParseIntError;
44
45    fn inventory() -> Vec<&'static EnvItemInfo> {
46        vec![&EnvItemInfo {
47            var: METRICS_PORT,
48            description: "Port on which to serve metrics, u16, defaults to 9000",
49            optional: true,
50        }]
51    }
52
53    fn from_env() -> Result<Self, FromEnvErr<Self::Error>> {
54        match u16::from_env_var(METRICS_PORT).map(Self::from) {
55            Ok(cfg) => Ok(cfg),
56            Err(_) => Ok(Self::default()),
57        }
58    }
59}
60
61/// Initialize a [`metrics_exporter_prometheus`] exporter.
62///
63/// Reads the `METRICS_PORT` environment variable to determine the port to bind
64/// the exporter to. If the variable is missing or unparseable, it defaults to
65/// 9000.
66///
67/// See [`MetricsConfig`] for more information.
68///
69/// # Panics
70///
71/// This function will panic if the exporter fails to install, e.g. if the port
72/// is in use.
73pub fn init_metrics() {
74    let cfg = MetricsConfig::from_env().unwrap();
75
76    PrometheusBuilder::new()
77        .with_http_listener(([0, 0, 0, 0], cfg.port))
78        .install()
79        .expect("failed to install prometheus exporter");
80}