use crate::MetricType;
use num::Num;
pub trait RenderToPrometheus {
fn render(&self) -> String;
}
pub struct PrometheusMetric<'a> {
pub counter_name: &'a str,
pub counter_type: MetricType,
pub counter_help: &'a str,
}
impl<'a> PrometheusMetric<'a> {
pub fn new(
counter_name: &'a str,
counter_type: MetricType,
counter_help: &'a str,
) -> PrometheusMetric<'a> {
PrometheusMetric {
counter_name,
counter_type,
counter_help,
}
}
pub fn render_header(&self) -> String {
format!(
"# HELP {} {}\n# TYPE {} {}\n",
self.counter_name, self.counter_help, self.counter_name, self.counter_type
)
}
pub fn render_sample<N>(&self, labels: Option<&[(&'a str, &'a str)]>, value: N) -> String
where
N: Num + std::fmt::Display,
{
if let Some(labels) = labels {
if labels.is_empty() {
format!("{} {}\n", self.counter_name, value.to_string())
} else {
let mut s = format!("{}{{", self.counter_name);
let mut first = true;
for (key, val) in labels.iter() {
if !first {
s.push_str(",");
} else {
first = false;
}
s.push_str(&format!("{}=\"{}\"", key, val));
}
s.push_str(&format!("}} {}\n", value.to_string()));
s
}
} else {
format!("{} {}\n", self.counter_name, value.to_string())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MetricType;
#[test]
fn test_header() {
let pc = PrometheusMetric::new("pippo_total", MetricType::Counter, "Number of pippos");
assert_eq!(
pc.render_header(),
"# HELP pippo_total Number of pippos\n# TYPE pippo_total counter\n"
);
}
#[test]
fn test_labels() {
let pc = PrometheusMetric::new("pippo_total", MetricType::Counter, "Number of pippos");
let mut number = 0;
let mut labels = Vec::new();
labels.push(("food", "chicken"));
labels.push(("instance", ""));
for _ in 0..4 {
let mut labels = Vec::new();
labels.push(("food", "chicken"));
let number_string = number.to_string();
labels.push(("instance", &number_string));
let ret = pc.render_sample(Some(&labels), number);
assert_eq!(
ret,
format!(
"pippo_total{{food=\"chicken\",instance=\"{}\"}} {}\n",
number, number
)
);
number += 1;
}
}
#[test]
fn test_no_labels() {
let pc = PrometheusMetric::new("gigino_total", MetricType::Counter, "Number of giginos");
assert_eq!(
pc.render_sample(None, 100),
format!("gigino_total {}\n", 100)
);
}
}