rs_zero/observability/metrics/
sql.rs1use std::{collections::BTreeMap, fmt::Write};
2
3use super::{DurationMetricValue, escape_label, write_duration_metric};
4
5#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
7pub struct SqlMetricLabels {
8 pub db_kind: String,
10 pub repository: String,
12 pub method: String,
14 pub operation: String,
16 pub result: String,
18}
19
20impl SqlMetricLabels {
21 pub fn new(
23 db_kind: impl Into<String>,
24 repository: impl Into<String>,
25 method: impl Into<String>,
26 operation: impl Into<String>,
27 result: impl Into<String>,
28 ) -> Self {
29 Self {
30 db_kind: db_kind.into(),
31 repository: repository.into(),
32 method: method.into(),
33 operation: operation.into(),
34 result: result.into(),
35 }
36 }
37}
38
39pub(crate) fn render(
40 output: &mut String,
41 metrics: &BTreeMap<SqlMetricLabels, DurationMetricValue>,
42) {
43 output.push_str("# HELP rs_zero_sql_queries_total Total number of SQL queries.\n");
44 output.push_str("# TYPE rs_zero_sql_queries_total counter\n");
45 for (labels, value) in metrics {
46 write!(output, "rs_zero_sql_queries_total{{").ok();
47 write_labels(output, labels, None);
48 writeln!(output, "}} {}", value.count).ok();
49 }
50
51 output.push_str("# HELP rs_zero_sql_query_errors_total Total number of failed SQL queries.\n");
52 output.push_str("# TYPE rs_zero_sql_query_errors_total counter\n");
53 for (labels, value) in metrics
54 .iter()
55 .filter(|(labels, _)| labels.result != "success")
56 {
57 write!(output, "rs_zero_sql_query_errors_total{{").ok();
58 write_labels(output, labels, None);
59 writeln!(output, "}} {}", value.count).ok();
60 }
61
62 output.push_str("# HELP rs_zero_sql_query_duration_seconds SQL query duration.\n");
63 output.push_str("# TYPE rs_zero_sql_query_duration_seconds histogram\n");
64 for (labels, value) in metrics {
65 write_duration_metric(
66 output,
67 "rs_zero_sql_query_duration_seconds",
68 labels,
69 value,
70 write_labels,
71 );
72 }
73}
74
75fn write_labels(output: &mut String, labels: &SqlMetricLabels, le: Option<&str>) {
76 write!(
77 output,
78 "db_kind=\"{}\",repository=\"{}\",method=\"{}\",operation=\"{}\",result=\"{}\"",
79 escape_label(&labels.db_kind),
80 escape_label(&labels.repository),
81 escape_label(&labels.method),
82 escape_label(&labels.operation),
83 escape_label(&labels.result)
84 )
85 .ok();
86 if let Some(le) = le {
87 write!(output, ",le=\"{}\"", escape_label(le)).ok();
88 }
89}