From 72225100bb7c2237317f3d493f305ea485397228 Mon Sep 17 00:00:00 2001 From: Robert Date: Sun, 14 Jul 2024 12:18:55 +0100 Subject: [PATCH] feat(tracing): add initial tracing to ~/.local/share/ducker/ducker.log --- Cargo.lock | 116 ++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 4 ++ ISSUES.md | 3 -- src/config.rs | 2 +- src/lib.rs | 1 + src/main.rs | 6 ++- src/tracing.rs | 84 +++++++++++++++++++++++++++++++++++ 7 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 src/tracing.rs diff --git a/Cargo.lock b/Cargo.lock index 6e1d5ac..ee4bce4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.18" @@ -620,12 +629,16 @@ dependencies = [ "dyn-clone", "futures", "itertools 0.13.0", + "lazy_static", "ratatui", "ratatui-macros", "reqwest", "serde", "serde_yml", "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", "tui-big-text", ] @@ -1291,9 +1304,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" @@ -1354,6 +1367,15 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" version = "2.7.2" @@ -1420,6 +1442,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -1504,6 +1536,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owo-colors" version = "3.5.0" @@ -1752,6 +1790,50 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + [[package]] name = "rend" version = "0.4.2" @@ -2527,9 +2609,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -2550,15 +2644,33 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", "sharded-slab", + "smallvec", "thread_local", + "tracing", "tracing-core", + "tracing-log", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0f84ae6..4b521b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ dirs-next = "2.0.0" dyn-clone = "1.0.17" futures = "0.3.30" itertools = "0.13.0" +lazy_static = "1.5.0" ratatui = { version = "0.27.0", features = [ "serde", "unstable-rendered-line-info", @@ -38,6 +39,9 @@ tokio = { version = "1.38.0", features = [ "macros", "process", ] } +tracing = "0.1.40" +tracing-error = "0.2.0" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tui-big-text = "0.4.5" diff --git a/ISSUES.md b/ISSUES.md index 683ac81..44324be 100644 --- a/ISSUES.md +++ b/ISSUES.md @@ -6,11 +6,8 @@ The "issues" listed here are the aspirational set of features I have in mind, so Feel free to raise issues in github. -- Option to control container log time ranges - Add tracing of some sort - Automated test strategy; perhaps obviously there aren't any tests in the repo. This is due to the way in which the project started, but probably needs to change sooner rather than later! -- Add volumes as a first class citizen -- Add networks as a first class citizen - Modals should use a general purpose trait object of some sort - preferably only one modal field per page, in a similar way to pages in the page manager - Support for "forms" of scrolling stateful widgets (TODO - look out for ratatui libraries that already support this) - Run Images - Given an image, run a new container; provide a form/modal to allow user to configure the container diff --git a/src/config.rs b/src/config.rs index c45dbb1..46c5a68 100644 --- a/src/config.rs +++ b/src/config.rs @@ -216,7 +216,7 @@ impl Default for Theme { } } -fn get_app_config_path() -> Result { +pub fn get_app_config_path() -> Result { let path = if cfg!(target_os = "macos") { dirs_next::home_dir().map(|h| h.join(".config")) } else { diff --git a/src/lib.rs b/src/lib.rs index 7da0fad..83d258c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ pub mod events; pub mod pages; pub mod state; pub mod terminal; +pub mod tracing; pub mod traits; pub mod ui; pub mod widgets; diff --git a/src/main.rs b/src/main.rs index 61159d7..b6dc152 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,9 +4,9 @@ use color_eyre::eyre::Context; use ducker::{ config::Config, docker::util::new_local_docker_connection, - events, - events::{EventLoop, Key, Message}, + events::{self, EventLoop, Key, Message}, state, terminal, + tracing::initialize_logging, ui::App, }; @@ -28,6 +28,8 @@ struct Args { #[tokio::main] async fn main() -> color_eyre::Result<()> { + initialize_logging().context("failed to initialise logging")?; + color_eyre::install()?; let args = Args::parse(); let config = Config::new(&args.export_default_config, args.docker_path)?; diff --git a/src/tracing.rs b/src/tracing.rs new file mode 100644 index 0000000..2110943 --- /dev/null +++ b/src/tracing.rs @@ -0,0 +1,84 @@ +use std::path::PathBuf; + +use color_eyre::eyre::Result; +use lazy_static::lazy_static; +use tracing::info; +use tracing_error::ErrorLayer; +use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt}; + +use crate::config::get_app_config_path; + +// taken form https://ratatui.rs/recipes/apps/log-with-tracing/ + +lazy_static! { + pub static ref PROJECT_NAME: String = env!("CARGO_CRATE_NAME").to_uppercase().to_string(); + pub static ref LOG_ENV: String = format!("{}_LOGLEVEL", PROJECT_NAME.clone()); + pub static ref LOG_FILE: String = format!("{}.log", env!("CARGO_PKG_NAME")); +} + +fn project_directory() -> Option { + dirs_next::data_dir().map(|data_dir| data_dir.join(env!("CARGO_CRATE_NAME"))) +} + +pub fn get_log_dir() -> PathBuf { + if let Some(p) = project_directory() { + p + } else if let Ok(p) = get_app_config_path() { + p + } else { + PathBuf::from(".").join(".data") + } +} + +pub fn initialize_logging() -> Result<()> { + let directory = get_log_dir(); + std::fs::create_dir_all(directory.clone())?; + let log_path = directory.join(LOG_FILE.clone()); + let log_file = std::fs::File::create(log_path)?; + std::env::set_var( + "RUST_LOG", + std::env::var("RUST_LOG") + .or_else(|_| std::env::var(LOG_ENV.clone())) + .unwrap_or_else(|_| format!("{}=info", env!("CARGO_CRATE_NAME"))), + ); + let file_subscriber = tracing_subscriber::fmt::layer() + .with_file(true) + .with_line_number(true) + .with_writer(log_file) + .with_target(false) + .with_ansi(false); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .with(tracing_subscriber::filter::EnvFilter::from_default_env()) + .init(); + + info!("logging initialised"); + Ok(()) +} + +/// Similar to the `std::dbg!` macro, but generates `tracing` events rather +/// than printing to stdout. +/// +/// By default, the verbosity level for the generated events is `DEBUG`, but +/// this can be customized. +#[macro_export] +macro_rules! trace_dbg { + (target: $target:expr, level: $level:expr, $ex:expr) => {{ + match $ex { + value => { + tracing::event!(target: $target, $level, ?value, stringify!($ex)); + value + } + } + }}; + (level: $level:expr, $ex:expr) => { + trace_dbg!(target: module_path!(), level: $level, $ex) + }; + (target: $target:expr, $ex:expr) => { + trace_dbg!(target: $target, level: tracing::Level::DEBUG, $ex) + }; + ($ex:expr) => { + trace_dbg!(level: tracing::Level::DEBUG, $ex) + }; +}