diff options
Diffstat (limited to 'src/metrics.rs')
-rw-r--r-- | src/metrics.rs | 65 |
1 files changed, 65 insertions, 0 deletions
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<S> tide::Middleware<S> for InstrumentationMiddleware +where + S: Send + Sync + Clone + 'static, +{ + async fn handle( + &self, + req: Request<S>, + 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<S>(_: Request<S>) -> Result +where + S: Send + Sync + Clone +{ + let mut buffer: Vec<u8> = vec![]; + let encoder = TextEncoder::new(); + let metric_families = prometheus::gather(); + encoder.encode(&metric_families, &mut buffer).unwrap(); + + Ok(Response::builder(200).body(buffer).build()) +} |