diff --git a/Cargo.lock b/Cargo.lock index dde7144..5178f02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[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.57" @@ -125,14 +134,14 @@ dependencies = [ "dirs", "handlebars", "hotwatch", - "log", "percent-encoding", "serde", "serde_json", "serde_yaml", - "simple_logger", "tempfile", "tokio", + "tracing", + "tracing-subscriber", ] [[package]] @@ -205,17 +214,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "colored" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" -dependencies = [ - "atty", - "lazy_static", - "winapi 0.3.9", -] - [[package]] name = "digest" version = "0.8.1" @@ -593,6 +591,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + [[package]] name = "matches" version = "0.1.9" @@ -711,15 +718,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", -] - [[package]] name = "once_cell" version = "1.12.0" @@ -881,6 +879,30 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -973,16 +995,12 @@ dependencies = [ ] [[package]] -name = "simple_logger" -version = "2.1.0" +name = "sharded-slab" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75a9723083573ace81ad0cdfc50b858aa3c366c48636edb4109d73122a0c0ea" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" dependencies = [ - "atty", - "colored", - "log", - "time", - "winapi 0.3.9", + "lazy_static", ] [[package]] @@ -991,6 +1009,12 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + [[package]] name = "socket2" version = "0.4.4" @@ -1087,23 +1111,14 @@ dependencies = [ ] [[package]] -name = "time" -version = "0.3.9" +name = "thread_local" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ - "itoa", - "libc", - "num_threads", - "time-macros", + "once_cell", ] -[[package]] -name = "time-macros" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" - [[package]] name = "tokio" version = "1.18.2" @@ -1201,9 +1216,21 @@ dependencies = [ "cfg-if 1.0.0", "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.26" @@ -1211,6 +1238,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" dependencies = [ "lazy_static", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -1237,6 +1294,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 297682f..4ce42b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,12 +18,12 @@ clap = { version = "3", features = ["wrap_help", "derive", "cargo"] } dirs = "4" handlebars = "4" hotwatch = "0.4" -log = "0.4" percent-encoding = "2" serde = { version = "1", features = ["derive"] } serde_yaml = "0.8" serde_json = "1" -simple_logger = "2" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } [dev-dependencies] tempfile = "3" diff --git a/src/cli.rs b/src/cli.rs index 93ba71b..e0eafdc 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,15 +1,13 @@ use clap::{crate_authors, crate_version, Parser}; use std::path::PathBuf; +use tracing_subscriber::filter::Directive; #[derive(Parser)] #[clap(version = crate_version!(), author = crate_authors!())] pub struct Opts { - /// Increases the log level to info, debug, and trace, respectively. - #[clap(short, long, parse(from_occurrences), conflicts_with("quiet"))] - pub verbose: u8, - /// Decreases the log level to error or no logging at all, respectively. - #[clap(short, long, parse(from_occurrences), conflicts_with("verbose"))] - pub quiet: u8, + /// Set the logging directives + #[clap(long, default_value = "info")] + pub log: Vec, /// Specify the location of the config file to read from. Needs read/write permissions. #[clap(short, long)] pub config: Option, diff --git a/src/config.rs b/src/config.rs index 0649992..1436101 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,5 @@ use crate::BunBunError; use dirs::{config_dir, home_dir}; -use log::{debug, info, trace}; use serde::{ de::{self, Deserializer, MapAccess, Unexpected, Visitor}, Deserialize, Serialize, @@ -10,6 +9,7 @@ use std::fmt; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; use std::path::PathBuf; +use tracing::{debug, info, trace}; const CONFIG_FILENAME: &str = "bunbun.yaml"; const DEFAULT_CONFIG: &[u8] = include_bytes!("../bunbun.default.yaml"); diff --git a/src/error.rs b/src/error.rs index 065ad9a..f895506 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,7 +7,6 @@ pub enum BunBunError { Io(std::io::Error), Parse(serde_yaml::Error), Watch(hotwatch::Error), - LoggerInit(log::SetLoggerError), CustomProgram(String), NoValidConfigPath, InvalidConfigPath(std::path::PathBuf, std::io::Error), @@ -24,7 +23,6 @@ impl fmt::Display for BunBunError { Self::Io(e) => e.fmt(f), Self::Parse(e) => e.fmt(f), Self::Watch(e) => e.fmt(f), - Self::LoggerInit(e) => e.fmt(f), Self::CustomProgram(msg) => msg.fmt(f), Self::NoValidConfigPath => write!(f, "No valid config path was found!"), Self::InvalidConfigPath(path, reason) => { @@ -52,5 +50,4 @@ macro_rules! from_error { from_error!(std::io::Error, Io); from_error!(serde_yaml::Error, Parse); from_error!(hotwatch::Error, Watch); -from_error!(log::SetLoggerError, LoggerInit); from_error!(serde_json::Error, JsonParse); diff --git a/src/main.rs b/src/main.rs index 9ae1af0..76b9e2f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,12 +15,12 @@ use clap::Parser; use error::BunBunError; use handlebars::Handlebars; use hotwatch::{Event, Hotwatch}; -use log::{debug, info, trace, warn}; -use simple_logger::SimpleLogger; -use std::cmp::min; use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; +use tracing::{debug, info, trace, warn}; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; mod cli; mod config; @@ -43,9 +43,19 @@ pub struct State { #[tokio::main] #[cfg(not(tarpaulin_include))] async fn main() -> Result<()> { + use tracing_subscriber::EnvFilter; + let opts = cli::Opts::parse(); - init_logger(opts.verbose, opts.quiet)?; + let mut env_filter = EnvFilter::from_default_env(); + for directive in opts.log { + env_filter = env_filter.add_directive(directive); + } + + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer()) + .with(env_filter) + .init(); let conf_data = match opts.config { Some(file_name) => load_custom_file(file_name), @@ -71,35 +81,17 @@ async fn main() -> Result<()> { .layer(Extension(compile_templates()?)) .layer(Extension(state)); - axum::Server::bind(&conf.bind_address.parse()?) + let bind_addr = conf.bind_address.parse()?; + + info!("Starting server at {bind_addr}"); + + axum::Server::bind(&bind_addr) .serve(app.into_make_service()) .await?; Ok(()) } -/// Initializes the logger based on the number of quiet and verbose flags passed -/// in. Usually, these values are mutually exclusive, that is, if the number of -/// verbose flags is non-zero then the quiet flag is zero, and vice versa. -#[cfg(not(tarpaulin_include))] -fn init_logger(num_verbose_flags: u8, num_quiet_flags: u8) -> Result<()> { - let log_level = match min(num_verbose_flags, 3) as i8 - min(num_quiet_flags, 2) as i8 { - -2 => None, - -1 => Some(log::LevelFilter::Error), - 0 => Some(log::LevelFilter::Warn), - 1 => Some(log::LevelFilter::Info), - 2 => Some(log::LevelFilter::Debug), - 3 => Some(log::LevelFilter::Trace), - _ => unreachable!(), // values are clamped to [0, 3] - [0, 2] - }; - - if let Some(level) = log_level { - SimpleLogger::new().with_level(level).init()?; - } - - Ok(()) -} - /// Generates a hashmap of routes from the data structure created by the config /// file. This should improve runtime performance and is a better solution than /// just iterating over the config object for every hop resolution. @@ -201,39 +193,6 @@ fn start_watch( Ok(watch) } -#[cfg(test)] -mod init_logger { - use super::*; - use anyhow::Result; - - #[test] - fn defaults_to_warn() -> Result<()> { - init_logger(0, 0)?; - assert_eq!(log::max_level(), log::Level::Warn); - Ok(()) - } - - // The following tests work but because the log crate is global, initializing - // the logger more than once (read: testing it more than once) leads to a - // panic. These ignored tests must be manually tested. - - #[test] - #[ignore] - fn caps_to_2_when_log_level_is_lt_2() -> Result<()> { - init_logger(0, 3)?; - assert_eq!(log::max_level(), log::LevelFilter::Off); - Ok(()) - } - - #[test] - #[ignore] - fn caps_to_3_when_log_level_is_gt_3() -> Result<()> { - init_logger(4, 0)?; - assert_eq!(log::max_level(), log::Level::Trace); - Ok(()) - } -} - #[cfg(test)] mod cache_routes { use super::*; diff --git a/src/routes.rs b/src/routes.rs index b4e3d2d..aec231b 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -7,13 +7,13 @@ use axum::http::{header, StatusCode}; use axum::response::{Html, IntoResponse, Response}; use axum::Extension; use handlebars::Handlebars; -use log::{debug, error}; use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; use serde::Deserialize; use std::collections::HashMap; use std::path::Path; use std::process::Command; use std::sync::Arc; +use tracing::{debug, error}; // https://url.spec.whatwg.org/#fragment-percent-encode-set const FRAGMENT_ENCODE_SET: &AsciiSet = &CONTROLS