1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
use tracing::{warn, Level};
use xitca_http::util::middleware;
use crate::service::Service;
/// builder for tracing log middleware.
///
/// # Examples
/// ```rust
/// # use xitca_web::{handler::handler_service, middleware::Logger, route::get, App, WebContext};
/// App::new()
/// .at("/", get(handler_service(|| async { "hello,world!" })))
/// # .at("/infer", handler_service(|_: &WebContext<'_>| async{ "infer type" }))
/// // log http request and error with default setting.
/// .enclosed(Logger::new());
/// ```
pub struct Logger {
logger: middleware::Logger,
}
impl Default for Logger {
fn default() -> Self {
Self::new()
}
}
impl Logger {
/// construct a new logger middleware builder with [`Level::INFO`] of verbosity it generate and captures.
/// would try to initialize global trace dispatcher.
pub fn new() -> Self {
Self::with_level(Level::INFO)
}
/// construct a new logger middleware builder with given [Level] of verbosity it generate and captures.
/// would try to initialize global trace dispatcher.
pub fn with_level(level: Level) -> Self {
if let Err(e) = tracing_subscriber::fmt().with_max_level(level).try_init() {
// the most likely case is trace dispatcher has already been set by user. log the warning and move on.
warn!("failed to initialize global trace dispatcher: {}", e);
}
Self {
logger: middleware::Logger::with_level(level),
}
}
}
impl<Arg> Service<Arg> for Logger
where
middleware::Logger: Service<Arg>,
{
type Response = <middleware::Logger as Service<Arg>>::Response;
type Error = <middleware::Logger as Service<Arg>>::Error;
async fn call(&self, arg: Arg) -> Result<Self::Response, Self::Error> {
self.logger.call(arg).await
}
}