entrenar/monitor/prometheus/
types.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum MetricType {
6 Gauge,
8 Counter,
10 Histogram,
12}
13
14#[derive(Debug, Clone)]
16pub struct MetricDef {
17 pub name: String,
19 pub help: String,
21 pub metric_type: MetricType,
23 pub labels: Vec<String>,
25}
26
27impl MetricDef {
28 pub fn gauge(name: &str, help: &str) -> Self {
30 Self {
31 name: name.to_string(),
32 help: help.to_string(),
33 metric_type: MetricType::Gauge,
34 labels: Vec::new(),
35 }
36 }
37
38 pub fn counter(name: &str, help: &str) -> Self {
40 Self {
41 name: name.to_string(),
42 help: help.to_string(),
43 metric_type: MetricType::Counter,
44 labels: Vec::new(),
45 }
46 }
47
48 pub fn with_labels(mut self, labels: &[&str]) -> Self {
50 self.labels = labels.iter().map(|s| (*s).to_string()).collect();
51 self
52 }
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, Hash)]
57pub struct LabelSet {
58 pub(crate) values: Vec<(String, String)>,
59}
60
61impl LabelSet {
62 pub fn new() -> Self {
64 Self { values: Vec::new() }
65 }
66
67 pub fn from_pairs(pairs: &[(&str, &str)]) -> Self {
69 Self { values: pairs.iter().map(|(k, v)| ((*k).to_string(), (*v).to_string())).collect() }
70 }
71
72 pub fn add(mut self, key: &str, value: &str) -> Self {
74 self.values.push((key.to_string(), value.to_string()));
75 self
76 }
77
78 pub(crate) fn format(&self) -> String {
80 if self.values.is_empty() {
81 return String::new();
82 }
83
84 let parts: Vec<String> = self
85 .values
86 .iter()
87 .map(|(k, v)| format!("{}=\"{}\"", k, escape_label_value(v)))
88 .collect();
89
90 format!("{{{}}}", parts.join(","))
91 }
92}
93
94impl Default for LabelSet {
95 fn default() -> Self {
96 Self::new()
97 }
98}
99
100pub(crate) fn escape_label_value(s: &str) -> String {
102 s.replace('\\', "\\\\").replace('"', "\\\"").replace('\n', "\\n")
103}
104
105#[derive(Debug, Clone)]
107pub(crate) struct MetricValue {
108 pub(crate) labels: LabelSet,
109 pub(crate) value: f64,
110 pub(crate) timestamp: Option<u64>,
111}