Add timings metrics middleware

This commit is contained in:
asonix 2022-11-19 20:35:45 -06:00
parent 4e1a782bea
commit cecc35ae85
3 changed files with 76 additions and 1 deletions

View file

@ -33,7 +33,7 @@ use self::{
data::{ActorCache, MediaCache, State}, data::{ActorCache, MediaCache, State},
db::Db, db::Db,
jobs::create_workers, jobs::create_workers,
middleware::{DebugPayload, RelayResolver}, middleware::{DebugPayload, RelayResolver, Timings},
routes::{actor, inbox, index, nodeinfo, nodeinfo_meta, statics}, routes::{actor, inbox, index, nodeinfo, nodeinfo_meta, statics},
}; };
@ -182,6 +182,7 @@ async fn main() -> Result<(), anyhow::Error> {
}; };
app.wrap(TracingLogger::default()) app.wrap(TracingLogger::default())
.wrap(Timings)
.service(web::resource("/").route(web::get().to(index))) .service(web::resource("/").route(web::get().to(index)))
.service(web::resource("/media/{path}").route(web::get().to(routes::media))) .service(web::resource("/media/{path}").route(web::get().to(routes::media)))
.service( .service(

View file

@ -1,7 +1,9 @@
mod payload; mod payload;
mod timings;
mod verifier; mod verifier;
mod webfinger; mod webfinger;
pub(crate) use payload::DebugPayload; pub(crate) use payload::DebugPayload;
pub(crate) use timings::Timings;
pub(crate) use verifier::MyVerify; pub(crate) use verifier::MyVerify;
pub(crate) use webfinger::RelayResolver; pub(crate) use webfinger::RelayResolver;

72
src/middleware/timings.rs Normal file
View file

@ -0,0 +1,72 @@
use actix_web::dev::{Service, ServiceRequest, Transform};
use futures_util::future::LocalBoxFuture;
use std::{
future::{ready, Ready},
time::Instant,
};
pub(crate) struct Timings;
pub(crate) struct TimingsMiddleware<S>(S);
struct LogOnDrop {
begin: Instant,
path: String,
method: String,
}
impl Drop for LogOnDrop {
fn drop(&mut self) {
let duration = self.begin.elapsed();
metrics::histogram!("relay.request.complete", duration, "path" => self.path.clone(), "method" => self.method.clone());
}
}
impl<S> Transform<S, ServiceRequest> for Timings
where
S: Service<ServiceRequest>,
S::Future: 'static,
{
type Response = S::Response;
type Error = S::Error;
type InitError = ();
type Transform = TimingsMiddleware<S>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future {
ready(Ok(TimingsMiddleware(service)))
}
}
impl<S> Service<ServiceRequest> for TimingsMiddleware<S>
where
S: Service<ServiceRequest>,
S::Future: 'static,
{
type Response = S::Response;
type Error = S::Error;
type Future = LocalBoxFuture<'static, Result<S::Response, S::Error>>;
fn poll_ready(
&self,
ctx: &mut core::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
self.0.poll_ready(ctx)
}
fn call(&self, req: ServiceRequest) -> Self::Future {
let logger = LogOnDrop {
begin: Instant::now(),
path: req.path().to_string(),
method: req.method().to_string(),
};
let fut = self.0.call(req);
Box::pin(async move {
let res = fut.await;
drop(logger);
res
})
}
}