use crate::utils::from_env::{FromEnv, FromEnvErr, FromEnvVar};
use core::net::SocketAddr;
use metrics_exporter_prometheus::PrometheusBuilder;
use super::from_env::EnvItemInfo;
const METRICS_PORT: &str = "METRICS_PORT";
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Deserialize)]
#[non_exhaustive]
#[serde(from = "Option<u16>")]
pub struct MetricsConfig {
pub port: u16,
}
impl Default for MetricsConfig {
fn default() -> Self {
Self { port: 9000 }
}
}
impl From<Option<u16>> for MetricsConfig {
fn from(port: Option<u16>) -> Self {
Self {
port: port.unwrap_or(9000),
}
}
}
impl From<u16> for MetricsConfig {
fn from(port: u16) -> Self {
Self { port }
}
}
impl FromEnv for MetricsConfig {
fn inventory() -> Vec<&'static EnvItemInfo> {
vec![&EnvItemInfo {
var: METRICS_PORT,
description: "Port on which to serve metrics, u16, defaults to 9000",
optional: true,
}]
}
fn from_env() -> Result<Self, FromEnvErr> {
match u16::from_env_var(METRICS_PORT).map(Self::from) {
Ok(cfg) => Ok(cfg),
Err(_) => Ok(Self::default()),
}
}
}
pub fn init_metrics() {
let cfg = MetricsConfig::from_env().unwrap();
init_metrics_with_config(cfg)
}
pub(crate) fn init_metrics_with_config(config: MetricsConfig) {
let address = SocketAddr::from(([0, 0, 0, 0], config.port));
PrometheusBuilder::new()
.with_http_listener(address)
.install()
.unwrap_or_else(|error| {
panic!(
"failed to install prometheus exporter on {address} (configure with {METRICS_PORT} env var): {error}",
)
});
}