use std::fmt::Debug;
use axum::http::Request;
use futures::FutureExt;
pub use loginit::{init, NoTime};
use tower::Service;
#[derive(Clone)]
pub struct Log;
impl<S> tower::Layer<S> for Log {
type Service = ResponseTimeService<S>;
fn layer(&self, service: S) -> Self::Service {
ResponseTimeService { inner: service }
}
}
#[derive(Clone)]
pub struct ResponseTimeService<S> {
inner: S,
}
impl<S, B> Service<Request<B>> for ResponseTimeService<S>
where
S: Service<Request<B>>,
B: Send + Debug,
{
type Response = S::Response;
type Error = S::Error;
type Future = futures::future::Map<
S::Future,
impl FnOnce(Result<S::Response, S::Error>) -> Result<S::Response, S::Error>,
>;
fn poll_ready(
&mut self,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, req: Request<B>) -> Self::Future {
#[cfg(not(feature = "stackdriver"))]
let start_time: u64 = coarsetime::Clock::now_since_epoch().as_millis();
#[cfg(not(feature = "stackdriver"))]
let method = req.method().to_string();
#[cfg(not(feature = "stackdriver"))]
let url = req.uri().to_string();
self.inner.call(req).map(move |response_result| {
#[cfg(not(feature = "stackdriver"))]
{
let latency =
(coarsetime::Clock::now_since_epoch().as_millis() - start_time) as f32 / 1000.0;
tracing::info!("{} {} {}s", method, url, latency)
}
response_result
})
}
}