rs_zero/observability/metrics/
http.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 HttpMetricLabels {
8 pub method: String,
10 pub route: String,
12 pub status: u16,
14}
15
16impl HttpMetricLabels {
17 pub fn new(method: impl Into<String>, route: impl Into<String>, status: u16) -> Self {
19 Self {
20 method: method.into(),
21 route: route.into(),
22 status,
23 }
24 }
25}
26
27pub(crate) fn render(
28 output: &mut String,
29 metrics: &BTreeMap<HttpMetricLabels, DurationMetricValue>,
30 in_flight: i64,
31) {
32 output.push_str("# HELP rs_zero_http_requests_total Total number of HTTP requests.\n");
33 output.push_str("# TYPE rs_zero_http_requests_total counter\n");
34 for (labels, value) in metrics {
35 write!(output, "rs_zero_http_requests_total{{").ok();
36 write_labels(output, labels, None);
37 writeln!(output, "}} {}", value.count).ok();
38 }
39
40 output.push_str("# HELP rs_zero_http_request_duration_seconds HTTP request duration.\n");
41 output.push_str("# TYPE rs_zero_http_request_duration_seconds histogram\n");
42 for (labels, value) in metrics {
43 write_duration_metric(
44 output,
45 "rs_zero_http_request_duration_seconds",
46 labels,
47 value,
48 write_labels,
49 );
50 }
51
52 output.push_str("# HELP rs_zero_http_requests_in_flight Current in-flight HTTP requests.\n");
53 output.push_str("# TYPE rs_zero_http_requests_in_flight gauge\n");
54 writeln!(output, "rs_zero_http_requests_in_flight {in_flight}").ok();
55}
56
57fn write_labels(output: &mut String, labels: &HttpMetricLabels, le: Option<&str>) {
58 write!(
59 output,
60 "method=\"{}\",route=\"{}\",status=\"{}\"",
61 escape_label(&labels.method),
62 escape_label(&labels.route),
63 labels.status
64 )
65 .ok();
66 if let Some(le) = le {
67 write!(output, ",le=\"{}\"", escape_label(le)).ok();
68 }
69}