use crate::rt::time::Instant;
use crate::service::node::Node;
use crate::service::{Layer, Service};
use http::{Request, Response};
use std::sync::Arc;
pub struct NodeMetricsLayer;
impl<S> Layer<S> for NodeMetricsLayer {
type Service = NodeMetricsService<S>;
fn layer(self, inner: S) -> NodeMetricsService<S> {
NodeMetricsService { inner }
}
}
pub struct NodeMetricsService<S> {
inner: S,
}
impl<S, B1, B2> Service<Request<B1>> for NodeMetricsService<S>
where
S: Service<Request<B1>, Response = Response<B2>>,
{
type Error = S::Error;
type Response = S::Response;
async fn call(&self, req: Request<B1>) -> Result<S::Response, S::Error> {
let node = req
.extensions()
.get::<Arc<Node>>()
.expect("should have a Node extension")
.clone();
let start = Instant::now();
let result = self.inner.call(req).await;
if let Some(host_metrics) = &node.host_metrics {
match &result {
Ok(response) => host_metrics.update(response.status(), start.elapsed()),
Err(_) => host_metrics.update_io_error(),
}
}
result
}
}