Skip to content
Snippets Groups Projects
lib.rs 3.1 KiB
Newer Older
RDruon's avatar
RDruon committed
pub mod brw_stats;
pub mod jobstats;
pub mod lnet;
RDruon's avatar
RDruon committed
pub mod stats;
RDruon's avatar
RDruon committed

use brw_stats::build_target_stats;
use lnet::build_lnet_stats;
RDruon's avatar
RDruon committed
use lustre_collector::{LNetStat, Record, TargetStat, TargetVariant};
RDruon's avatar
RDruon committed
use num_traits::Num;
use prometheus_exporter_base::{prelude::*, Yes};
use std::{collections::BTreeMap, fmt, ops::Deref, time::Duration};

#[derive(Debug, Clone, Copy)]
struct Metric {
    name: &'static str,
    help: &'static str,
    r#type: MetricType,
}

RDruon's avatar
RDruon committed
trait LabelProm {
    fn to_prom_label(&self) -> &'static str;
}

impl LabelProm for TargetVariant {
    fn to_prom_label(&self) -> &'static str {
        match self {
            TargetVariant::Ost => "ost",
            TargetVariant::Mgt => "mgt",
            TargetVariant::Mdt => "mdt",
        }
    }
}

RDruon's avatar
RDruon committed
impl From<Metric> for PrometheusMetric<'_> {
    fn from(x: Metric) -> Self {
        PrometheusMetric::build()
            .with_name(x.name)
            .with_help(x.help)
            .with_metric_type(x.r#type)
            .build()
    }
}

trait ToMetricInst<T>
where
    T: Num + fmt::Display + fmt::Debug + Copy,
{
    fn to_metric_inst(&self, time: Duration) -> PrometheusInstance<'_, T, Yes>;
}

impl<T> ToMetricInst<T> for TargetStat<T>
where
    T: Num + fmt::Display + fmt::Debug + Copy,
{
    fn to_metric_inst(&self, time: Duration) -> PrometheusInstance<'_, T, Yes> {
        PrometheusInstance::new()
RDruon's avatar
RDruon committed
            .with_label("component", self.kind.to_prom_label())
RDruon's avatar
RDruon committed
            .with_label("target", self.target.deref())
            .with_value(self.value)
            .with_timestamp(time.as_millis())
    }
}

impl<T> ToMetricInst<T> for LNetStat<T>
where
    T: Num + fmt::Display + fmt::Debug + Copy,
{
    fn to_metric_inst(&self, time: Duration) -> PrometheusInstance<'_, T, Yes> {
        PrometheusInstance::new()
            .with_label("nid", self.nid.deref())
            .with_value(self.value)
            .with_timestamp(time.as_millis())
    }
}

trait Name {
    fn name(&self) -> &'static str;
}

impl Name for Metric {
    fn name(&self) -> &'static str {
        self.name
    }
}

trait StatsMapExt {
    fn get_mut_metric<T: Name + Into<PrometheusMetric<'static>>>(
        &mut self,
        x: T,
    ) -> &mut PrometheusMetric<'static>;
}

impl StatsMapExt for BTreeMap<&'static str, PrometheusMetric<'static>> {
    fn get_mut_metric<T: Name + Into<PrometheusMetric<'static>>>(
        &mut self,
        x: T,
    ) -> &mut PrometheusMetric<'static> {
        self.entry(x.name()).or_insert_with(|| x.into())
    }
}

pub fn build_lustre_stats(output: Vec<Record>, time: Duration) -> String {
    let mut stats_map = BTreeMap::new();

    for x in output {
        match x {
            lustre_collector::Record::Host(_) => {}
            lustre_collector::Record::Node(_) => {}
            lustre_collector::Record::LNetStat(x) => {
                build_lnet_stats(x, &mut stats_map, time);
            }
            lustre_collector::Record::Target(x) => {
                build_target_stats(x, &mut stats_map, time);
            }
        }
    }

    stats_map
        .values()
        .map(|x| x.render())
        .collect::<Vec<_>>()
        .join("\n")
}