From f40e332175c46612c96b06871a6014d8cf78495e Mon Sep 17 00:00:00 2001 From: Jose Quintana Date: Wed, 6 Jan 2021 00:31:16 +0100 Subject: [PATCH] feat: logging support --- Cargo.lock | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------- Cargo.toml | 5 ++--- src/bin/server.rs | 29 ++++++++++++++++------------- src/core/config.rs | 2 +- src/core/helpers.rs | 28 ++++++++++------------------ src/core/logger.rs | 56 ++++++++++++++------------------------------------------ src/core/mod.rs | 9 ++++++--- src/core/rejection.rs | 7 +++---- src/core/result.rs | 4 ++++ src/lib.rs | 1 + 10 files changed, 171 insertions(+), 153 deletions(-) create mode 100644 src/core/result.rs diff --git a/Cargo.lock b/Cargo.lock index f142856..53c8e39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,15 +7,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] -name = "aho-corasick" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" -dependencies = [ - "memchr", -] - -[[package]] name = "alloc-no-stdlib" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -40,6 +31,15 @@ dependencies = [ ] [[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] name = "anyhow" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -56,7 +56,7 @@ dependencies = [ "flate2", "futures-core", "memchr", - "pin-project-lite 0.2.0", + "pin-project-lite 0.2.1", ] [[package]] @@ -210,7 +210,7 @@ version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ - "ansi_term", + "ansi_term 0.11.0", "atty", "bitflags", "strsim", @@ -268,19 +268,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e" [[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -402,7 +389,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-task", - "pin-project 1.0.2", + "pin-project 1.0.3", "pin-utils", "slab", ] @@ -540,15 +527,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" [[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] - -[[package]] name = "hyper" version = "0.13.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -564,7 +542,7 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project 1.0.2", + "pin-project 1.0.3", "socket2", "tokio", "tower-service", @@ -670,6 +648,15 @@ dependencies = [ ] [[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata", +] + +[[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -877,11 +864,11 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccc2237c2c489783abd8c4c80e5450fc0e98644555b1364da68cc29aa151ca7" +checksum = "5a83804639aad6ba65345661744708855f9fbcb71176ea8d28d05aeb11d975e7" dependencies = [ - "pin-project-internal 1.0.2", + "pin-project-internal 1.0.3", ] [[package]] @@ -897,9 +884,9 @@ dependencies = [ [[package]] name = "pin-project-internal" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f" +checksum = "b7bcc46b8f73443d15bc1c5fecbb315718491fa9187fa483f0e359323cde8b3a" dependencies = [ "proc-macro2", "quote", @@ -914,9 +901,9 @@ checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" [[package]] name = "pin-project-lite" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" +checksum = "e36743d754ccdf9954c2e352ce2d4b106e024c814f6499c2dadff80da9a442d8" [[package]] name = "pin-utils" @@ -1146,10 +1133,17 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" dependencies = [ - "aho-corasick", - "memchr", "regex-syntax", - "thread_local", +] + +[[package]] +name = "regex-automata" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" +dependencies = [ + "byteorder", + "regex-syntax", ] [[package]] @@ -1240,6 +1234,15 @@ dependencies = [ ] [[package]] +name = "sharded-slab" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3" +dependencies = [ + "lazy_static", +] + +[[package]] name = "signal" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1265,6 +1268,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] +name = "smallvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0" + +[[package]] name = "socket2" version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1280,14 +1289,13 @@ name = "static-web-server" version = "0.0.0" dependencies = [ "anyhow", - "chrono", - "env_logger", "jemallocator", - "log", "nix", "signal", "structopt", "tokio", + "tracing", + "tracing-subscriber", "warp", ] @@ -1323,9 +1331,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6" +checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" dependencies = [ "proc-macro2", "quote", @@ -1347,15 +1355,6 @@ dependencies = [ ] [[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1475,11 +1474,23 @@ checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3" dependencies = [ "cfg-if 1.0.0", "log", - "pin-project-lite 0.2.0", + "pin-project-lite 0.2.1", + "tracing-attributes", "tracing-core", ] [[package]] +name = "tracing-attributes" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "tracing-core" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1499,6 +1510,49 @@ dependencies = [ ] [[package]] +name = "tracing-log" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e0f8c7178e13481ff6765bd169b33e8d554c5d2bbede5e32c356194be02b9b9" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1fa8f0c8f4c594e4fc9debc1990deab13238077271ba84dd853d54902ee3401" +dependencies = [ + "ansi_term 0.12.1", + "chrono", + "lazy_static", + "matchers", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] name = "try-lock" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1705,15 +1759,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index d4bc078..b1d206a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,10 +23,9 @@ include = ["src/**/*", "Cargo.toml", "Cargo.lock"] [dependencies] tokio = { version = "0.2", features = ["full"] } warp = { version = "0.2", features = ["compression"] } -log = "0.4" -chrono = "0.4" anyhow = "1.0" -env_logger = "0.7" +tracing = "0.1" +tracing-subscriber = "0.2" structopt = "0.3" nix = "0.14" signal = "0.7" diff --git a/src/bin/server.rs b/src/bin/server.rs index 9e6211e..4f17f92 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -4,33 +4,36 @@ #[global_allocator] static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; -#[macro_use] extern crate static_web_server; -use self::static_web_server::{core::config, core::logger, core::rejection}; use structopt::StructOpt; +use tracing::info; use warp::Filter; +use self::static_web_server::core::*; + /// It creates a new server instance with given options. -async fn server(opts: config::Options) { - logger::init(&opts.log_level); +async fn server(opts: config::Options) -> Result { + logger::init(&opts.log_level)?; let filters = warp::get() .and(warp::fs::dir(opts.root)) .with(warp::compression::gzip()) - .recover(rejection::handle_rejection); + .recover(rejection::handle_rejection) + .with(warp::trace::request()); + + info!("listening on http://[{}]:{}", &opts.host, &opts.port); - note!("server is listening on {}:{}", &opts.host, &opts.port); + let host = opts.host.parse::()?; - let host = opts - .host - .parse::() - .expect("not valid IP address"); + warp::serve(filters).run((host, opts.port)).await; - warp::serve(filters).run((host, opts.port)).await + Ok(()) } #[tokio::main(max_threads = 10_000)] -async fn main() { - server(config::Options::from_args()).await +async fn main() -> Result { + server(config::Options::from_args()).await?; + + Ok(()) } diff --git a/src/core/config.rs b/src/core/config.rs index ddd1d83..c8fa835 100644 --- a/src/core/config.rs +++ b/src/core/config.rs @@ -1,6 +1,6 @@ use structopt::StructOpt; -/// Warp Web Server +/// Static Web Server #[derive(Debug, StructOpt)] pub struct Options { #[structopt(long, short = "s", default_value = "::", env = "SERVER_HOST")] diff --git a/src/core/helpers.rs b/src/core/helpers.rs index d251a0c..96f2eff 100644 --- a/src/core/helpers.rs +++ b/src/core/helpers.rs @@ -1,35 +1,27 @@ -use std::error; use std::path::{Path, PathBuf}; +use super::Result; + /// Validate and return a directory path. -pub fn get_valid_dirpath>(path: P) -> Result> +pub fn get_valid_dirpath>(path: P) -> Result where PathBuf: From

, { match PathBuf::from(path) { - v if !v.exists() => Result::Err(From::from(format!("path \"{:?}\" was not found", &v))), - v if !v.is_dir() => { - Result::Err(From::from(format!("path \"{:?}\" is not a directory", &v))) - } - v => Result::Ok(v), + v if !v.exists() => bail!("path \"{:?}\" was not found", &v), + v if !v.is_dir() => bail!("path \"{:?}\" is not a directory", &v), + v => Ok(v), } } /// Get the directory name of a valid directory path. -pub fn get_dirname>(path: P) -> Result> +pub fn get_dirname>(path: P) -> Result where PathBuf: From

, { - let path = match get_valid_dirpath(path) { - Err(e) => return Result::Err(e), - Ok(v) => v, - }; - + let path = get_valid_dirpath(path)?; match path.iter().last() { - Some(v) => Result::Ok(v.to_str().unwrap().to_string()), - _ => Result::Err(From::from(format!( - "directory name for path \"{:?}\" was not determined", - path, - ))), + Some(v) => Ok(v.to_str().unwrap().to_string()), + _ => bail!("directory name for path \"{:?}\" was not determined", path), } } diff --git a/src/core/logger.rs b/src/core/logger.rs index c25df23..759dd4f 100644 --- a/src/core/logger.rs +++ b/src/core/logger.rs @@ -1,45 +1,17 @@ -use env_logger::Builder; -use log::LevelFilter; -use std::io::Write; +use tracing::Level; +use tracing_subscriber::fmt::format::FmtSpan; -/// Initialize logging builder with its levels -pub fn init(level: &str) { - let log_level = match level { - "off" => LevelFilter::Off, - "error" => LevelFilter::Error, - "warn" => LevelFilter::Warn, - "info" => LevelFilter::Info, - "debug" => LevelFilter::Debug, - "trace" => LevelFilter::Trace, - _ => { - println!("Log level \"{}\" is not supported", level); - std::process::exit(1); - } - }; +use super::Result; - Builder::new() - .filter_level(log_level) - .format(|buf, record| { - writeln!( - buf, - "{} [{}] - {}", - chrono::Local::now().format("%Y-%m-%dT%H:%M:%S"), - record.level(), - record.args() - ) - }) - .init(); -} - -// `note` is a custom log level macro which is not affected by env log level. -// It takes precedence over other log levels -#[macro_export] -macro_rules! note { - ($($arg:tt)*) => ({ - println!( - "{} [NOTE] - {}", - chrono::Local::now().format("%Y-%m-%dT%H:%M:%S"), - format!($($arg)*) - ); - }) +/// Initialize logging builder with its levels. +pub fn init(level: &str) -> Result { + let level = level.parse::()?; + match tracing_subscriber::fmt() + .with_max_level(level) + .with_span_events(FmtSpan::CLOSE) + .try_init() + { + Err(err) => Err(anyhow!(err)), + _ => Ok(()), + } } diff --git a/src/core/mod.rs b/src/core/mod.rs index 5d48af2..e68fe1d 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,7 +1,10 @@ -#[macro_use] -pub mod logger; - pub mod config; pub mod helpers; +pub mod logger; pub mod rejection; pub mod signal_manager; + +#[macro_use] +pub mod result; + +pub use crate::core::result::*; diff --git a/src/core/rejection.rs b/src/core/rejection.rs index f798e87..d57062f 100644 --- a/src/core/rejection.rs +++ b/src/core/rejection.rs @@ -3,8 +3,7 @@ use std::convert::Infallible; use warp::http::StatusCode; use warp::{Rejection, Reply}; -// This function receives a `Rejection` and tries to return a custom -// value, otherwise simply passes the rejection along. +// It receives a `Rejection` and tries to return a HTML error reply. pub async fn handle_rejection(err: Rejection) -> Result { let code = if err.is_not_found() { StatusCode::NOT_FOUND @@ -15,9 +14,9 @@ pub async fn handle_rejection(err: Rejection) -> Result } else { StatusCode::INTERNAL_SERVER_ERROR }; - let body = format!( + let content = format!( "{}

{}

", code, code ); - Ok(warp::reply::with_status(warp::reply::html(body), code)) + Ok(warp::reply::with_status(warp::reply::html(content), code)) } diff --git a/src/core/result.rs b/src/core/result.rs new file mode 100644 index 0000000..a183171 --- /dev/null +++ b/src/core/result.rs @@ -0,0 +1,4 @@ +/// Convenient result return type alias of `anyhow::Result` +pub type Result = anyhow::Result; + +pub use anyhow::Context; diff --git a/src/lib.rs b/src/lib.rs index 6e03bf4..2cf9f77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#[macro_use] extern crate anyhow; pub mod core; -- libgit2 1.7.2