From 764d19570ceff8bd11d18ada3d2798f895da2da7 Mon Sep 17 00:00:00 2001 From: Vika Date: Fri, 6 Aug 2021 11:44:46 +0300 Subject: Added Prometheus instrumentation I need to instrument the mobc library used for the Redis connection pool, but that can be done later since I am somewhat tired. I don't remember how much I've worked and I need a break... >.< --- src/metrics.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/metrics.rs (limited to 'src/metrics.rs') diff --git a/src/metrics.rs b/src/metrics.rs new file mode 100644 index 0000000..0537b9d --- /dev/null +++ b/src/metrics.rs @@ -0,0 +1,65 @@ +use tide::{Request, Response, Result, Next}; +use prometheus::{self, IntCounterVec, HistogramVec, TextEncoder, Encoder, register_int_counter_vec, register_histogram_vec}; +use lazy_static::lazy_static; +use async_trait::async_trait; +use std::time::{Instant, Duration}; + +// Copied from https://docs.rs/prometheus/0.12.0/src/prometheus/histogram.rs.html#885-889 +#[inline] +fn duration_to_seconds(d: Duration) -> f64 { + let nanos = f64::from(d.subsec_nanos()) / 1e9; + d.as_secs() as f64 + nanos +} + +lazy_static! { + static ref HTTP_CONNS_COUNTER: IntCounterVec = register_int_counter_vec!( + "http_requests_total", "Number of processed HTTP requests", + &["code", "method", "url"] + ).unwrap(); + + static ref HTTP_REQUEST_DURATION_HISTOGRAM: HistogramVec = register_histogram_vec!( + "http_request_duration_seconds", "Duration of HTTP requests", + &["code", "method", "url"] + ).unwrap(); +} + +pub struct InstrumentationMiddleware {} + + +#[async_trait] +impl tide::Middleware for InstrumentationMiddleware +where + S: Send + Sync + Clone + 'static, +{ + async fn handle( + &self, + req: Request, + next: Next<'_, S>, + ) -> Result { + let url = req.url().to_string(); + let method = req.method().to_string(); + // Execute the request + let instant = Instant::now(); + let res = next.run(req).await; + let elapsed = duration_to_seconds(instant.elapsed()); + // Get the code from the response + let code = res.status().to_string(); + + HTTP_CONNS_COUNTER.with_label_values(&[&code, &method, &url]).inc(); + HTTP_REQUEST_DURATION_HISTOGRAM.with_label_values(&[&code, &method, &url]).observe(elapsed); + + Ok(res) + } +} + +pub async fn gather(_: Request) -> Result +where + S: Send + Sync + Clone +{ + let mut buffer: Vec = vec![]; + let encoder = TextEncoder::new(); + let metric_families = prometheus::gather(); + encoder.encode(&metric_families, &mut buffer).unwrap(); + + Ok(Response::builder(200).body(buffer).build()) +} -- cgit 1.4.1