openzeppelin_relayer/metrics/
middleware.rs1use crate::metrics::{ERROR_COUNTER, RAW_REQUEST_COUNTER, REQUEST_COUNTER, REQUEST_LATENCY};
5use actix_web::{
6 dev::{Service, ServiceRequest, ServiceResponse, Transform},
7 Error,
8};
9use futures::future::{LocalBoxFuture, Ready};
10use std::{
11 task::{Context, Poll},
12 time::Instant,
13};
14
15pub struct MetricsMiddleware;
16
17impl<S, B> Transform<S, ServiceRequest> for MetricsMiddleware
19where
20 S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
21 B: 'static,
22{
23 type Response = ServiceResponse<B>;
24 type Error = Error;
25 type InitError = ();
26 type Transform = MetricsMiddlewareService<S>;
27 type Future = Ready<Result<Self::Transform, Self::InitError>>;
28
29 fn new_transform(&self, service: S) -> Self::Future {
30 futures::future::ready(Ok(MetricsMiddlewareService { service }))
31 }
32}
33
34pub struct MetricsMiddlewareService<S> {
35 service: S,
36}
37
38impl<S, B> Service<ServiceRequest> for MetricsMiddlewareService<S>
40where
41 S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
42 B: 'static,
43{
44 type Response = ServiceResponse<B>;
45 type Error = Error;
46 type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
47
48 fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
50 self.service.poll_ready(cx)
51 }
52
53 fn call(&self, req: ServiceRequest) -> Self::Future {
55 let endpoint = req
59 .match_pattern()
60 .unwrap_or_else(|| req.path().to_string());
61
62 let method = req.method().to_string();
64
65 let raw_uri = req.path().to_string();
67
68 let start_time = Instant::now();
70
71 let fut = self.service.call(req);
72 Box::pin(async move {
73 let res = fut.await;
74 let elapsed = start_time.elapsed().as_secs_f64();
76
77 let status = match &res {
79 Ok(response) => response.response().status().to_string(),
80 Err(e) => e.as_response_error().status_code().to_string(),
81 };
82
83 REQUEST_LATENCY
85 .with_label_values(&[&endpoint, &method, &status])
86 .observe(elapsed);
87
88 match &res {
89 Ok(_) => {
90 REQUEST_COUNTER
91 .with_label_values(&[&endpoint, &method, &status])
92 .inc();
93 }
94 Err(_) => {
95 ERROR_COUNTER
97 .with_label_values(&[&endpoint, &method, &status])
98 .inc();
99 }
100 }
101 RAW_REQUEST_COUNTER
103 .with_label_values(&[&raw_uri, &method, &status])
104 .inc();
105 res
106 })
107 }
108}