diff --git a/.gitignore b/.gitignore index d1c20ca..31c0a6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +log.txt /target *.iml diff --git a/Cargo.lock b/Cargo.lock index 1087dad..5e55ae5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,18 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + [[package]] name = "atty" version = "0.2.14" @@ -214,6 +226,23 @@ dependencies = [ "syn", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "destructure_traitobject" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c877555693c14d2f84191cfd3ad8582790fc52b5e2274b40b59cf5f5cea25c7" + [[package]] name = "dirs-next" version = "1.0.2" @@ -310,6 +339,8 @@ dependencies = [ "git2", "itertools", "lazy_static", + "log", + "log4rs", "muncher", "platform-dirs", "syntect", @@ -348,6 +379,12 @@ dependencies = [ "libc", ] +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "iana-time-zone" version = "0.1.53" @@ -497,11 +534,43 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" dependencies = [ - "cfg-if", + "serde", +] + +[[package]] +name = "log-mdc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7" + +[[package]] +name = "log4rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36ca1786d9e79b8193a68d480a0907b612f109537115c6ff655a3a1967533fd" +dependencies = [ + "anyhow", + "arc-swap", + "chrono", + "derivative", + "fnv", + "humantime", + "libc", + "log", + "log-mdc", + "parking_lot", + "serde", + "serde-value", + "serde_json", + "serde_yaml", + "thiserror", + "thread-id", + "typemap-ors", + "winapi", ] [[package]] @@ -578,6 +647,15 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "ordered-float" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +dependencies = [ + "num-traits", +] + [[package]] name = "os_str_bytes" version = "6.3.1" @@ -733,6 +811,19 @@ name = "serde" version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] [[package]] name = "serde_derive" @@ -756,6 +847,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +dependencies = [ + "indexmap", + "ryu", + "serde", + "yaml-rust", +] + [[package]] name = "signal-hook" version = "0.3.14" @@ -876,6 +979,17 @@ dependencies = [ "syn", ] +[[package]] +name = "thread-id" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee93aa2b8331c0fec9091548843f2c90019571814057da3b783f9de09349d73" +dependencies = [ + "libc", + "redox_syscall", + "winapi", +] + [[package]] name = "time" version = "0.1.44" @@ -951,6 +1065,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "typemap-ors" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68c24b707f02dd18f1e4ccceb9d49f2058c2fb86384ef9972592904d7a28867" +dependencies = [ + "unsafe-any-ors", +] + [[package]] name = "unicode-bidi" version = "0.3.8" @@ -984,6 +1107,15 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unsafe-any-ors" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a303d30665362d9680d7d91d78b23f5f899504d4f08b3c4cf08d055d87c0ad" +dependencies = [ + "destructure_traitobject", +] + [[package]] name = "url" version = "2.3.1" diff --git a/Cargo.toml b/Cargo.toml index 71ca5cc..bb8d5f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,3 +35,5 @@ lazy_static = "1.4" syntect = "5.0" textwrap = {version = "0.16", default-features = false, optional = false, features = ["unicode-width"]} git-graph = "0.5.3" +log4rs = "1.2.0" +log = "0.4.18" diff --git a/src/main.rs b/src/main.rs index eec959d..5fdc600 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,6 +59,45 @@ fn main() { }); } +fn setup_logger(log_level: &String) { + let level = match log_level.as_str() { + "error" => log::LevelFilter::Error, + "warn" => log::LevelFilter::Warn, + "info" => log::LevelFilter::Info, + "debug" => log::LevelFilter::Debug, + "trace" => log::LevelFilter::Trace, + "off" => log::LevelFilter::Off, + _ => log::LevelFilter::Off, + }; + + // Logging to log file. + let logfile = log4rs::append::file::FileAppender::builder() + // Pattern: https://docs.rs/log4rs/*/log4rs/encode/pattern/index.html + .encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new( + "{l} - {m}\n", + ))) + .build("log.txt") + .unwrap(); + + // Log Trace level output to file where trace is the default level + // and the programmatically specified level to stderr. + let config = log4rs::Config::builder() + .appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile))) + .build( + log4rs::config::Root::builder() + .appender("logfile") + .build(level), + ) + .unwrap(); + + // Use this to change log levels at runtime. + // This means you can change the default log level to trace + // if you are trying to debug an issue and need more logs on then turn it off + // once you are done. + // let _handle = log4rs::init_config(config)?; + let _handle = log4rs::init_config(config).unwrap(); +} + fn from_args() -> Result<(), String> { let app_dir = AppDirs::new(Some("git-graph"), false).unwrap().config_dir; let mut models_dir = app_dir; @@ -125,6 +164,13 @@ fn from_args() -> Result<(), String> { .required(false) .num_args(0), ) + .arg( + Arg::new("log-level") + .long("log-level") + .help("Output log messages to a file. Default off. One of [error|warn|info|debug|trace|off].") + .required(false) + .num_args(1), + ) .arg( Arg::new("color") .long("color") @@ -285,6 +331,11 @@ fn from_args() -> Result<(), String> { let include_remote = !matches.get_flag("local"); let compact = !matches.get_flag("sparse"); + match matches.get_one::("log-level") { + Some(log_level) => setup_logger(log_level), + None => {} + } + let style = matches .get_one::("style") .map(|s| Characters::from_str(s))