diff --git a/Cargo.toml b/Cargo.toml index bc0805e..3f8edc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,13 +16,16 @@ tokio = { version = "^1", features = [ "full" ] } tokio-rustls = { version = "^0.23", optional = true } webpki = { version = "^0.22", optional = true } log = { version = "^0.4", optional = true } +tracing = { version = "0.1", optional = true } [dev-dependencies] log = "^0.4" env_logger = "^0.9" +tracing-subscriber = "0.2" [features] default = ["logging"] logging = ["log"] tls = ["tokio-rustls", "webpki"] +trace = ["tracing"] unix = [] diff --git a/examples/log.rs b/examples/log.rs index 5f1c69b..86f7f12 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -1,4 +1,9 @@ +#[cfg(all(feature = "logging", not(feature = "trace")))] use log::LevelFilter; + +#[cfg(feature = "trace")] +use tracing::Level; + use ratpack::prelude::*; async fn log( @@ -8,7 +13,11 @@ async fn log( _app: App<(), NoState>, _state: NoState, ) -> HTTPResult { + #[cfg(all(feature = "logging", not(feature = "trace")))] log::trace!("New request: {}", req.uri().path()); + #[cfg(feature = "trace")] + tracing::trace!("New request: {}", req.uri().path()); + Ok((req, resp, NoState {})) } @@ -20,7 +29,12 @@ async fn hello( _state: NoState, ) -> HTTPResult { let name = params.get("name").unwrap(); + + #[cfg(all(feature = "logging", not(feature = "trace")))] log::info!("Saying hello to {}", name); + #[cfg(feature = "trace")] + tracing::info!("Saying hello to {}", name); + let bytes = Body::from(format!("hello, {}!\n", name)); return Ok(( @@ -32,11 +46,25 @@ async fn hello( #[tokio::main] async fn main() -> Result<(), ServerError> { + #[cfg(all(feature = "logging", not(feature = "trace")))] env_logger::builder() .target(env_logger::Target::Stderr) .filter(None, LevelFilter::Trace) .init(); + #[cfg(feature = "trace")] + { + let subscriber = tracing_subscriber::FmtSubscriber::builder() + // all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.) + // will be written to stdout. + .with_max_level(Level::TRACE) + // completes the builder. + .finish(); + + tracing::subscriber::set_global_default(subscriber) + .expect("setting default subscriber failed"); + } + let mut app = App::new(); app.get("/:name", compose_handler!(log, hello)); diff --git a/src/app.rs b/src/app.rs index 4790383..14169f6 100644 --- a/src/app.rs +++ b/src/app.rs @@ -148,14 +148,17 @@ impl App< let _uri = req.uri().clone(); let _method = req.method().clone(); - #[cfg(feature = "logging")] + #[cfg(all(feature = "logging", not(feature = "trace")))] log::info!("{} request to {}", _method, _uri); + #[cfg(feature = "trace")] + tracing::info!("{} request to {}", _method, _uri); + match self.router.dispatch(req, self.clone()).await { Ok(resp) => { let _status = resp.status().clone(); - #[cfg(feature = "logging")] + #[cfg(all(feature = "logging", not(feature = "trace")))] log::info!( "{} request to {}: responding with status {}", _method, @@ -163,16 +166,32 @@ impl App< _status, ); + #[cfg(feature = "trace")] + tracing::info!( + "{} request to {}: responding with status {}", + _method, + _uri, + _status, + ); + Ok(resp) } Err(e) => { - #[cfg(feature = "logging")] + #[cfg(all(feature = "logging", not(feature = "trace")))] log::error!( "{} request to {}: responding with error {:?}", _method, _uri, e, ); + + #[cfg(feature = "trace")] + tracing::error!( + "{} request to {}: responding with error {:?}", + _method, + _uri, + e, + ); match e.clone() { Error::StatusCode(sc, msg) => Ok(Response::builder() .status(sc) @@ -207,7 +226,9 @@ impl App< { #[cfg(feature = "logging")] log::error!("Error while serving HTTP connection: {}", http_err); - #[cfg(not(feature = "logging"))] + #[cfg(feature = "trace")] + tracing::error!("Error while serving HTTP connection: {}", http_err); + #[cfg(all(not(feature = "trace"), not(feature = "logging")))] eprintln!("Error while serving HTTP connection: {}", http_err); } }); @@ -231,9 +252,12 @@ impl App< async move { s.clone().dispatch(req).await } }); - #[cfg(feature = "logging")] + #[cfg(all(feature = "logging", not(feature = "trace")))] log::trace!("Request from {}", sa); + #[cfg(feature = "trace")] + tracing::trace!("Request from {}", sa); + tokio::task::spawn(async move { if let Err(http_err) = Http::new() .http1_keep_alive(true) @@ -242,7 +266,9 @@ impl App< { #[cfg(feature = "logging")] log::error!("Error while serving HTTP connection: {}", http_err); - #[cfg(not(feature = "logging"))] + #[cfg(feature = "trace")] + tracing::error!("Error while serving HTTP connection: {}", http_err); + #[cfg(all(not(feature = "trace"), not(feature = "logging")))] eprintln!("Error while serving HTTP connection: {}", http_err); } }); @@ -272,9 +298,12 @@ impl App< async move { s.clone().dispatch(req).await } }); - #[cfg(feature = "logging")] + #[cfg(all(feature = "logging", not(feature = "trace")))] log::trace!("Request from {}", sa); + #[cfg(feature = "trace")] + tracing::trace!("Request from {}", sa); + let config = config.clone(); tokio::task::spawn(async move { match config.accept(tcp_stream).await { @@ -286,14 +315,18 @@ impl App< { #[cfg(feature = "logging")] log::error!("Error while serving HTTP connection: {}", http_err); - #[cfg(not(feature = "logging"))] + #[cfg(feature = "trace")] + tracing::error!("Error while serving HTTP connection: {}", http_err); + #[cfg(all(not(feature = "trace"), not(feature = "logging")))] eprintln!("Error while serving HTTP connection: {}", http_err); } } Err(e) => { #[cfg(feature = "logging")] log::error!("Error while serving TLS: {:?}", e); - #[cfg(not(feature = "logging"))] + #[cfg(feature = "trace")] + tracing::error!("Error while serving TLS: {:?}", e); + #[cfg(all(not(feature = "trace"), not(feature = "logging")))] eprintln!("Error while serving TLS: {:?}", e); } }