From d9cf49d8805577773a9143ff16c012a9ab0dfe60 Mon Sep 17 00:00:00 2001 From: Daniel Voogsgerd Date: Thu, 29 Aug 2024 13:55:58 +0200 Subject: [PATCH 1/4] feat: Variable log levels This uses the `tracing_subscriber` with `EnvFilter` to get log levels that can be set using environment variables. This also enables `branectl` to translate a set of environment variables so that every container can get a specific log level set at start --- Cargo.lock | 125 +++++++++++++++++++- brane-api/Cargo.toml | 3 + brane-api/src/main.rs | 19 ++- brane-ctl/Cargo.toml | 3 + brane-ctl/src/lifetime.rs | 235 +++++++++++++++++++++++++++++--------- 5 files changed, 316 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d5a2136..150d6917 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -536,6 +536,8 @@ dependencies = [ "tokio", "tokio-stream", "tokio-tar", + "tracing", + "tracing-subscriber", "uuid", "warp", ] @@ -731,9 +733,12 @@ dependencies = [ "shlex", "specifications 3.0.0", "srv", + "strum 0.26.3", + "strum_macros 0.26.4", "tempfile", "thiserror 2.0.12", "tokio", + "tracing", ] [[package]] @@ -2913,6 +2918,15 @@ dependencies = [ "twox-hash", ] +[[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 = "matchit" version = "0.7.3" @@ -3100,6 +3114,16 @@ dependencies = [ "nom", ] +[[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-bigint" version = "0.4.6" @@ -3257,6 +3281,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "overview" version = "3.0.0" @@ -3712,8 +3742,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[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]] @@ -3724,9 +3763,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] +[[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.5" @@ -4281,6 +4326,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shell-words" version = "1.1.0" @@ -4523,6 +4577,12 @@ dependencies = [ "strum_macros 0.25.3", ] +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + [[package]] name = "strum" version = "0.27.1" @@ -4571,6 +4631,19 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.100", +] + [[package]] name = "strum_macros" version = "0.27.1" @@ -4765,6 +4838,16 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "time" version = "0.3.39" @@ -5120,6 +5203,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", + "valuable", +] + +[[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.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -5256,6 +5369,12 @@ dependencies = [ "serde", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/brane-api/Cargo.toml b/brane-api/Cargo.toml index 6024f263..72914c94 100644 --- a/brane-api/Cargo.toml +++ b/brane-api/Cargo.toml @@ -34,6 +34,9 @@ tokio-tar = "0.3.0" uuid = { version = "1.7.0", features = ["serde", "v4"] } warp = "0.3.2" +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } + brane-cfg = { path = "../brane-cfg" } brane-prx = { path = "../brane-prx" } brane-shr = { path = "../brane-shr" } diff --git a/brane-api/src/main.rs b/brane-api/src/main.rs index 3e55b867..8d0e5171 100644 --- a/brane-api/src/main.rs +++ b/brane-api/src/main.rs @@ -29,29 +29,26 @@ use clap::Parser; use dotenvy::dotenv; use error_trace::trace; use juniper::EmptySubscription; -use log::{LevelFilter, debug, error, info, warn}; +use log::{debug, error, info, warn}; use scylla::{Session, SessionBuilder}; use tokio::signal::unix::{Signal, SignalKind, signal}; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; use warp::Filter; - /***** ENTRYPOINT *****/ #[tokio::main] async fn main() { dotenv().ok(); let opts = cli::Cli::parse(); - // Configure logger. - let mut logger = env_logger::builder(); - logger.format_module_path(false); + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer()) + .with(tracing_subscriber::EnvFilter::builder().with_default_directive(tracing::level_filters::LevelFilter::WARN.into()).from_env_lossy()) + .init(); - if opts.debug { - logger.filter_level(LevelFilter::Debug).init(); - } else { - logger.filter_level(LevelFilter::Info).init(); - } - info!("Initializing brane-job v{}...", env!("CARGO_PKG_VERSION")); + tracing::info!("Initializing brane-job v{}...", env!("CARGO_PKG_VERSION")); // Load the config, making sure it's a worker config debug!("Loading node.yml file '{}'...", opts.node_config_path.display()); diff --git a/brane-ctl/Cargo.toml b/brane-ctl/Cargo.toml index 6f9356f7..85f02040 100644 --- a/brane-ctl/Cargo.toml +++ b/brane-ctl/Cargo.toml @@ -54,7 +54,10 @@ brane-shr = { path = "../brane-shr" } brane-tsk = { path = "../brane-tsk" } specifications = { path = "../specifications" } clap_complete = "4.5.8" +tracing = "0.1.40" +strum = "0.26.3" +strum_macros = "0.26.4" [build-dependencies] download.workspace = true diff --git a/brane-ctl/src/lifetime.rs b/brane-ctl/src/lifetime.rs index a1b4f15b..3fe110f5 100644 --- a/brane-ctl/src/lifetime.rs +++ b/brane-ctl/src/lifetime.rs @@ -38,10 +38,94 @@ use rand::distr::Alphanumeric; use serde::{Deserialize, Serialize}; use specifications::container::Image; use specifications::version::Version; +use strum::IntoEnumIterator; pub use crate::errors::LifetimeError as Error; use crate::spec::{LogsOpts, StartOpts, StartSubcommand}; +#[derive(Copy, Clone)] +pub enum ServiceKind { + Central(CentralKind), + Worker(WorkerKind), +} + +impl ServiceKind { + #[inline] + pub fn to_service_name(&self) -> &'static str { + match self { + Self::Central(central_kind) => central_kind.to_service_name(), + Self::Worker(worker_kind) => worker_kind.to_service_name(), + } + } + + #[inline] + pub fn to_env_var(&self) -> &'static str { + match self { + Self::Central(central_kind) => central_kind.to_env_var(), + Self::Worker(worker_kind) => worker_kind.to_env_var(), + } + } +} + +#[derive(strum_macros::EnumIter, Copy, Clone)] +pub enum CentralKind { + Api, + Drv, + Plr, + Prx, +} + +impl CentralKind { + #[inline] + pub fn to_service_name(&self) -> &'static str { + match self { + Self::Api => "brane-api", + Self::Drv => "brane-drv", + Self::Plr => "brane-plr", + Self::Prx => "brane-prx", + } + } + + #[inline] + pub fn to_env_var(&self) -> &'static str { + match self { + Self::Api => "BRANE_API", + Self::Drv => "BRANE_DRV", + Self::Plr => "BRANE_PLR", + Self::Prx => "BRANE_PRX", + } + } +} + +#[derive(strum_macros::EnumIter, Copy, Clone)] +pub enum WorkerKind { + Reg, + Job, + Chk, + Prx, +} + +impl WorkerKind { + #[inline] + pub fn to_service_name(&self) -> &'static str { + match self { + Self::Reg => "brane-reg", + Self::Job => "brane-job", + Self::Chk => "brane-chk", + Self::Prx => "brane-prx", + } + } + + #[inline] + pub fn to_env_var(&self) -> &'static str { + match self { + Self::Reg => "BRANE_REG", + Self::Job => "BRANE_JOB", + Self::Chk => "BRANE_CHK", + Self::Prx => "BRANE_PRX", + } + } +} /***** HELPER STRUCTS *****/ /// Defines a struct that writes to a valid compose file for overriding hostnames. @@ -53,8 +137,6 @@ struct ComposeOverrideFile { services: HashMap<&'static str, ComposeOverrideFileService>, } - - /// Defines a struct that defines how a service looks like in a valid compose file for overriding hostnames. #[derive(Clone, Debug, Deserialize, Serialize)] struct ComposeOverrideFileService { @@ -66,12 +148,10 @@ struct ComposeOverrideFileService { profiles: Vec, /// Whether to open any additional ports. ports: Vec, + /// Wheter to set any environment variables + environment: Vec, } - - - - /***** HELPER FUNCTIONS *****/ /// Makes the given path canonical, casting the error for convenience. /// @@ -328,6 +408,28 @@ fn prepare_host(node_config: &NodeConfig) -> Result<(), Error> { } } +fn get_log_level(service: ServiceKind) -> Option { + let log_var = format!("{service_name}_LOG", service_name = service.to_env_var()); + + match std::env::var(&log_var) { + Ok(val) => return Some(val), + // TODO: Could use the trace! macro from error-trace. + Err(err) => tracing::info!( + "Malformed log level set using environment variable `{log_var}`. Falling back to using `BRANE_LOG`, if it is set. Cause: \n{err:#}" + ), + }; + + match std::env::var("BRANE_LOG") { + Ok(val) => return Some(val), + // TODO: Could use the trace! macro from error-trace. + Err(err) => { + tracing::info!("Malformed log level set using environment variable `BRANE_LOG`. Continuing with default logging. Cause: \n{err:#}") + }, + }; + + None +} + /// Generate an additional, temporary `docker-compose.yml` file that adds additional hostnames and/or additional volumes. /// /// # Arguments @@ -352,66 +454,95 @@ fn generate_override_file(node_config: &NodeConfig, hosts: &HashMap { - // Prepare a proxy service override - let mut prx_svc: ComposeOverrideFileService = svc.clone(); - if let Some(proxy_path) = &node.paths.proxy { - // Open the extra ports - - // Read the proxy file to find the incoming ports - let proxy: proxy::ProxyConfig = proxy::ProxyConfig::from_path(proxy_path).map_err(|source| Error::ProxyReadError { source })?; - - // Open both the management and the incoming ports now - prx_svc.ports.reserve(proxy.incoming.len()); - for (port, _) in proxy.incoming { - prx_svc.ports.push(format!("0.0.0.0:{port}:{port}")); + let mut services = CentralKind::iter() + .map(|service| { + let mut service_override = svc.clone(); + + println!("Log level?"); + if let Some(log_level) = get_log_level(ServiceKind::Central(service)) { + service_override.environment.push(format!("RUST_LOG={}", log_level)); + tracing::warn!("Setting loglevel for {} to {}", service.to_service_name(), log_level); + } else { + tracing::warn!("Leaving loglevel for {} at its default", service.to_service_name()); + } + (service.to_service_name(), service_override) + }) + .collect::>(); + { + // Prepare a proxy service override + let prx_svc = services.get_mut(CentralKind::Prx.to_service_name()).unwrap(); + if let Some(proxy_path) = &node.paths.proxy { + // Open the extra ports + + // Read the proxy file to find the incoming ports + let proxy: proxy::ProxyConfig = proxy::ProxyConfig::from_path(proxy_path).map_err(|source| Error::ProxyReadError { source })?; + + // Open both the management and the incoming ports now + prx_svc.ports.reserve(proxy.incoming.len()); + for (port, _) in proxy.incoming { + prx_svc.ports.push(format!("0.0.0.0:{port}:{port}")); + } + } else { + // Otherwise, add it won't start + prx_svc.profiles = vec!["donotstart".into()]; } - } else { - // Otherwise, add it won't start - prx_svc.profiles = vec!["donotstart".into()]; } // Generate the override file for this node - ComposeOverrideFile { - version: "3.6", - services: HashMap::from([("brane-api", svc.clone()), ("brane-drv", svc.clone()), ("brane-plr", svc), ("brane-prx", prx_svc)]), - } + ComposeOverrideFile { version: "3.6", services } }, NodeSpecificConfig::Worker(node) => { - // Prepare a proxy service override - let mut prx_svc: ComposeOverrideFileService = svc.clone(); - if let Some(proxy_path) = &node.paths.proxy { - // Open the extra ports - - // Read the proxy file to find the incoming ports - let proxy: proxy::ProxyConfig = proxy::ProxyConfig::from_path(proxy_path).map_err(|source| Error::ProxyReadError { source })?; - - // Open both the management and the incoming ports now - prx_svc.ports.reserve(proxy.incoming.len()); - for (port, _) in proxy.incoming { - prx_svc.ports.push(format!("0.0.0.0:{port}:{port}")); + let mut services = WorkerKind::iter() + .map(|service| { + let mut service_override = svc.clone(); + + if let Some(log_level) = get_log_level(ServiceKind::Worker(service)) { + service_override.environment.push(format!("RUST_LOG={}", log_level)); + println!("Setting loglevel to {log_level}"); + } + (service.to_service_name(), service_override) + }) + .collect::>(); + { + // Prepare a proxy service override + // Unwrap: This comes from an exhaustive iterator therefore there *MUST* be a + // checker. + let prx_svc = services.get_mut(WorkerKind::Prx.to_service_name()).unwrap(); + if let Some(proxy_path) = &node.paths.proxy { + // Open the extra ports + + // Read the proxy file to find the incoming ports + let proxy: proxy::ProxyConfig = proxy::ProxyConfig::from_path(proxy_path).map_err(|source| Error::ProxyReadError { source })?; + + // Open both the management and the incoming ports now + prx_svc.ports.reserve(proxy.incoming.len()); + for (port, _) in proxy.incoming { + prx_svc.ports.push(format!("0.0.0.0:{port}:{port}")); + } + } else { + // Otherwise, add it won't start + prx_svc.profiles = vec!["donotstart".into()]; } - } else { - // Otherwise, add it won't start - prx_svc.profiles = vec!["donotstart".into()]; } - - // Also a checker override - let mut chk_svc: ComposeOverrideFileService = svc.clone(); - if let Some(policy_audit_log) = &node.paths.policy_audit_log { - chk_svc.volumes.push(format!("{}:/audit-log.log", policy_audit_log.display())); + { + // Also a checker override + // Unwrap: This comes from an exhaustive iterator therefore there *MUST* be a + // checker. + let chk_svc = services.get_mut(WorkerKind::Chk.to_service_name()).unwrap(); + if let Some(policy_audit_log) = &node.paths.policy_audit_log { + chk_svc.volumes.push(format!("{}:/audit-log.log", policy_audit_log.display())); + } } // Generate the override file for this node - ComposeOverrideFile { - version: "3.6", - services: HashMap::from([("brane-reg", svc.clone()), ("brane-job", svc), ("brane-chk", chk_svc), ("brane-prx", prx_svc)]), - } + ComposeOverrideFile { version: "3.6", services } }, NodeSpecificConfig::Proxy(node) => { @@ -721,10 +852,6 @@ fn run_compose( Ok(()) } - - - - /***** LIBRARY *****/ /// Starts the local node by running the given docker-compose file. /// @@ -891,8 +1018,6 @@ pub async fn start( Ok(()) } - - /// Stops the (currently running) local node. /// /// This is a very simple command, no more than a wrapper around docker-compose. From 2fd923ada0330bc69bb25ce750936af99c78a277 Mon Sep 17 00:00:00 2001 From: Daniel Voogsgerd Date: Tue, 8 Oct 2024 12:05:06 +0200 Subject: [PATCH 2/4] fix: Generate override even without hosts This guard clause was a correct optimization before we set loglevels via overrides --- brane-ctl/src/lifetime.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/brane-ctl/src/lifetime.rs b/brane-ctl/src/lifetime.rs index 3fe110f5..0ba7d4e1 100644 --- a/brane-ctl/src/lifetime.rs +++ b/brane-ctl/src/lifetime.rs @@ -414,7 +414,7 @@ fn get_log_level(service: ServiceKind) -> Option { match std::env::var(&log_var) { Ok(val) => return Some(val), // TODO: Could use the trace! macro from error-trace. - Err(err) => tracing::info!( + Err(err) => tracing::trace!( "Malformed log level set using environment variable `{log_var}`. Falling back to using `BRANE_LOG`, if it is set. Cause: \n{err:#}" ), }; @@ -423,7 +423,7 @@ fn get_log_level(service: ServiceKind) -> Option { Ok(val) => return Some(val), // TODO: Could use the trace! macro from error-trace. Err(err) => { - tracing::info!("Malformed log level set using environment variable `BRANE_LOG`. Continuing with default logging. Cause: \n{err:#}") + tracing::trace!("Malformed log level set using environment variable `BRANE_LOG`. Continuing with default logging. Cause: \n{err:#}") }, }; @@ -443,11 +443,6 @@ fn get_log_level(service: ServiceKind) -> Option { /// # Errors /// This function errors if we failed to write the file. fn generate_override_file(node_config: &NodeConfig, hosts: &HashMap, profile_dir: Option) -> Result, Error> { - // Early quit if there's nothing to do - if hosts.is_empty() { - return Ok(None); - } - // Generate the ComposeOverrideFileService let svc: ComposeOverrideFileService = ComposeOverrideFileService { volumes: if let Some(dir) = profile_dir { vec![format!("{}:/logs/profile", dir.display())] } else { vec![] }, From 650612e6e1ae0ad38b15a15b82375259d977af83 Mon Sep 17 00:00:00 2001 From: Daniel Voogsgerd Date: Mon, 24 Mar 2025 17:30:59 +0100 Subject: [PATCH 3/4] chore(api): Replace log with tracing --- Cargo.lock | 2 -- brane-api/Cargo.toml | 2 -- brane-api/src/data.rs | 2 +- brane-api/src/infra.rs | 2 +- brane-api/src/main.rs | 4 ++-- brane-api/src/packages.rs | 2 +- brane-api/src/schema.rs | 2 +- 7 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 150d6917..e0a6f3fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -520,11 +520,9 @@ dependencies = [ "clap", "dotenvy", "enum-debug", - "env_logger 0.11.7", "error-trace", "juniper", "juniper_warp", - "log", "rand 0.9.0", "reqwest 0.12.14", "scylla", diff --git a/brane-api/Cargo.toml b/brane-api/Cargo.toml index 72914c94..26ed1729 100644 --- a/brane-api/Cargo.toml +++ b/brane-api/Cargo.toml @@ -14,12 +14,10 @@ chrono = "0.4.35" clap = { version = "4.5.6", features = ["derive","env"] } dotenvy = "0.15" enum-debug.workspace = true -env_logger = "0.11.0" error-trace.workspace = true juniper = { version = "0.16.1", features = ["chrono"] } juniper_warp = "0.8.0" # k8s-openapi = { version = "0.14", default-features = false, features = ["v1_23"] } -log = "0.4.22" rand = "0.9.0" # rdkafka = { version = "0.31", features = ["cmake-build"] } reqwest = { version = "0.12.0", features = ["rustls-tls-manual-roots"] } diff --git a/brane-api/src/data.rs b/brane-api/src/data.rs index d26cc179..30192acd 100644 --- a/brane-api/src/data.rs +++ b/brane-api/src/data.rs @@ -19,9 +19,9 @@ use brane_cfg::info::Info as _; use brane_cfg::infra::InfraFile; use brane_cfg::node::NodeConfig; use brane_prx::spec::NewPathRequestTlsOptions; -use log::{debug, error}; use reqwest::StatusCode; use specifications::data::{AssetInfo, DataInfo}; +use tracing::{debug, error, info}; use warp::http::{HeaderValue, Response}; use warp::hyper::Body; use warp::{Rejection, Reply}; diff --git a/brane-api/src/infra.rs b/brane-api/src/infra.rs index 04b33dde..dc202691 100644 --- a/brane-api/src/infra.rs +++ b/brane-api/src/infra.rs @@ -18,9 +18,9 @@ use brane_cfg::info::Info as _; use brane_cfg::infra::{InfraFile, InfraLocation}; use brane_cfg::node::NodeConfig; use brane_prx::spec::NewPathRequestTlsOptions; -use log::{debug, error}; use specifications::address::Address; use specifications::package::Capability; +use tracing::{debug, error}; use warp::hyper::header::HeaderValue; use warp::hyper::{Body, Response}; use warp::{Rejection, Reply}; diff --git a/brane-api/src/main.rs b/brane-api/src/main.rs index 8d0e5171..924934ad 100644 --- a/brane-api/src/main.rs +++ b/brane-api/src/main.rs @@ -29,9 +29,9 @@ use clap::Parser; use dotenvy::dotenv; use error_trace::trace; use juniper::EmptySubscription; -use log::{debug, error, info, warn}; use scylla::{Session, SessionBuilder}; use tokio::signal::unix::{Signal, SignalKind, signal}; +use tracing::{debug, error, info, warn}; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use warp::Filter; @@ -165,7 +165,7 @@ async fn main() { let version = warp::path("version").and(warp::path::end()).and_then(version::handle); // Construct the final routes - let routes = data.or(packages.or(infra.or(health.or(version.or(graphql))))).with(warp::log("brane-api")); + let routes = data.or(packages.or(infra.or(health.or(version.or(graphql))))).with(warp::trace::request()); // Run the server let handle = warp::serve(routes).try_bind_with_graceful_shutdown(central.services.api.bind, async { diff --git a/brane-api/src/packages.rs b/brane-api/src/packages.rs index 2973aba0..bde67e72 100644 --- a/brane-api/src/packages.rs +++ b/brane-api/src/packages.rs @@ -22,7 +22,6 @@ use async_compression::tokio::bufread::GzipDecoder; use brane_cfg::info::Info as _; use brane_cfg::node::{CentralConfig, NodeConfig, NodeKind}; use bytes::Buf; -use log::{debug, error, info, warn}; use rand::Rng; use rand::distr::Alphanumeric; use scylla::macros::{FromUserType, IntoUserType}; @@ -35,6 +34,7 @@ use tokio::fs as tfs; use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader}; use tokio_stream::StreamExt; use tokio_tar::{Archive, Entries, Entry}; +use tracing::{debug, error, info, warn}; use uuid::Uuid; use warp::http::{HeaderValue, StatusCode}; use warp::hyper::Body; diff --git a/brane-api/src/schema.rs b/brane-api/src/schema.rs index 6a65d46a..56cac69a 100644 --- a/brane-api/src/schema.rs +++ b/brane-api/src/schema.rs @@ -17,9 +17,9 @@ use std::str::FromStr; use chrono::{DateTime, TimeZone, Utc}; use juniper::{EmptySubscription, FieldResult, GraphQLObject, RootNode, graphql_object}; -use log::{debug, info}; use scylla::IntoTypedRows; use specifications::version::Version; +use tracing::{debug, info}; use crate::packages::PackageUdt; use crate::spec::Context; From 13d724d54e9d0f07d3455e7888a292215eeb3c36 Mon Sep 17 00:00:00 2001 From: Daniel Voogsgerd Date: Wed, 26 Mar 2025 16:18:55 +0100 Subject: [PATCH 4/4] wip --- Cargo.lock | 78 +++--- Cargo.toml | 8 +- brane-api/Cargo.toml | 11 +- brane-api/src/cli.rs | 5 +- brane-api/src/data.rs | 2 +- brane-api/src/main.rs | 15 +- brane-ast/Cargo.toml | 9 +- brane-ast/src/ast.rs | 9 +- brane-ast/src/compile.rs | 2 +- brane-ast/src/fetcher.rs | 2 +- brane-ast/src/traversals/compile.rs | 2 +- brane-ast/src/traversals/data.rs | 2 +- brane-ast/src/traversals/resolve.rs | 2 +- brane-ast/src/traversals/workflow_resolve.rs | 2 +- brane-cc/Cargo.toml | 10 +- brane-cc/src/cli.rs | 8 +- brane-cc/src/compile.rs | 2 +- brane-cc/src/main.rs | 16 +- brane-cfg/Cargo.toml | 4 +- brane-cfg/src/certs.rs | 2 +- brane-cli-c/Cargo.toml | 5 +- brane-cli-c/src/lib.rs | 7 +- brane-cli/Cargo.toml | 16 +- brane-cli/src/check.rs | 2 +- brane-cli/src/cli.rs | 7 +- brane-cli/src/instance.rs | 2 +- brane-cli/src/lib.rs | 2 +- brane-cli/src/main.rs | 21 +- brane-cli/src/planner.rs | 2 +- brane-cli/src/repl.rs | 2 +- brane-cli/src/run.rs | 4 +- brane-cli/src/upgrade.rs | 2 +- brane-cli/src/version.rs | 2 +- brane-cli/src/vm.rs | 2 +- brane-ctl/Cargo.toml | 25 +- brane-ctl/src/cli.rs | 18 +- brane-ctl/src/download.rs | 2 +- brane-ctl/src/generate.rs | 2 +- brane-ctl/src/lifetime.rs | 245 ++++++------------- brane-ctl/src/main.rs | 38 +-- brane-ctl/src/old_configs/v1_0_0/node.rs | 2 +- brane-ctl/src/packages.rs | 2 +- brane-ctl/src/policies.rs | 2 +- brane-ctl/src/unpack.rs | 2 +- brane-ctl/src/upgrade.rs | 2 +- brane-ctl/src/wizard.rs | 2 +- brane-drv/Cargo.toml | 11 +- brane-drv/src/check.rs | 4 +- brane-drv/src/cli.rs | 5 +- brane-drv/src/gc.rs | 2 +- brane-drv/src/handler.rs | 18 +- brane-drv/src/main.rs | 19 +- brane-drv/src/planner.rs | 2 +- brane-drv/src/vm.rs | 2 +- brane-dsl/Cargo.toml | 10 +- brane-dsl/src/compiler.rs | 2 +- brane-dsl/src/parser/bscript.rs | 2 +- brane-dsl/src/parser/expression.rs | 2 +- brane-dsl/src/parser/identifier.rs | 2 +- brane-dsl/src/parser/instance.rs | 2 +- brane-dsl/src/parser/literal.rs | 2 +- brane-dsl/src/parser/operator.rs | 2 +- brane-exe/Cargo.toml | 10 +- brane-exe/src/dummy.rs | 2 +- brane-exe/src/lib.rs | 2 +- brane-exe/src/stack.rs | 2 +- brane-exe/src/thread.rs | 8 +- brane-job/Cargo.toml | 13 +- brane-job/src/cli.rs | 5 +- brane-job/src/main.rs | 18 +- brane-job/src/worker.rs | 8 +- brane-let/Cargo.toml | 8 +- brane-let/src/callback.rs | 2 +- brane-let/src/cli.rs | 5 +- brane-let/src/common.rs | 2 +- brane-let/src/exec_ecu.rs | 2 +- brane-let/src/exec_nop.rs | 2 +- brane-let/src/main.rs | 25 +- brane-log/Cargo.toml | 34 +++ brane-log/src/main.rs | 134 ++++++++++ brane-plr/Cargo.toml | 10 +- brane-plr/src/cli.rs | 5 +- brane-plr/src/main.rs | 18 +- brane-plr/src/planner.rs | 2 +- brane-prx/Cargo.toml | 11 +- brane-prx/src/cli.rs | 5 +- brane-prx/src/client.rs | 2 +- brane-prx/src/main.rs | 21 +- brane-prx/src/manage.rs | 2 +- brane-prx/src/redirect.rs | 2 +- brane-reg/Cargo.toml | 13 +- brane-reg/src/check.rs | 2 +- brane-reg/src/cli.rs | 4 +- brane-reg/src/data.rs | 2 +- brane-reg/src/health.rs | 2 +- brane-reg/src/infra.rs | 2 +- brane-reg/src/main.rs | 22 +- brane-reg/src/server.rs | 2 +- brane-reg/src/store.rs | 2 +- brane-reg/src/version.rs | 2 +- brane-shr/Cargo.toml | 11 +- brane-shr/src/address.rs | 2 +- brane-shr/src/fs.rs | 2 +- brane-shr/src/input.rs | 2 +- brane-shr/src/kafka.rs | 2 +- brane-shr/src/utilities.rs | 10 +- brane-tsk/Cargo.toml | 11 +- brane-tsk/src/caches.rs | 2 +- brane-tsk/src/docker.rs | 2 +- brane-tsk/src/input.rs | 2 +- brane-tsk/src/k8s.rs | 2 +- brane-tsk/src/spec.rs | 2 +- specifications/Cargo.toml | 14 +- specifications/src/address.rs | 2 +- specifications/src/brane.rs | 111 +++++++++ specifications/src/cli.rs | 49 ++++ specifications/src/index.rs | 2 +- specifications/src/lib.rs | 3 + specifications/src/package.rs | 3 +- specifications/src/policy.rs | 2 +- specifications/src/profiling.rs | 2 +- specifications/src/tracing.rs | 18 ++ 122 files changed, 814 insertions(+), 551 deletions(-) create mode 100644 brane-log/Cargo.toml create mode 100644 brane-log/src/main.rs create mode 100644 specifications/src/brane.rs create mode 100644 specifications/src/cli.rs create mode 100644 specifications/src/tracing.rs diff --git a/Cargo.lock b/Cargo.lock index e0a6f3fd..fe9be317 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -549,7 +549,6 @@ dependencies = [ "console", "enum-debug", "lazy_static", - "log", "num-traits", "rand 0.9.0", "serde", @@ -557,6 +556,7 @@ dependencies = [ "specifications 3.0.0", "strum 0.27.1", "thiserror 2.0.12", + "tracing", "uuid", ] @@ -593,12 +593,12 @@ dependencies = [ "enum-debug", "expanduser", "human-panic 2.0.2", - "humanlog", - "log", "serde_json", "specifications 3.0.0", "thiserror 2.0.12", "tokio", + "tracing", + "tracing-subscriber", "url", ] @@ -608,7 +608,6 @@ version = "3.0.0" dependencies = [ "async-trait", "enum-debug", - "log", "rustls 0.21.12", "rustls-pemfile 1.0.4", "serde", @@ -616,6 +615,7 @@ dependencies = [ "specifications 3.0.0", "thiserror 2.0.12", "tokio", + "tracing", "x509-parser", ] @@ -647,11 +647,9 @@ dependencies = [ "futures-util", "graphql_client", "human-panic 2.0.2", - "humanlog", "hyper 1.6.0", "indicatif", "lazy_static", - "log", "names", "parking_lot", "path-clean", @@ -672,6 +670,8 @@ dependencies = [ "tokio-stream", "tokio-util", "tonic 0.12.3", + "tracing", + "tracing-subscriber", "uuid", "x509-parser", ] @@ -685,12 +685,11 @@ dependencies = [ "brane-exe 3.0.0", "brane-tsk", "console", - "humanlog", "libc", - "log", "parking_lot", "specifications 3.0.0", "tokio", + "tracing", ] [[package]] @@ -716,11 +715,9 @@ dependencies = [ "error-trace", "hex-literal", "human-panic 2.0.2", - "humanlog", "humantime", "jsonwebtoken", "lazy_static", - "log", "names", "policy", "rand 0.9.0", @@ -731,12 +728,12 @@ dependencies = [ "shlex", "specifications 3.0.0", "srv", - "strum 0.26.3", - "strum_macros 0.26.4", + "strum 0.27.1", "tempfile", "thiserror 2.0.12", "tokio", "tracing", + "tracing-subscriber", ] [[package]] @@ -756,7 +753,6 @@ dependencies = [ "enum-debug", "env_logger 0.11.7", "error-trace", - "log", "reqwest 0.12.14", "serde_json", "serde_json_any_key", @@ -765,6 +761,8 @@ dependencies = [ "tokio", "tokio-stream", "tonic 0.12.3", + "tracing", + "tracing-subscriber", ] [[package]] @@ -773,7 +771,6 @@ version = "3.0.0" dependencies = [ "brane-shr 3.0.0", "enum-debug", - "log", "nom", "nom_locate", "rand 0.9.0", @@ -781,6 +778,7 @@ dependencies = [ "serde", "specifications 3.0.0", "thiserror 2.0.12", + "tracing", ] [[package]] @@ -815,15 +813,14 @@ dependencies = [ "console", "enum-debug", "futures", - "humanlog", "lazy_static", - "log", "num-traits", "serde", "serde_json", "specifications 3.0.0", "thiserror 2.0.12", "tokio", + "tracing", ] [[package]] @@ -870,7 +867,6 @@ dependencies = [ "error-trace", "futures-util", "hyper 1.6.0", - "log", "reqwest 0.12.14", "serde", "serde_json", @@ -881,6 +877,8 @@ dependencies = [ "tokio", "tokio-stream", "tonic 0.12.3", + "tracing", + "tracing-subscriber", ] [[package]] @@ -895,7 +893,6 @@ dependencies = [ "dotenvy", "env_logger 0.11.7", "libc", - "log", "serde", "serde_json", "serde_yml", @@ -903,6 +900,7 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tonic 0.12.3", + "tracing", "yaml-rust2", ] @@ -918,8 +916,6 @@ dependencies = [ "clap", "dotenvy", "error-trace", - "humanlog", - "log", "parking_lot", "rand 0.9.0", "reqwest 0.12.14", @@ -927,6 +923,8 @@ dependencies = [ "specifications 3.0.0", "tokio", "tonic 0.12.3", + "tracing", + "tracing-subscriber", "warp", ] @@ -941,7 +939,6 @@ dependencies = [ "dotenvy", "env_logger 0.11.7", "error-trace", - "log", "never-say-never", "reqwest 0.12.14", "rustls 0.21.12", @@ -952,6 +949,8 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tokio-rustls 0.24.1", + "tracing", + "tracing-subscriber", "url", "warp", ] @@ -971,7 +970,6 @@ dependencies = [ "enum-debug", "env_logger 0.11.7", "error-trace", - "log", "reqwest 0.12.14", "rustls 0.21.12", "serde", @@ -982,6 +980,8 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tokio-rustls 0.24.1", + "tracing", + "tracing-subscriber", "warp", ] @@ -995,9 +995,7 @@ dependencies = [ "enum-debug", "fs2", "hex", - "humanlog", "indicatif", - "log", "rand 0.9.0", "regex", "reqwest 0.12.14", @@ -1008,6 +1006,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-tar", + "tracing", "url", ] @@ -1056,9 +1055,7 @@ dependencies = [ "enum-debug", "futures-util", "graphql_client", - "humanlog", "lazy_static", - "log", "num-traits", "parking_lot", "rand 0.9.0", @@ -1073,6 +1070,7 @@ dependencies = [ "tokio-tar", "tokio-util", "tonic 0.12.3", + "tracing", "uuid", ] @@ -1160,9 +1158,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.46" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5c5508ea23c5366f77e53f5a0070e5a84e51687ec3ef9e0464c86dc8d13ce98" +checksum = "c06f5378ea264ad4f82bbc826628b5aad714a75abf6ece087e923010eb937fb6" dependencies = [ "clap", ] @@ -4442,11 +4440,11 @@ dependencies = [ "base64 0.22.1", "base64ct", "chrono", + "clap", "const_format", "enum-debug", "futures", "jsonwebtoken", - "log", "parking_lot", "prost 0.13.5", "reqwest 0.12.14", @@ -4457,9 +4455,10 @@ dependencies = [ "serde_with", "serde_yml", "strum 0.27.1", - "strum_macros 0.27.1", "thiserror 2.0.12", "tonic 0.12.3", + "tracing", + "tracing-subscriber", "uuid", ] @@ -4575,12 +4574,6 @@ dependencies = [ "strum_macros 0.25.3", ] -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" - [[package]] name = "strum" version = "0.27.1" @@ -4629,19 +4622,6 @@ dependencies = [ "syn 2.0.100", ] -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.100", -] - [[package]] name = "strum_macros" version = "0.27.1" diff --git a/Cargo.toml b/Cargo.toml index a1ae1d91..30c15284 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,13 +65,19 @@ license = "Apache-2.0" [workspace.dependencies] # Lut99 Crates -humanlog = { git = "https://github.com/Lut99/humanlog-rs", tag = "v0.2.0" } enum-debug = { git = "https://github.com/Lut99/enum-debug", tag = "v1.1.0", features = ["derive"] } error-trace = { git = "https://github.com/Lut99/error-trace-rs", tag = "v3.0.0" } transform = { git = "https://github.com/Lut99/transform-rs", tag = "v0.2.0" } names = { git = "https://github.com/Lut99/names-rs", tag = "v0.1.0", default-features = false, features = [ "rand", "three-lowercase" ]} download = { git = "https://github.com/Lut99/download-rs", tag = "v0.1.0", default-features = false, features = ["download"] } +# Other crates +clap = { version = "4.4.0", features = ["derive", "env"] } +strum = "0.27.0" +thiserror = { version = "2.0.0" } +tracing = { version = "0.1.36" } +tracing-subscriber = { version = "0.3.10", features = ["env-filter"] } + [workspace.lints.clippy] result_large_err = { level = "allow", priority = 1 } suspicious = "deny" diff --git a/brane-api/Cargo.toml b/brane-api/Cargo.toml index 26ed1729..a7ba3235 100644 --- a/brane-api/Cargo.toml +++ b/brane-api/Cargo.toml @@ -11,10 +11,7 @@ authors.workspace = true async-compression = { version = "0.4.0", features = ["tokio","gzip"] } bytes = "1.2.0" chrono = "0.4.35" -clap = { version = "4.5.6", features = ["derive","env"] } dotenvy = "0.15" -enum-debug.workspace = true -error-trace.workspace = true juniper = { version = "0.16.1", features = ["chrono"] } juniper_warp = "0.8.0" # k8s-openapi = { version = "0.14", default-features = false, features = ["v1_23"] } @@ -32,8 +29,12 @@ tokio-tar = "0.3.0" uuid = { version = "1.7.0", features = ["serde", "v4"] } warp = "0.3.2" -tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +# Workspace dependencies +clap.workspace = true +enum-debug.workspace = true +error-trace.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true brane-cfg = { path = "../brane-cfg" } brane-prx = { path = "../brane-prx" } diff --git a/brane-api/src/cli.rs b/brane-api/src/cli.rs index 2b94d422..6d726b26 100644 --- a/brane-api/src/cli.rs +++ b/brane-api/src/cli.rs @@ -6,9 +6,8 @@ use clap::Parser; #[derive(Parser)] #[clap(version = env!("CARGO_PKG_VERSION"))] pub(crate) struct Cli { - /// Print debug info - #[clap(short, long, env = "DEBUG")] - pub(crate) debug: bool, + #[clap(flatten)] + pub(crate) logging: specifications::cli::Tracing, /// Load everything from the node.yml file #[clap( diff --git a/brane-api/src/data.rs b/brane-api/src/data.rs index 30192acd..5ddca8a7 100644 --- a/brane-api/src/data.rs +++ b/brane-api/src/data.rs @@ -21,7 +21,7 @@ use brane_cfg::node::NodeConfig; use brane_prx::spec::NewPathRequestTlsOptions; use reqwest::StatusCode; use specifications::data::{AssetInfo, DataInfo}; -use tracing::{debug, error, info}; +use tracing::{debug, error}; use warp::http::{HeaderValue, Response}; use warp::hyper::Body; use warp::{Rejection, Reply}; diff --git a/brane-api/src/main.rs b/brane-api/src/main.rs index 924934ad..2d1eb890 100644 --- a/brane-api/src/main.rs +++ b/brane-api/src/main.rs @@ -32,10 +32,13 @@ use juniper::EmptySubscription; use scylla::{Session, SessionBuilder}; use tokio::signal::unix::{Signal, SignalKind, signal}; use tracing::{debug, error, info, warn}; -use tracing_subscriber::layer::SubscriberExt; -use tracing_subscriber::util::SubscriberInitExt; use warp::Filter; +/***** CONSTANTS *****/ +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: tracing::level_filters::LevelFilter = tracing::level_filters::LevelFilter::INFO; +/// The environment variable used by env-filter in tracing subscriber +const LOG_LEVEL_ENV_VAR: &str = "BRANE_API_LOG"; /***** ENTRYPOINT *****/ #[tokio::main] @@ -43,12 +46,10 @@ async fn main() { dotenv().ok(); let opts = cli::Cli::parse(); - tracing_subscriber::registry() - .with(tracing_subscriber::fmt::layer()) - .with(tracing_subscriber::EnvFilter::builder().with_default_directive(tracing::level_filters::LevelFilter::WARN.into()).from_env_lossy()) - .init(); + let cli_log_level = opts.logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); - tracing::info!("Initializing brane-job v{}...", env!("CARGO_PKG_VERSION")); + info!("Initializing brane-job v{}...", env!("CARGO_PKG_VERSION")); // Load the config, making sure it's a worker config debug!("Loading node.yml file '{}'...", opts.node_config_path.display()); diff --git a/brane-ast/Cargo.toml b/brane-ast/Cargo.toml index 50479e52..405fcf26 100644 --- a/brane-ast/Cargo.toml +++ b/brane-ast/Cargo.toml @@ -11,15 +11,18 @@ license.workspace = true console = "0.15.5" enum-debug.workspace = true lazy_static = "1.4.0" -log = "0.4.22" rand = "0.9.0" num-traits = "0.2.18" serde = { version = "1.0.204", features = ["rc"] } serde_json_any_key = "2.0.0" -strum = { version = "0.27.0", features = ["derive"] } -thiserror = "2.0.0" uuid = { version = "1.7.0", features = ["serde", "v4"] } +# Workspace dependencies +strum = { workspace = true, features = ["derive"] } +thiserror.workspace = true +tracing.workspace = true + +# Intra workspace dependencies brane-dsl = { path = "../brane-dsl" } brane-shr = { path = "../brane-shr" } specifications = { path = "../specifications" } diff --git a/brane-ast/src/ast.rs b/brane-ast/src/ast.rs index ae8fa38b..1396b746 100644 --- a/brane-ast/src/ast.rs +++ b/brane-ast/src/ast.rs @@ -25,7 +25,6 @@ use std::sync::Arc; use brane_dsl::ParserOptions; use brane_dsl::spec::MergeStrategy; use enum_debug::EnumDebug; -use log::debug; use rand::Rng as _; use rand::distr::Alphanumeric; use serde::de::{self, Deserializer, Visitor}; @@ -35,6 +34,7 @@ use serde_json_any_key::any_key_map; use specifications::data::{AvailabilityKind, DataIndex, DataName}; use specifications::package::{Capability, PackageIndex}; use specifications::version::Version; +use tracing::debug; use crate::data_type::DataType; use crate::errors::CompileError; @@ -197,9 +197,10 @@ impl Workflow { }, }; debug!("Compiled to workflow:\n\n"); - if log::max_level() == log::LevelFilter::Debug { - crate::traversals::print::ast::do_traversal(&workflow, std::io::stdout()).unwrap(); - } + // TODO: Implement tracing + // if tracing::max_level() == tracing::LevelFilter::Debug { + // crate::traversals::print::ast::do_traversal(&workflow, std::io::stdout()).unwrap(); + // } // Return Ok(workflow) diff --git a/brane-ast/src/compile.rs b/brane-ast/src/compile.rs index 14a5bd43..0743ca72 100644 --- a/brane-ast/src/compile.rs +++ b/brane-ast/src/compile.rs @@ -16,9 +16,9 @@ use std::fmt::{Display, Formatter, Result as FResult}; use brane_dsl::ast::Program; use brane_dsl::{Error as ParseError, ParserOptions}; -use log::trace; use specifications::data::DataIndex; use specifications::package::PackageIndex; +use tracing::trace; use crate::ast::Workflow; use crate::ast_unresolved::UnresolvedWorkflow; diff --git a/brane-ast/src/fetcher.rs b/brane-ast/src/fetcher.rs index 29feb943..24fbd08e 100644 --- a/brane-ast/src/fetcher.rs +++ b/brane-ast/src/fetcher.rs @@ -16,7 +16,7 @@ use std::error::Error; use brane_dsl::TextPos; -use log::error; +use tracing::error; /***** LIBRARY *****/ diff --git a/brane-ast/src/traversals/compile.rs b/brane-ast/src/traversals/compile.rs index 20531c55..71b7053e 100644 --- a/brane-ast/src/traversals/compile.rs +++ b/brane-ast/src/traversals/compile.rs @@ -23,8 +23,8 @@ use brane_dsl::ast as dsl; use brane_dsl::spec::MergeStrategy; use brane_dsl::symbol_table::{FunctionEntry, VarEntry}; use enum_debug::EnumDebug as _; -use log::warn; use specifications::data::DataName; +use tracing::warn; use crate::ast; use crate::ast_unresolved::UnresolvedWorkflow; diff --git a/brane-ast/src/traversals/data.rs b/brane-ast/src/traversals/data.rs index 60da9d2d..0f7de2b3 100644 --- a/brane-ast/src/traversals/data.rs +++ b/brane-ast/src/traversals/data.rs @@ -21,7 +21,7 @@ use brane_dsl::ast::{Block, Data, Expr, Program, Stmt}; use brane_dsl::symbol_table::{ClassEntry, FunctionEntry, SymbolTableEntry, VarEntry}; use brane_dsl::{DataType, SymbolTable}; use enum_debug::EnumDebug as _; -use log::debug; +use tracing::debug; use uuid::Uuid; use crate::errors::AstError; diff --git a/brane-ast/src/traversals/resolve.rs b/brane-ast/src/traversals/resolve.rs index c392775d..1d3955b6 100644 --- a/brane-ast/src/traversals/resolve.rs +++ b/brane-ast/src/traversals/resolve.rs @@ -23,10 +23,10 @@ use brane_dsl::spec::MergeStrategy; use brane_dsl::symbol_table::{ClassEntry, FunctionEntry, SymbolTableEntry, VarEntry}; use brane_dsl::{DataType, SymbolTable, TextRange}; use enum_debug::EnumDebug as _; -use log::trace; use specifications::data::DataIndex; use specifications::package::{PackageIndex, PackageInfo}; use specifications::version::Version; +use tracing::trace; use crate::errors::AstError; pub use crate::errors::ResolveError as Error; diff --git a/brane-ast/src/traversals/workflow_resolve.rs b/brane-ast/src/traversals/workflow_resolve.rs index a94adaa3..e21a981f 100644 --- a/brane-ast/src/traversals/workflow_resolve.rs +++ b/brane-ast/src/traversals/workflow_resolve.rs @@ -16,7 +16,7 @@ use std::cell::Ref; use std::collections::HashMap; -use log::debug; +use tracing::debug; use crate::ast::{Edge, SymTable, Workflow}; use crate::ast_unresolved::UnresolvedWorkflow; diff --git a/brane-cc/Cargo.toml b/brane-cc/Cargo.toml index e51207c2..fd7ac15f 100644 --- a/brane-cc/Cargo.toml +++ b/brane-cc/Cargo.toml @@ -12,16 +12,18 @@ name = "branec" path = "src/main.rs" [dependencies] -clap = { version = "4.5.6", features = ["derive","env"] } dotenvy = "0.15.0" -enum-debug.workspace = true -humanlog.workspace = true human-panic = "2.0.0" -log = "0.4.22" thiserror = "2.0.0" tokio = { version = "1.38.0", features = ["rt","macros"] } url = "2.5.0" +# Workspace dependencies +clap.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +enum-debug.workspace = true + brane-ast = { path = "../brane-ast" } brane-dsl = { path = "../brane-dsl" } brane-shr = { path = "../brane-shr" } diff --git a/brane-cc/src/cli.rs b/brane-cc/src/cli.rs index 9357a759..dad8c1da 100644 --- a/brane-cc/src/cli.rs +++ b/brane-cc/src/cli.rs @@ -6,12 +6,8 @@ use clap::Parser; #[derive(Parser)] #[clap(name = "branec", author, about = "An offline compiler for BraneScript/Bakery to Workflows.")] pub(crate) struct Cli { - /// If given, shows debug prints. - #[clap(long, help = "If given, shows INFO- and DEBUG-level prints in the log.", env = "DEBUG")] - pub(crate) debug: bool, - /// If given, shows additional trace prints. - #[clap(long, help = "If given, shows TRACE-level prints in the log. Implies '--debug'", env = "TRACE")] - pub(crate) trace: bool, + #[clap(flatten)] + pub(crate) logging: specifications::cli::Tracing, /// The file(s) to compile. May be '-' to compile from stdin. #[clap(name = "FILES", help = "The input files to compile. Use '-' to read from stdin.")] diff --git a/brane-cc/src/compile.rs b/brane-cc/src/compile.rs index 21edc50d..48e6c649 100644 --- a/brane-cc/src/compile.rs +++ b/brane-cc/src/compile.rs @@ -17,7 +17,7 @@ use std::fs::File; use std::io::{Read, Write}; use std::path::{Path, PathBuf}; -use log::debug; +use tracing::debug; use brane_dsl::Language; use brane_ast::{compile_snippet, CompileResult, ParserOptions, Workflow}; diff --git a/brane-cc/src/main.rs b/brane-cc/src/main.rs index 5ab7ffe4..dc2f4289 100644 --- a/brane-cc/src/main.rs +++ b/brane-cc/src/main.rs @@ -30,11 +30,15 @@ use dotenvy::dotenv; #[cfg(unix)] use expanduser::expanduser; use human_panic::setup_panic; -use humanlog::{DebugMode, HumanLogger}; -use log::{debug, error, info, warn}; use specifications::data::DataIndex; use specifications::package::PackageIndex; +use tracing::{debug, error, info, warn}; +/***** CONSTANTS *****/ +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: tracing::level_filters::LevelFilter = tracing::level_filters::LevelFilter::INFO; +/// The environment variable used by env-filter in tracing subscriber +const LOG_LEVEL_ENV_VAR: &str = "BRANE_CC_LOG"; /***** ENTRYPOINT *****/ @@ -47,13 +51,13 @@ async fn main() { let mut args = cli::Cli::parse(); // Setup the logger - if let Err(err) = HumanLogger::terminal(DebugMode::from_flags(args.trace, args.debug)).init() { - eprintln!("WARNING: Failed to setup logger: {err} (logging disabled for this session)"); - } + let cli_log_level = args.logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); + info!("Initializing branec v{}", env!("CARGO_PKG_VERSION")); // Setup the panic mode - if !args.trace && !args.debug { + if !args.logging.trace && !args.logging.debug { setup_panic!(); } diff --git a/brane-cfg/Cargo.toml b/brane-cfg/Cargo.toml index e3066e47..61f6e135 100644 --- a/brane-cfg/Cargo.toml +++ b/brane-cfg/Cargo.toml @@ -10,7 +10,6 @@ license.workspace = true [dependencies] async-trait = "0.1.67" enum-debug.workspace = true -log = "0.4.22" rustls = "0.21.6" rustls-pemfile = "1.0.1" serde = { version = "1.0.204", features = ["derive"] } @@ -19,6 +18,9 @@ thiserror = "2.0.0" tokio = { version = "1.38.0", features = [] } x509-parser = "0.17.0" +# Workspace dependencies +tracing.workspace = true + specifications = { path = "../specifications" } [lints] diff --git a/brane-cfg/src/certs.rs b/brane-cfg/src/certs.rs index ef9ce38f..643cabbf 100644 --- a/brane-cfg/src/certs.rs +++ b/brane-cfg/src/certs.rs @@ -16,9 +16,9 @@ use std::path::Path; use std::{fs, io}; -use log::debug; use rustls::{Certificate, PrivateKey, RootCertStore}; use rustls_pemfile::{Item, certs, rsa_private_keys}; +use tracing::debug; use x509_parser::certificate::X509Certificate; use x509_parser::prelude::FromDer; diff --git a/brane-cli-c/Cargo.toml b/brane-cli-c/Cargo.toml index 9d2c8683..a72ae6c9 100644 --- a/brane-cli-c/Cargo.toml +++ b/brane-cli-c/Cargo.toml @@ -17,12 +17,13 @@ doc = false [dependencies] console = "0.15.5" -humanlog.workspace = true libc = "0.2.154" -log = "0.4.22" parking_lot = "0.12.1" tokio = "1.38.0" +# Workspace dependencies +tracing.workspace = true + brane-ast = { path = "../brane-ast" } brane-cli = { path = "../brane-cli" } brane-exe = { path = "../brane-exe" } diff --git a/brane-cli-c/src/lib.rs b/brane-cli-c/src/lib.rs index e67f1c23..aa7fc3af 100644 --- a/brane-cli-c/src/lib.rs +++ b/brane-cli-c/src/lib.rs @@ -35,12 +35,11 @@ use brane_cli::run::{InstanceVmState, initialize_instance, run_instance}; use brane_exe::FullValue; use brane_tsk::api::{get_data_index, get_package_index}; use console::style; -use humanlog::{DebugMode, HumanLogger}; -use log::{debug, error, info, trace}; use parking_lot::{Mutex, MutexGuard}; use specifications::data::DataIndex; use specifications::package::PackageIndex; use tokio::runtime::{Builder, Runtime}; +use tracing::{debug, error, info, trace}; /***** CONSTANTS *****/ @@ -68,9 +67,7 @@ static RUNTIME: Mutex>> = Mutex::new(None); #[inline] fn init_logger() { LOG_INIT.call_once(|| { - if let Err(err) = HumanLogger::terminal(DebugMode::Debug).init() { - eprintln!("WARNING: Failed to setup Rust logger: {err} (logging disabled for this session)"); - } + // TODO: Set up tracing }); } diff --git a/brane-cli/Cargo.toml b/brane-cli/Cargo.toml index 0dcb4b64..10d0c1c5 100644 --- a/brane-cli/Cargo.toml +++ b/brane-cli/Cargo.toml @@ -23,25 +23,20 @@ async-trait = "0.1.67" base64 = "0.22.0" bollard = "0.18.0" chrono = "0.4.35" -clap = { version = "4.5.6", features = ["derive","env"] } +clap.workspace = true console = "0.15.5" dialoguer = "0.11.0" dirs = "6.0.0" dotenvy = "0.15.0" -enum-debug.workspace = true -error-trace.workspace = true flate2 = { version = "1.0.13", features = ["zlib"], default-features = false } fs_extra = "1.2.0" futures-util = "0.3.30" # git2 = { version = "0.17", features = ["vendored-libgit2"] } graphql_client = "0.14.0" -humanlog.workspace = true human-panic = "2.0.0" hyper = "1.3.0" indicatif = "0.17.0" lazy_static = "1.4.0" -log = "0.4.22" -names.workspace = true parking_lot = "0.12.1" path-clean = "1.0.0" prettytable-rs = "0.10.0" @@ -63,6 +58,13 @@ tonic = "0.12.0" uuid = { version = "1.7.0", features = ["serde", "v4"] } x509-parser = "0.17.0" +# Workspace dependencies +enum-debug.workspace = true +error-trace.workspace = true +names.workspace = true +tracing-subscriber.workspace = true +tracing.workspace = true + brane-ast = { path = "../brane-ast" } brane-cfg = { path = "../brane-cfg" } brane-dsl = { path = "../brane-dsl" } @@ -70,7 +72,7 @@ brane-exe = { path = "../brane-exe" } brane-shr = { path = "../brane-shr" } brane-tsk = { path = "../brane-tsk" } specifications = { path = "../specifications" } -clap_complete = "4.5.8" +clap_complete = "4.4.0" [features] print_exec_path = [ "brane-exe/print_exec_path" ] diff --git a/brane-cli/src/check.rs b/brane-cli/src/check.rs index 676a3edc..545432ee 100644 --- a/brane-cli/src/check.rs +++ b/brane-cli/src/check.rs @@ -21,11 +21,11 @@ use brane_ast::{CompileResult, Workflow}; use brane_dsl::{Language, ParserOptions}; use console::style; use error_trace::trace; -use log::{debug, info}; use specifications::data::DataIndex; use specifications::driving::{CheckReply, CheckRequest, DriverServiceClient}; use specifications::package::PackageIndex; use specifications::profiling::{self}; +use tracing::{debug, info}; pub use crate::errors::CheckError as Error; use crate::instance::InstanceInfo; diff --git a/brane-cli/src/cli.rs b/brane-cli/src/cli.rs index 5f74bd0d..23215b04 100644 --- a/brane-cli/src/cli.rs +++ b/brane-cli/src/cli.rs @@ -11,10 +11,11 @@ use specifications::version::Version as SemVersion; #[derive(Parser)] #[clap(name = "brane", about = "The Brane command-line interface.")] pub(crate) struct Cli { - #[clap(long, global = true, action, help = "Enable debug mode")] - pub(crate) debug: bool, + #[clap(flatten)] + pub logging: specifications::cli::Tracing, + #[clap(long, action, help = "Skip dependencies check")] - pub(crate) skip_check: bool, + pub(crate) skip_check: bool, #[clap(subcommand)] pub(crate) sub_command: SubCommand, } diff --git a/brane-cli/src/instance.rs b/brane-cli/src/instance.rs index 37858769..91b95551 100644 --- a/brane-cli/src/instance.rs +++ b/brane-cli/src/instance.rs @@ -23,11 +23,11 @@ use std::str::FromStr; use brane_shr::formatters::PrettyListFormatter; use console::{Alignment, pad_str, style}; use dialoguer::Confirm; -use log::{debug, info, warn}; use prettytable::Table; use prettytable::format::FormatBuilder; use serde::{Deserialize, Serialize}; use specifications::address::Address; +use tracing::{debug, info, warn}; pub use crate::errors::InstanceError as Error; use crate::spec::Hostname; diff --git a/brane-cli/src/lib.rs b/brane-cli/src/lib.rs index 105e1f44..592781e6 100644 --- a/brane-cli/src/lib.rs +++ b/brane-cli/src/lib.rs @@ -1,7 +1,7 @@ #[macro_use] extern crate anyhow; #[macro_use] -extern crate log; +extern crate tracing; #[macro_use] extern crate prettytable; #[macro_use] diff --git a/brane-cli/src/main.rs b/brane-cli/src/main.rs index f69ddcdc..81674527 100644 --- a/brane-cli/src/main.rs +++ b/brane-cli/src/main.rs @@ -31,14 +31,20 @@ use clap::Parser; use cli::*; use dotenvy::dotenv; use error_trace::ErrorTrace as _; -use humanlog::{DebugMode, HumanLogger}; -// use git2::Repository; -use log::{error, info}; use specifications::arch::Arch; use specifications::package::PackageKind; use specifications::version::Version as SemVersion; use tempfile::TempDir; +use tracing::level_filters::LevelFilter; +// use git2::Repository; +use tracing::{error, info}; + +// Constants +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: LevelFilter = LevelFilter::INFO; +/// Tracing log filter used by brane-cli +const LOG_LEVEL_ENV_VAR: &str = "BRANE_CLI_LOG"; /***** ENTRYPOINT *****/ @@ -48,14 +54,13 @@ async fn main() -> Result<()> { dotenv().ok(); let options = cli::Cli::parse(); - // Prepare the logger - if let Err(err) = HumanLogger::terminal(if options.debug { DebugMode::Debug } else { DebugMode::HumanFriendly }).init() { - eprintln!("WARNING: Failed to setup logger: {err} (no logging for this session)"); - } + let cli_log_level = options.logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); + info!("{} - v{}", env!("CARGO_BIN_NAME"), env!("CARGO_PKG_VERSION")); // Also setup humanpanic - if !options.debug { + if !options.logging.debug { setup_panic!(); } diff --git a/brane-cli/src/planner.rs b/brane-cli/src/planner.rs index 2cf2bac0..ba538e1b 100644 --- a/brane-cli/src/planner.rs +++ b/brane-cli/src/planner.rs @@ -22,9 +22,9 @@ use brane_ast::Workflow; use brane_ast::ast::{Edge, SymTable}; use brane_tsk::errors::PlanError; use brane_tsk::spec::{LOCALHOST, Planner}; -use log::debug; use parking_lot::Mutex; use specifications::data::{AccessKind, AvailabilityKind, DataIndex, DataName}; +use tracing::debug; /***** HELPER FUNCTIONS *****/ diff --git a/brane-cli/src/repl.rs b/brane-cli/src/repl.rs index 3f632ebf..5b0f71d7 100644 --- a/brane-cli/src/repl.rs +++ b/brane-cli/src/repl.rs @@ -22,7 +22,6 @@ use brane_dsl::Language; use brane_exe::FullValue; use brane_tsk::docker::DockerOptions; use brane_tsk::spec::AppId; -use log::warn; use rustyline::completion::{Completer, FilenameCompleter, Pair}; use rustyline::error::ReadlineError; use rustyline::highlight::{CmdKind, Highlighter, MatchingBracketHighlighter}; @@ -31,6 +30,7 @@ use rustyline::history::DefaultHistory; use rustyline::validate::{self, MatchingBracketValidator, Validator}; use rustyline::{CompletionType, Config, Context, EditMode, Editor}; use rustyline_derive::Helper; +use tracing::warn; pub use crate::errors::ReplError as Error; use crate::instance::InstanceInfo; diff --git a/brane-cli/src/run.rs b/brane-cli/src/run.rs index 5f3e8853..c269c717 100644 --- a/brane-cli/src/run.rs +++ b/brane-cli/src/run.rs @@ -160,8 +160,8 @@ pub async fn run_instance( if profile { /* TODO */ } // The remote send us some debug message - if let Some(debug) = reply.debug { - debug!("Remote: {}", debug); + if let Some(debug_v) = reply.debug { + debug!("Remote: {}", debug_v); } // The remote send us a normal text message diff --git a/brane-cli/src/upgrade.rs b/brane-cli/src/upgrade.rs index 1afd508d..56d088ae 100644 --- a/brane-cli/src/upgrade.rs +++ b/brane-cli/src/upgrade.rs @@ -20,9 +20,9 @@ use std::fs::{self, DirEntry}; use std::path::{Path, PathBuf}; use console::style; -use log::{debug, info, warn}; use serde::Serialize; use specifications::version::Version; +use tracing::{debug, info, warn}; use crate::old_configs::v1_0_0; use crate::spec::VersionFix; diff --git a/brane-cli/src/version.rs b/brane-cli/src/version.rs index 9dbcb0d4..3c2bcf17 100644 --- a/brane-cli/src/version.rs +++ b/brane-cli/src/version.rs @@ -14,10 +14,10 @@ use std::str::FromStr; -use log::debug; use reqwest::{Response, StatusCode}; use specifications::arch::Arch; use specifications::version::Version; +use tracing::debug; use crate::errors::VersionError; use crate::instance::InstanceInfo; diff --git a/brane-cli/src/vm.rs b/brane-cli/src/vm.rs index 00c6da46..8d2d1742 100644 --- a/brane-cli/src/vm.rs +++ b/brane-cli/src/vm.rs @@ -34,7 +34,6 @@ use brane_tsk::errors::{CommitError, ExecuteError, PreprocessError, StdoutError} use brane_tsk::spec::{LOCALHOST, Planner as _}; use brane_tsk::tools::decode_base64; use chrono::Utc; -use log::{debug, info}; use parking_lot::Mutex; use specifications::container::{Image, VolumeBind}; use specifications::data::{AccessKind, DataIndex, DataInfo, DataName, PreprocessKind}; @@ -42,6 +41,7 @@ use specifications::package::{PackageIndex, PackageInfo}; use specifications::profiling::ProfileScopeHandle; use tokio::fs as tfs; use tokio::io::AsyncWriteExt; +use tracing::{debug, info}; pub use crate::errors::OfflineVmError as Error; use crate::planner::OfflinePlanner; diff --git a/brane-ctl/Cargo.toml b/brane-ctl/Cargo.toml index 85f02040..f3fb89e3 100644 --- a/brane-ctl/Cargo.toml +++ b/brane-ctl/Cargo.toml @@ -20,7 +20,6 @@ doc = false [dependencies] base64ct = "1.6.0" bollard = "0.18.0" -clap = { version = "4.5.6", features = ["derive","env"] } console = "0.15.5" dialoguer = "0.11.0" diesel = { version = "2.2.3", features = ["sqlite"] } @@ -28,15 +27,10 @@ diesel_migrations = "2.2.0" dirs = "6.0.0" dotenvy = "0.15.0" eflint-to-json = { git = "https://github.com/braneframework/policy-reasoner" } -enum-debug.workspace = true -error-trace.workspace = true -humanlog.workspace = true humantime = "2.1.0" human-panic = "2.0.0" jsonwebtoken = "9.2.0" lazy_static = "1.4.0" -log = "0.4.22" -names.workspace = true policy = { git = "https://github.com/braneframework/policy-reasoner" } srv = { git = "https://github.com/braneframework/policy-reasoner" } rand = "0.9.0" @@ -46,23 +40,28 @@ serde_json = "1.0.120" serde_yaml = { version = "0.0.10", package = "serde_yml" } shlex = "1.1.0" tempfile = "3.10.1" -thiserror = "2.0.0" tokio = { version = "1.38.0", features = [] } +# Workspace dependencies +clap.workspace = true +enum-debug.workspace = true +error-trace.workspace = true +names.workspace = true +strum = { workspace = true, features = ["derive"] } +thiserror.workspace = true +tracing-subscriber.workspace = true +tracing.workspace = true + brane-cfg = { path = "../brane-cfg" } brane-shr = { path = "../brane-shr" } brane-tsk = { path = "../brane-tsk" } specifications = { path = "../specifications" } -clap_complete = "4.5.8" -tracing = "0.1.40" - -strum = "0.26.3" -strum_macros = "0.26.4" +clap_complete = "4.4.0" [build-dependencies] download.workspace = true hex-literal = "0.4.0" -clap = { version = "4.5.6", features = ["derive","env"] } +clap.workspace = true [lints] workspace = true diff --git a/brane-ctl/src/cli.rs b/brane-ctl/src/cli.rs index 369abb19..444fb411 100644 --- a/brane-ctl/src/cli.rs +++ b/brane-ctl/src/cli.rs @@ -12,6 +12,7 @@ use humantime::Duration as HumanDuration; use jsonwebtoken::jwk::KeyAlgorithm; use specifications::address::{Address, AddressOpt}; use specifications::arch::Arch; +use specifications::cli::Tracing; use specifications::package::Capability; use specifications::version::Version; @@ -20,12 +21,9 @@ use specifications::version::Version; #[derive(Debug, Parser)] #[clap(name = "branectl", about = "The server-side Brane command-line interface.")] pub(crate) struct Cli { - /// If given, prints `info` and `debug` prints. - #[clap(long, global = true, help = "If given, prints additional information during execution.")] - pub(crate) debug: bool, - /// If given, prints `info`, `debug` and `trace` prints. - #[clap(long, global = true, conflicts_with = "debug", help = "If given, prints the largest amount of debug information as possible.")] - pub(crate) trace: bool, + #[clap(flatten)] + pub(crate) logging: Tracing, + /// The path to the node config file to use. #[clap( short, @@ -77,7 +75,7 @@ pub(crate) enum CtlSubcommand { file: Option, /// The specific Brane version to start. - #[clap(short, long, default_value = env!("CARGO_PKG_VERSION"), help = "The Brane version to import.")] + #[clap(long, default_value = env!("CARGO_PKG_VERSION"), help = "The Brane version to import.")] version: Version, /// Sets the '$IMG_DIR' variable, which can easily switch the location of compiled binaries. @@ -124,7 +122,7 @@ pub(crate) enum CtlSubcommand { #[clap(short, long, default_value = "docker compose", help = "The command to use to run Docker Compose.")] exe: String, /// The docker-compose file that we start. - #[clap(short, long, help = concat!("The docker-compose.yml file that defines the services to stop. You can use '$NODE' to match either 'central' or 'worker', depending how we started. If omitted, will use the baked-in counterpart (although that only works for the default version, v", env!("CARGO_PKG_VERSION"), ")."))] + #[clap(long, help = concat!("The docker-compose.yml file that defines the services to stop. You can use '$NODE' to match either 'central' or 'worker', depending how we started. If omitted, will use the baked-in counterpart (although that only works for the default version, v", env!("CARGO_PKG_VERSION"), ")."))] file: Option, }, #[clap(name = "logs", about = "Show the logs for the specficied node")] @@ -133,7 +131,7 @@ pub(crate) enum CtlSubcommand { #[clap(short, long, default_value = "docker compose", help = "The command to use to run Docker Compose.")] exe: String, /// The docker-compose file that we start. - #[clap(short, long, help = concat!("The docker-compose.yml file that defines the services to log. You can use '$NODE' to match either 'central' or 'worker', depending how we started. If omitted, will use the baked-in counterpart (although that only works for the default version, v", env!("CARGO_PKG_VERSION"), ")."))] + #[clap(long, help = concat!("The docker-compose.yml file that defines the services to log. You can use '$NODE' to match either 'central' or 'worker', depending how we started. If omitted, will use the baked-in counterpart (although that only works for the default version, v", env!("CARGO_PKG_VERSION"), ")."))] file: Option, }, @@ -192,7 +190,7 @@ pub(crate) enum DownloadSubcommand { )] arch: Arch, /// The version of the services to download. - #[clap(short, long, default_value=env!("CARGO_PKG_VERSION"), global=true, help="The version of the images to download from GitHub. You can specify 'latest' to download the latest version (but that might be incompatible with this CTL version)")] + #[clap(long, default_value=env!("CARGO_PKG_VERSION"), global=true, help="The version of the images to download from GitHub. You can specify 'latest' to download the latest version (but that might be incompatible with this CTL version)")] version: Version, /// Whether to overwrite existing images or not. #[clap( diff --git a/brane-ctl/src/download.rs b/brane-ctl/src/download.rs index 26798ce8..60162163 100644 --- a/brane-ctl/src/download.rs +++ b/brane-ctl/src/download.rs @@ -22,11 +22,11 @@ use brane_shr::fs::{DownloadSecurity, download_file_async, move_path_async, unar use brane_tsk::docker::{Docker, DockerOptions, ImageSource, connect_local, ensure_image, save_image}; use console::{Style, style}; use enum_debug::EnumDebug as _; -use log::{debug, info, warn}; use specifications::arch::Arch; use specifications::container::Image; use specifications::version::Version; use tempfile::TempDir; +use tracing::{debug, info, warn}; pub use crate::errors::DownloadError as Error; use crate::spec::DownloadServicesSubcommand; diff --git a/brane-ctl/src/generate.rs b/brane-ctl/src/generate.rs index e32d6eb8..5e80559b 100644 --- a/brane-ctl/src/generate.rs +++ b/brane-ctl/src/generate.rs @@ -37,7 +37,6 @@ use diesel::{Connection as _, SqliteConnection}; use diesel_migrations::{FileBasedMigrations, MigrationHarness as _}; use enum_debug::EnumDebug as _; use jsonwebtoken::jwk::{self, Jwk, JwkSet, KeyAlgorithm, OctetKeyParameters, OctetKeyType, PublicKeyUse}; -use log::{debug, info, warn}; use rand::distr::Alphanumeric; use rand::rngs::OsRng; use rand::{Rng as _, TryRngCore}; @@ -46,6 +45,7 @@ use specifications::address::Address; use specifications::package::Capability; use specifications::policy::generate_policy_token; use tempfile::TempDir; +use tracing::{debug, info, warn}; pub use crate::errors::GenerateError as Error; use crate::spec::{GenerateBackendSubcommand, GenerateCertsSubcommand, GenerateNodeSubcommand, Pair}; diff --git a/brane-ctl/src/lifetime.rs b/brane-ctl/src/lifetime.rs index 0ba7d4e1..b59f004f 100644 --- a/brane-ctl/src/lifetime.rs +++ b/brane-ctl/src/lifetime.rs @@ -32,101 +32,18 @@ use brane_cfg::node::{ use brane_cfg::proxy; use brane_tsk::docker::{DockerOptions, ImageSource, ensure_image, get_digest}; use console::style; -use log::{debug, info}; use rand::Rng; use rand::distr::Alphanumeric; use serde::{Deserialize, Serialize}; +use specifications::brane::{CentralKind, ServiceKind, WorkerKind}; use specifications::container::Image; use specifications::version::Version; use strum::IntoEnumIterator; +use tracing::{debug, info}; pub use crate::errors::LifetimeError as Error; use crate::spec::{LogsOpts, StartOpts, StartSubcommand}; -#[derive(Copy, Clone)] -pub enum ServiceKind { - Central(CentralKind), - Worker(WorkerKind), -} - -impl ServiceKind { - #[inline] - pub fn to_service_name(&self) -> &'static str { - match self { - Self::Central(central_kind) => central_kind.to_service_name(), - Self::Worker(worker_kind) => worker_kind.to_service_name(), - } - } - - #[inline] - pub fn to_env_var(&self) -> &'static str { - match self { - Self::Central(central_kind) => central_kind.to_env_var(), - Self::Worker(worker_kind) => worker_kind.to_env_var(), - } - } -} - -#[derive(strum_macros::EnumIter, Copy, Clone)] -pub enum CentralKind { - Api, - Drv, - Plr, - Prx, -} - -impl CentralKind { - #[inline] - pub fn to_service_name(&self) -> &'static str { - match self { - Self::Api => "brane-api", - Self::Drv => "brane-drv", - Self::Plr => "brane-plr", - Self::Prx => "brane-prx", - } - } - - #[inline] - pub fn to_env_var(&self) -> &'static str { - match self { - Self::Api => "BRANE_API", - Self::Drv => "BRANE_DRV", - Self::Plr => "BRANE_PLR", - Self::Prx => "BRANE_PRX", - } - } -} - -#[derive(strum_macros::EnumIter, Copy, Clone)] -pub enum WorkerKind { - Reg, - Job, - Chk, - Prx, -} - -impl WorkerKind { - #[inline] - pub fn to_service_name(&self) -> &'static str { - match self { - Self::Reg => "brane-reg", - Self::Job => "brane-job", - Self::Chk => "brane-chk", - Self::Prx => "brane-prx", - } - } - - #[inline] - pub fn to_env_var(&self) -> &'static str { - match self { - Self::Reg => "BRANE_REG", - Self::Job => "BRANE_JOB", - Self::Chk => "BRANE_CHK", - Self::Prx => "BRANE_PRX", - } - } -} - /***** HELPER STRUCTS *****/ /// Defines a struct that writes to a valid compose file for overriding hostnames. #[derive(Clone, Debug, Deserialize, Serialize)] @@ -408,28 +325,6 @@ fn prepare_host(node_config: &NodeConfig) -> Result<(), Error> { } } -fn get_log_level(service: ServiceKind) -> Option { - let log_var = format!("{service_name}_LOG", service_name = service.to_env_var()); - - match std::env::var(&log_var) { - Ok(val) => return Some(val), - // TODO: Could use the trace! macro from error-trace. - Err(err) => tracing::trace!( - "Malformed log level set using environment variable `{log_var}`. Falling back to using `BRANE_LOG`, if it is set. Cause: \n{err:#}" - ), - }; - - match std::env::var("BRANE_LOG") { - Ok(val) => return Some(val), - // TODO: Could use the trace! macro from error-trace. - Err(err) => { - tracing::trace!("Malformed log level set using environment variable `BRANE_LOG`. Continuing with default logging. Cause: \n{err:#}") - }, - }; - - None -} - /// Generate an additional, temporary `docker-compose.yml` file that adds additional hostnames and/or additional volumes. /// /// # Arguments @@ -455,38 +350,43 @@ fn generate_override_file(node_config: &NodeConfig, hosts: &HashMap { - let mut services = CentralKind::iter() - .map(|service| { - let mut service_override = svc.clone(); - - println!("Log level?"); - if let Some(log_level) = get_log_level(ServiceKind::Central(service)) { - service_override.environment.push(format!("RUST_LOG={}", log_level)); - tracing::warn!("Setting loglevel for {} to {}", service.to_service_name(), log_level); + let mut services = HashMap::new(); + for service in CentralKind::iter() { + let mut service_override = svc.clone(); + + let log_level = ServiceKind::Central(service).get_tracing_env_filter(); + + info!( + "Setting log level for service {service} to {log_level}", + service = service.to_service_name(), + // log_level = log_level.as_ref().map(|x| x.as_str()).unwrap_or("default") + log_level = log_level.as_deref().unwrap_or("default") + ); + + if let Some(log_level) = log_level { + service_override.environment.push(format!("{level_var}={level}", level_var = service.to_env_var(), level = log_level)); + } + + if matches!(service, CentralKind::Prx) { + if let Some(proxy_path) = &node.paths.proxy { + // Open the extra ports + + // Read the proxy file to find the incoming ports + let proxy: proxy::ProxyConfig = + proxy::ProxyConfig::from_path(proxy_path).map_err(|source| Error::ProxyReadError { source })?; + + // Open both the management and the incoming ports now + service_override.ports.reserve(proxy.incoming.len()); + for (port, _) in proxy.incoming { + service_override.ports.push(format!("0.0.0.0:{port}:{port}")); + } } else { - tracing::warn!("Leaving loglevel for {} at its default", service.to_service_name()); - } - (service.to_service_name(), service_override) - }) - .collect::>(); - { - // Prepare a proxy service override - let prx_svc = services.get_mut(CentralKind::Prx.to_service_name()).unwrap(); - if let Some(proxy_path) = &node.paths.proxy { - // Open the extra ports - - // Read the proxy file to find the incoming ports - let proxy: proxy::ProxyConfig = proxy::ProxyConfig::from_path(proxy_path).map_err(|source| Error::ProxyReadError { source })?; - - // Open both the management and the incoming ports now - prx_svc.ports.reserve(proxy.incoming.len()); - for (port, _) in proxy.incoming { - prx_svc.ports.push(format!("0.0.0.0:{port}:{port}")); + // Otherwise, add it won't start + service_override.profiles = vec!["donotstart".into()]; } - } else { - // Otherwise, add it won't start - prx_svc.profiles = vec!["donotstart".into()]; } + + services.insert(service.to_service_name(), service_override); } // Generate the override file for this node @@ -494,46 +394,47 @@ fn generate_override_file(node_config: &NodeConfig, hosts: &HashMap { - let mut services = WorkerKind::iter() - .map(|service| { - let mut service_override = svc.clone(); + let mut services = HashMap::new(); + for service in WorkerKind::iter() { + let mut service_override = svc.clone(); + + let log_level = ServiceKind::Worker(service).get_tracing_env_filter(); + info!( + "Setting log level for service {service} to {log_level}", + service = service.to_service_name(), + log_level = log_level.as_deref().unwrap_or("default") + ); + + if let Some(log_level) = log_level { + service_override.environment.push(format!("{level_var}={level}", level_var = service.to_env_var(), level = log_level)); + } - if let Some(log_level) = get_log_level(ServiceKind::Worker(service)) { - service_override.environment.push(format!("RUST_LOG={}", log_level)); - println!("Setting loglevel to {log_level}"); - } - (service.to_service_name(), service_override) - }) - .collect::>(); - { - // Prepare a proxy service override - // Unwrap: This comes from an exhaustive iterator therefore there *MUST* be a - // checker. - let prx_svc = services.get_mut(WorkerKind::Prx.to_service_name()).unwrap(); - if let Some(proxy_path) = &node.paths.proxy { - // Open the extra ports - - // Read the proxy file to find the incoming ports - let proxy: proxy::ProxyConfig = proxy::ProxyConfig::from_path(proxy_path).map_err(|source| Error::ProxyReadError { source })?; - - // Open both the management and the incoming ports now - prx_svc.ports.reserve(proxy.incoming.len()); - for (port, _) in proxy.incoming { - prx_svc.ports.push(format!("0.0.0.0:{port}:{port}")); + if matches!(service, WorkerKind::Prx) { + if let Some(proxy_path) = &node.paths.proxy { + // Open the extra ports + + // Read the proxy file to find the incoming ports + let proxy: proxy::ProxyConfig = + proxy::ProxyConfig::from_path(proxy_path).map_err(|source| Error::ProxyReadError { source })?; + + // Open both the management and the incoming ports now + service_override.ports.reserve(proxy.incoming.len()); + for (port, _) in proxy.incoming { + service_override.ports.push(format!("0.0.0.0:{port}:{port}")); + } + } else { + // Otherwise, add it won't start + service_override.profiles = vec!["donotstart".into()]; } - } else { - // Otherwise, add it won't start - prx_svc.profiles = vec!["donotstart".into()]; } - } - { - // Also a checker override - // Unwrap: This comes from an exhaustive iterator therefore there *MUST* be a - // checker. - let chk_svc = services.get_mut(WorkerKind::Chk.to_service_name()).unwrap(); - if let Some(policy_audit_log) = &node.paths.policy_audit_log { - chk_svc.volumes.push(format!("{}:/audit-log.log", policy_audit_log.display())); + + if matches!(service, WorkerKind::Chk) { + if let Some(policy_audit_log) = &node.paths.policy_audit_log { + service_override.volumes.push(format!("{}:/audit-log.log", policy_audit_log.display())); + } } + + services.insert(service.to_service_name(), service_override); } // Generate the override file for this node diff --git a/brane-ctl/src/main.rs b/brane-ctl/src/main.rs index ee47acc9..f156c7ec 100644 --- a/brane-ctl/src/main.rs +++ b/brane-ctl/src/main.rs @@ -13,7 +13,6 @@ // pub mod cli; - use brane_cfg::proxy::ForwardConfig; use brane_ctl::spec::{LogsOpts, StartOpts}; use brane_ctl::{download, generate, lifetime, packages, policies, unpack, upgrade, wizard}; @@ -22,10 +21,15 @@ use clap::Parser; use cli::*; use dotenvy::dotenv; use error_trace::ErrorTrace as _; -use humanlog::{DebugMode, HumanLogger}; -use log::error; +use tracing::error; +use tracing::level_filters::LevelFilter; +/***** CONSTANTS *****/ +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: LevelFilter = LevelFilter::WARN; +/// The environment variable used by env-filter in tracing subscriber +const LOG_LEVEL_ENV_VAR: &str = "BRANE_CTL_LOG"; /***** ENTYRPOINT *****/ #[tokio::main(flavor = "current_thread")] @@ -36,21 +40,12 @@ async fn main() { // Parse the arguments let args = cli::Cli::parse(); - // Initialize the logger - if let Err(err) = HumanLogger::terminal(if args.trace { - DebugMode::Full - } else if args.debug { - DebugMode::Debug - } else { - DebugMode::HumanFriendly - }) - .init() - { - eprintln!("WARNING: Failed to setup logger: {err} (no logging for this session)"); - } + // Note that this can still be overriden by an environment variable + let cli_log_level = args.logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); // Setup the friendlier version of panic - if !args.trace && !args.debug { + if !args.logging.trace && !args.logging.debug { human_panic::setup_panic!(); } @@ -201,7 +196,8 @@ async fn main() { file, args.node_config, DockerOptions { socket: docker_socket, version: docker_version }, - StartOpts { compose_verbose: args.debug || args.trace, version, image_dir, local_aux, skip_import, profile_dir }, + // FIXME: Drop compose verbose? + StartOpts { compose_verbose: args.logging.debug || args.logging.trace, version, image_dir, local_aux, skip_import, profile_dir }, *kind, ) .await @@ -211,13 +207,17 @@ async fn main() { } }, CtlSubcommand::Stop { exe, file } => { - if let Err(err) = lifetime::stop(args.debug || args.trace, exe, file, args.node_config) { + // FIXME: Drop compose verbose? + if let Err(err) = lifetime::stop(args.logging.debug || args.logging.trace, exe, file, args.node_config) { error!("{}", err.trace()); std::process::exit(1); } }, CtlSubcommand::Logs { exe, file } => { - if let Err(err) = lifetime::logs(exe, file, args.node_config, LogsOpts { compose_verbose: args.debug || args.trace }).await { + // FIXME: Drop compose verbose? + if let Err(err) = + lifetime::logs(exe, file, args.node_config, LogsOpts { compose_verbose: args.logging.debug || args.logging.trace }).await + { error!("{}", err.trace()); std::process::exit(1); } diff --git a/brane-ctl/src/old_configs/v1_0_0/node.rs b/brane-ctl/src/old_configs/v1_0_0/node.rs index ba473381..744b708f 100644 --- a/brane-ctl/src/old_configs/v1_0_0/node.rs +++ b/brane-ctl/src/old_configs/v1_0_0/node.rs @@ -300,7 +300,7 @@ impl FromStr for Address { IpAddr::V6(ip) => Ok(Self::Ipv6(ip, port)), }, Err(err) => { - log::debug!("Parsing '{}' as a hostname, but might be an invalid IP address (parser feedback: {})", address, err); + tracing::debug!("Parsing '{}' as a hostname, but might be an invalid IP address (parser feedback: {})", address, err); Ok(Self::Hostname(address.into(), port)) }, } diff --git a/brane-ctl/src/packages.rs b/brane-ctl/src/packages.rs index f80f76ec..afbfc621 100644 --- a/brane-ctl/src/packages.rs +++ b/brane-ctl/src/packages.rs @@ -21,8 +21,8 @@ use std::str::FromStr; use brane_cfg::info::Info as _; use brane_cfg::node::{NodeConfig, NodeKind, NodeSpecificConfig}; use brane_tsk::docker; -use log::{debug, info, warn}; use specifications::version::Version; +use tracing::{debug, info, warn}; pub use crate::errors::PackagesError as Error; diff --git a/brane-ctl/src/policies.rs b/brane-ctl/src/policies.rs index f3315911..400c30ee 100644 --- a/brane-ctl/src/policies.rs +++ b/brane-ctl/src/policies.rs @@ -25,7 +25,6 @@ use console::style; use dialoguer::theme::ColorfulTheme; use enum_debug::EnumDebug; use error_trace::trace; -use log::{debug, info}; use policy::{Policy, PolicyVersion}; use rand::Rng; use rand::distr::Alphanumeric; @@ -37,6 +36,7 @@ use specifications::checking::{ }; use srv::models::{AddPolicyPostModel, PolicyContentPostModel, SetVersionPostModel}; use tokio::fs::{self as tfs, File as TFile}; +use tracing::{debug, info}; use crate::spec::PolicyInputLanguage; diff --git a/brane-ctl/src/unpack.rs b/brane-ctl/src/unpack.rs index e702a682..36347b89 100644 --- a/brane-ctl/src/unpack.rs +++ b/brane-ctl/src/unpack.rs @@ -17,7 +17,7 @@ use std::path::{Path, PathBuf}; use brane_cfg::info::Info as _; use brane_cfg::node::{NodeConfig, NodeKind}; -use log::{debug, info}; +use tracing::{debug, info}; pub use crate::errors::UnpackError as Error; use crate::spec::ResolvableNodeKind; diff --git a/brane-ctl/src/upgrade.rs b/brane-ctl/src/upgrade.rs index 31cc0e27..77c50582 100644 --- a/brane-ctl/src/upgrade.rs +++ b/brane-ctl/src/upgrade.rs @@ -24,9 +24,9 @@ use std::str::FromStr as _; use brane_cfg::node::WorkerUsecase; use brane_shr::input::input; use console::style; -use log::{debug, info, warn}; use serde::Serialize; use specifications::version::Version; +use tracing::{debug, info, warn}; use crate::old_configs::v1_0_0; use crate::spec::VersionFix; diff --git a/brane-ctl/src/wizard.rs b/brane-ctl/src/wizard.rs index 1ad256ae..eff66e16 100644 --- a/brane-ctl/src/wizard.rs +++ b/brane-ctl/src/wizard.rs @@ -28,8 +28,8 @@ use brane_shr::input::{FileHistory, confirm, input, input_map, input_path, selec use console::style; use dirs::config_dir; use enum_debug::EnumDebug as _; -use log::{debug, info}; use specifications::address::Address; +use tracing::{debug, info}; use validator::{FromStrValidator, MapValidator, PortValidator, RangeValidator}; pub mod validator; diff --git a/brane-drv/Cargo.toml b/brane-drv/Cargo.toml index a130da42..1692a3b5 100644 --- a/brane-drv/Cargo.toml +++ b/brane-drv/Cargo.toml @@ -9,13 +9,10 @@ license.workspace = true [dependencies] async-trait = "0.1.67" -clap = { version = "4.5.6", features = ["derive","env"] } +clap.workspace = true dashmap = "6.0.0" dotenvy = "0.15.0" -enum-debug.workspace = true env_logger = "0.11.0" -error-trace.workspace = true -log = "0.4.22" # rdkafka = { version = "0.31", features = ["cmake-build"] } reqwest = { version = "0.12.0" } serde_json = "1.0.120" @@ -25,6 +22,12 @@ tokio = { version = "1.38.0", default-features = false, features = ["macros", "r tokio-stream = "0.1.6" tonic = "0.12.0" +# Workspace dependencies +enum-debug.workspace = true +error-trace.workspace = true +tracing-subscriber.workspace = true +tracing.workspace = true + brane-ast = { path = "../brane-ast" } brane-cfg = { path = "../brane-cfg" } brane-exe = { path = "../brane-exe" } diff --git a/brane-drv/src/check.rs b/brane-drv/src/check.rs index 6350f27b..120f6e0f 100644 --- a/brane-drv/src/check.rs +++ b/brane-drv/src/check.rs @@ -22,7 +22,6 @@ use brane_cfg::infra::{InfraFile, InfraLocation}; use brane_exe::pc::ProgramCounter; use brane_shr::formatters::BlockFormatter; use enum_debug::EnumDebug as _; -use log::{debug, info}; use reqwest::{Client, Request, Response, StatusCode}; use serde_json::Value; use specifications::address::Address; @@ -30,6 +29,7 @@ use specifications::data::{AvailabilityKind, DataName, PreprocessKind}; use specifications::registering::{CheckTransferReply, CheckTransferRequest}; use specifications::working::{self, JobServiceClient}; use tokio::task::JoinHandle; +use tracing::{debug, info}; /***** TYPE ALIASES *****/ @@ -336,7 +336,7 @@ fn traverse_and_request( }; // Match on the edge - log::trace!("Spawning requests in {:?}", edge.variant()); + tracing::trace!("Spawning requests in {:?}", edge.variant()); use Edge::*; match edge { Node { task: _, locs: _, at, input, result: _, metadata: _, next } => { diff --git a/brane-drv/src/cli.rs b/brane-drv/src/cli.rs index eacc3d0a..fd9d5765 100644 --- a/brane-drv/src/cli.rs +++ b/brane-drv/src/cli.rs @@ -7,9 +7,8 @@ use clap::Parser; #[derive(Parser)] #[clap(version = env!("CARGO_PKG_VERSION"))] pub(crate) struct Cli { - /// Print debug info - #[clap(short, long, action, help = "If given, prints additional logging information.", env = "DEBUG")] - pub(crate) debug: bool, + #[clap(flatten)] + pub(crate) logging: specifications::cli::Tracing, /// Consumer group id #[clap(short, long, default_value = "brane-drv", help = "The group ID of this service's consumer")] pub(crate) group_id: String, diff --git a/brane-drv/src/gc.rs b/brane-drv/src/gc.rs index a8cdb2d8..c8269f61 100644 --- a/brane-drv/src/gc.rs +++ b/brane-drv/src/gc.rs @@ -18,7 +18,7 @@ use std::time::{Duration, Instant}; use brane_tsk::spec::AppId; use dashmap::DashMap; -use log::{debug, info, warn}; +use tracing::{debug, info, warn}; use crate::vm::InstanceVm; diff --git a/brane-drv/src/handler.rs b/brane-drv/src/handler.rs index 70cab82a..6b039099 100644 --- a/brane-drv/src/handler.rs +++ b/brane-drv/src/handler.rs @@ -28,13 +28,13 @@ use brane_tsk::spec::AppId; use dashmap::DashMap; use enum_debug::EnumDebug as _; use error_trace::{ErrorTrace as _, trace}; -use log::{debug, error, info}; use specifications::driving::{CheckReply, CheckRequest, CreateSessionReply, CreateSessionRequest, DriverService, ExecuteReply, ExecuteRequest}; use specifications::profiling::ProfileReport; use tokio::sync::mpsc; use tokio::task::JoinHandle; use tokio_stream::wrappers::ReceiverStream; use tonic::{Request, Response, Status}; +use tracing::{debug, error, info}; use crate::check::RequestOutput; use crate::errors::RemoteVmError; @@ -48,21 +48,21 @@ use crate::{check, gc}; macro_rules! fatal_err { ($tx:ident,Status:: $status:ident, $err:expr) => {{ // Always log to stderr - log::error!("{}", $err.trace()); + tracing::error!("{}", $err.trace()); // Attempt to log on tx let serr: String = $err.to_string(); if let Err(err) = $tx.send(Err(Status::$status(serr))).await { - log::error!("{}", trace!(("Failed to notify client of error"), err)); + tracing::error!("{}", trace!(("Failed to notify client of error"), err)); } // Return return; }}; ($tx:ident, $status:expr) => {{ // Always log to stderr - log::error!("Aborting incoming request: {}", $status); + tracing::error!("Aborting incoming request: {}", $status); // Attempt to log on tx if let Err(err) = $tx.send(Err($status)).await { - log::error!("{}", trace!(("Failed to notify client of error"), err)); + tracing::error!("{}", trace!(("Failed to notify client of error"), err)); } // Return return; @@ -70,20 +70,20 @@ macro_rules! fatal_err { ($tx:ident, $rx:ident,Status:: $status:ident, $err:expr) => {{ // Always log to stderr - log::error!("{}", $err.trace()); + tracing::error!("{}", $err.trace()); // Attempt to log on tx if let Err(err) = $tx.send(Err(Status::$status($err.to_string()))).await { - log::error!("{}", trace!(("Failed to notify client of error"), err)); + tracing::error!("{}", trace!(("Failed to notify client of error"), err)); } // Return return Ok(Response::new(ReceiverStream::new($rx))); }}; ($tx:ident, $rx:ident, $status:expr) => {{ // Always log to stderr - log::error!("Aborting incoming request: {}", $status); + tracing::error!("Aborting incoming request: {}", $status); // Attempt to log on tx if let Err(err) = $tx.send(Err($status)).await { - log::error!("{}", trace!(("Failed to notify client of error"), err)); + tracing::error!("{}", trace!(("Failed to notify client of error"), err)); } // Return return Ok(Response::new(ReceiverStream::new($rx))); diff --git a/brane-drv/src/main.rs b/brane-drv/src/main.rs index aa4097e8..50c6f940 100644 --- a/brane-drv/src/main.rs +++ b/brane-drv/src/main.rs @@ -24,10 +24,16 @@ use brane_prx::client::ProxyClient; use clap::Parser; use dotenvy::dotenv; use error_trace::trace; -use log::{LevelFilter, debug, error, info, warn}; use specifications::driving::DriverServiceServer; use tokio::signal::unix::{Signal, SignalKind, signal}; use tonic::transport::Server; +use tracing::{debug, error, info, warn}; + +/***** CONSTANTS *****/ +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: tracing::level_filters::LevelFilter = tracing::level_filters::LevelFilter::INFO; +/// The environment variable used by env-filter in tracing subscriber +const LOG_LEVEL_ENV_VAR: &str = "BRANE_DRV_LOG"; @@ -37,14 +43,9 @@ async fn main() { dotenv().ok(); let opts = cli::Cli::parse(); - // Configure logger. - let mut logger = env_logger::builder(); - logger.format_module_path(false); - if opts.debug { - logger.filter_level(LevelFilter::Debug).init(); - } else { - logger.filter_level(LevelFilter::Info).init(); - } + let cli_log_level = opts.logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); + info!("Initializing brane-drv v{}...", env!("CARGO_PKG_VERSION")); // Load the config, making sure it's a central config diff --git a/brane-drv/src/planner.rs b/brane-drv/src/planner.rs index 67cf7106..e7f51b0a 100644 --- a/brane-drv/src/planner.rs +++ b/brane-drv/src/planner.rs @@ -17,12 +17,12 @@ use brane_ast::Workflow; use brane_tsk::errors::PlanError; use brane_tsk::spec::{AppId, TaskId}; -use log::debug; use reqwest::{Client, Request, Response, StatusCode}; use serde_json::Value; use specifications::address::Address; use specifications::planning::{PlanningDeniedReply, PlanningReply, PlanningRequest}; use specifications::profiling::ProfileScopeHandle; +use tracing::debug; /***** LIBRARY *****/ diff --git a/brane-drv/src/vm.rs b/brane-drv/src/vm.rs index 94ead93f..54ab8586 100644 --- a/brane-drv/src/vm.rs +++ b/brane-drv/src/vm.rs @@ -32,7 +32,6 @@ use brane_prx::client::ProxyClient; use brane_tsk::errors::{CommitError, ExecuteError, PreprocessError, StdoutError, StringError}; use brane_tsk::spec::{AppId, JobStatus}; use enum_debug::EnumDebug as _; -use log::{debug, info, warn}; use serde_json_any_key::MapIterToJson; use specifications::address::Address; use specifications::data::{AccessKind, DataName, PreprocessKind}; @@ -41,6 +40,7 @@ use specifications::working::TransferRegistryTar; use specifications::{driving as driving_grpc, working as working_grpc}; use tokio::sync::mpsc::Sender; use tonic::{Response, Status, Streaming}; +use tracing::{debug, info, warn}; pub use crate::errors::RemoteVmError as Error; use crate::planner::InstancePlanner; diff --git a/brane-dsl/Cargo.toml b/brane-dsl/Cargo.toml index ed0c0569..61d7340c 100644 --- a/brane-dsl/Cargo.toml +++ b/brane-dsl/Cargo.toml @@ -8,14 +8,16 @@ authors.workspace = true license.workspace = true [dependencies] -enum-debug.workspace = true -log = "0.4.22" nom = "7.1.0" nom_locate = "4.1.0" rand = "0.9.0" -regex = "1.5.0" +regex = "1.5.1" serde = "1.0.204" -thiserror = "2.0.0" + +# Workspace dependencies +enum-debug.workspace = true +thiserror.workspace = true +tracing.workspace = true brane-shr = { path = "../brane-shr" } specifications = { path = "../specifications" } diff --git a/brane-dsl/src/compiler.rs b/brane-dsl/src/compiler.rs index 14fe6255..e8d8839b 100644 --- a/brane-dsl/src/compiler.rs +++ b/brane-dsl/src/compiler.rs @@ -13,10 +13,10 @@ //! (incomplete) AST. // -use log::trace; use nom::InputLength; use nom::error::VerboseErrorKind; use specifications::package::PackageIndex; +use tracing::trace; use crate::errors; pub use crate::errors::ParseError as Error; diff --git a/brane-dsl/src/parser/bscript.rs b/brane-dsl/src/parser/bscript.rs index e2327277..dbf7a75b 100644 --- a/brane-dsl/src/parser/bscript.rs +++ b/brane-dsl/src/parser/bscript.rs @@ -16,9 +16,9 @@ use std::collections::HashSet; use std::num::NonZeroUsize; -use log::trace; use nom::error::{ContextError, ErrorKind, ParseError, VerboseError}; use nom::{IResult, Parser, branch, combinator as comb, multi, sequence as seq}; +use tracing::trace; use super::ast::{Block, Identifier, Literal, Node, Program, Property, Stmt}; use crate::ast::Attribute; diff --git a/brane-dsl/src/parser/expression.rs b/brane-dsl/src/parser/expression.rs index 973c29b4..3ac53231 100644 --- a/brane-dsl/src/parser/expression.rs +++ b/brane-dsl/src/parser/expression.rs @@ -14,9 +14,9 @@ use std::num::NonZeroUsize; -use log::trace; use nom::error::{ContextError, ParseError}; use nom::{IResult, Parser, branch, combinator as comb, multi, sequence as seq}; +use tracing::trace; use super::ast::{Expr, Identifier, Node, Operator, UnaOp}; use crate::location::AllowedLocations; diff --git a/brane-dsl/src/parser/identifier.rs b/brane-dsl/src/parser/identifier.rs index 120ac1f0..4c0c4e87 100644 --- a/brane-dsl/src/parser/identifier.rs +++ b/brane-dsl/src/parser/identifier.rs @@ -14,9 +14,9 @@ use std::num::NonZeroUsize; -use log::trace; use nom::error::{ContextError, ParseError}; use nom::{IResult, Parser, combinator as comb}; +use tracing::trace; use super::ast::Identifier; use crate::scanner::{Token, Tokens}; diff --git a/brane-dsl/src/parser/instance.rs b/brane-dsl/src/parser/instance.rs index 398003da..157fe68f 100644 --- a/brane-dsl/src/parser/instance.rs +++ b/brane-dsl/src/parser/instance.rs @@ -14,9 +14,9 @@ use std::num::NonZeroUsize; -use log::trace; use nom::error::{ContextError, ParseError}; use nom::{IResult, Parser, combinator as comb, multi, sequence as seq}; +use tracing::trace; use super::ast::{Expr, Identifier, Node, PropertyExpr}; use crate::parser::{expression, identifier}; diff --git a/brane-dsl/src/parser/literal.rs b/brane-dsl/src/parser/literal.rs index d1c1e6b6..bf15920b 100644 --- a/brane-dsl/src/parser/literal.rs +++ b/brane-dsl/src/parser/literal.rs @@ -14,9 +14,9 @@ use std::num::NonZeroUsize; -use log::trace; use nom::error::{ContextError, ParseError}; use nom::{IResult, Parser, branch, combinator as comb}; +use tracing::trace; use super::ast::Literal; use crate::scanner::{Token, Tokens}; diff --git a/brane-dsl/src/parser/operator.rs b/brane-dsl/src/parser/operator.rs index ce81a4e0..47c1565e 100644 --- a/brane-dsl/src/parser/operator.rs +++ b/brane-dsl/src/parser/operator.rs @@ -14,9 +14,9 @@ use std::num::NonZeroUsize; -use log::trace; use nom::error::{ContextError, ParseError}; use nom::{IResult, Parser, branch, combinator as comb, sequence as seq}; +use tracing::trace; use super::ast::{BinOp, Operator, UnaOp}; use crate::scanner::{Token, Tokens}; diff --git a/brane-exe/Cargo.toml b/brane-exe/Cargo.toml index f7b6ea0e..691ea09e 100644 --- a/brane-exe/Cargo.toml +++ b/brane-exe/Cargo.toml @@ -12,27 +12,27 @@ async-recursion = "1.0.0" async-trait = "0.1.67" base64 = "0.22.0" console = "0.15.5" -enum-debug.workspace = true futures = "0.3.24" lazy_static = "1.4.0" -log = "0.4.22" num-traits = "0.2.18" serde = "1.0.204" serde_json = "1.0.120" -thiserror = "2.0.0" tokio = { version = "1.38.0", features = [] } +# Workspace dependencies +enum-debug.workspace = true +thiserror.workspace = true +tracing.workspace = true + brane-ast = { path = "../brane-ast" } brane-shr = { path = "../brane-shr" } specifications = { path = "../specifications" } [dev-dependencies] -humanlog.workspace = true brane-shr = { path = "../brane-shr" } [features] print_exec_path = [] -test_logging = [] [lints] workspace = true diff --git a/brane-exe/src/dummy.rs b/brane-exe/src/dummy.rs index ba4dce66..b3886c1b 100644 --- a/brane-exe/src/dummy.rs +++ b/brane-exe/src/dummy.rs @@ -21,9 +21,9 @@ use async_trait::async_trait; use brane_ast::ast::{Edge, SymTable}; use brane_ast::locations::Location; use brane_ast::{DataType, Workflow}; -use log::info; use specifications::data::{AccessKind, AvailabilityKind, DataName}; use specifications::profiling::ProfileScopeHandle; +use tracing::info; pub use crate::errors::DummyVmError as Error; use crate::errors::VmError; diff --git a/brane-exe/src/lib.rs b/brane-exe/src/lib.rs index 2c03567a..42470028 100644 --- a/brane-exe/src/lib.rs +++ b/brane-exe/src/lib.rs @@ -38,7 +38,7 @@ pub use vm::Vm; #[cfg(feature = "print_exec_path")] macro_rules! dbg_node { ($($arg:tt)+) => { - { log::debug!($($arg)+); } + { tracing::debug!($($arg)+); } }; } /// Macro that conditionally logs nodes that are being run. diff --git a/brane-exe/src/stack.rs b/brane-exe/src/stack.rs index 577545bd..a41d0205 100644 --- a/brane-exe/src/stack.rs +++ b/brane-exe/src/stack.rs @@ -16,7 +16,7 @@ use std::borrow::{Borrow, BorrowMut}; use std::mem; use std::ops::{Deref, DerefMut, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}; -use log::warn; +use tracing::warn; pub use crate::errors::StackError as Error; use crate::value::Value; diff --git a/brane-exe/src/thread.rs b/brane-exe/src/thread.rs index 5ca1aacf..287bd171 100644 --- a/brane-exe/src/thread.rs +++ b/brane-exe/src/thread.rs @@ -26,11 +26,11 @@ use brane_ast::spec::{BuiltinClasses, BuiltinFunctions}; use brane_ast::{DataType, MergeStrategy, Workflow}; use enum_debug::EnumDebug as _; use futures::future::{BoxFuture, FutureExt}; -use log::debug; use specifications::data::{AccessKind, AvailabilityKind, DataName}; use specifications::profiling::{ProfileScopeHandle, ProfileScopeHandleOwned}; use tokio::spawn; use tokio::task::JoinHandle; +use tracing::debug; use crate::dbg_node; use crate::errors::ReturnEdge; @@ -60,12 +60,6 @@ mod tests { /// Tests the traversal by generating symbol tables for every file. #[tokio::test] async fn test_thread() { - // Setup the simple logger - #[cfg(feature = "test_logging")] - if let Err(err) = humanlog::HumanLogger::terminal(humanlog::DebugMode::Debug).init() { - eprintln!("WARNING: Failed to setup logger: {err} (no logging for this session)"); - } - // Run the tests on all the files test_on_dsl_files_async("BraneScript", |path, code| { async move { diff --git a/brane-job/Cargo.toml b/brane-job/Cargo.toml index 9d3cf758..14ba4dae 100644 --- a/brane-job/Cargo.toml +++ b/brane-job/Cargo.toml @@ -11,27 +11,30 @@ license.workspace = true base64 = "0.22.0" bollard = "0.18.0" chrono = "0.4.35" -clap = { version = "4.5.6", features = ["derive","env"] } +clap.workspace = true deliberation = { git = "https://github.com/braneframework/policy-reasoner" } dotenvy = "0.15.0" -enum-debug.workspace = true env_logger = "0.11.0" -error-trace.workspace = true futures-util = "0.3.30" hyper = "1.3.0" # kube = { version = "0.82", default_features = false, features = ["client"] } # k8s-openapi = { version = "0.18", default_features = false, features = ["v1_23"] } -log = "0.4.22" reqwest = { version = "0.12.0", features = ["rustls-tls-manual-roots","json","stream","multipart"] } serde = { version = "1.0.204", features = ["derive"] } serde_json = "1.0.120" serde_json_any_key = "2.0.0" serde_yaml = { version = "0.0.10", package = "serde_yml" } -thiserror = "2.0.0" tokio = { version = "1.38.0", default-features = false, features = ["rt", "macros", "signal"] } tokio-stream = "0.1.6" tonic = "0.12.0" +# Workspace dependencies +enum-debug.workspace = true +error-trace.workspace = true +thiserror.workspace = true +tracing-subscriber.workspace = true +tracing.workspace = true + brane-ast = { path = "../brane-ast" } brane-cfg = { path = "../brane-cfg" } brane-exe = { path = "../brane-exe" } diff --git a/brane-job/src/cli.rs b/brane-job/src/cli.rs index 225b502c..253ed5e7 100644 --- a/brane-job/src/cli.rs +++ b/brane-job/src/cli.rs @@ -5,9 +5,8 @@ use clap::Parser; #[derive(Parser)] #[clap(version = env!("CARGO_PKG_VERSION"))] pub(crate) struct Cli { - /// Print debug info - #[clap(long, action, help = "If given, shows additional logging information.", env = "DEBUG")] - pub(crate) debug: bool, + #[clap(flatten)] + pub(crate) logging: specifications::cli::Tracing, /// Whether to keep containers after execution or not. #[clap(long, action, help = "If given, will not remove job containers after removing them.", env = "KEEP_CONTAINERS")] pub(crate) keep_containers: bool, diff --git a/brane-job/src/main.rs b/brane-job/src/main.rs index 94b1ff3f..25346cf3 100644 --- a/brane-job/src/main.rs +++ b/brane-job/src/main.rs @@ -22,10 +22,16 @@ use brane_prx::client::ProxyClient; use clap::Parser; use dotenvy::dotenv; use error_trace::trace; -use log::{LevelFilter, debug, error, info, warn}; use specifications::working::JobServiceServer; use tokio::signal::unix::{Signal, SignalKind, signal}; use tonic::transport::Server; +use tracing::{debug, error, info, warn}; + +/***** CONSTANTS *****/ +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: tracing::level_filters::LevelFilter = tracing::level_filters::LevelFilter::INFO; +/// The environment variable used by env-filter in tracing subscriber +const LOG_LEVEL_ENV_VAR: &str = "BRANE_JOB_LOG"; mod cli; @@ -35,15 +41,9 @@ async fn main() { dotenv().ok(); let opts = cli::Cli::parse(); - // Configure logger. - let mut logger = env_logger::builder(); - logger.format_module_path(false); + let cli_log_level = opts.logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); - if opts.debug { - logger.filter_level(LevelFilter::Debug).init(); - } else { - logger.filter_level(LevelFilter::Info).init(); - } info!("Initializing brane-job v{}...", env!("CARGO_PKG_VERSION")); // Load the config, making sure it's a worker config diff --git a/brane-job/src/worker.rs b/brane-job/src/worker.rs index 98d1bfe0..0d43cc2c 100644 --- a/brane-job/src/worker.rs +++ b/brane-job/src/worker.rs @@ -51,8 +51,6 @@ use enum_debug::EnumDebug as _; use error_trace::{ErrorTrace as _, trace}; use futures_util::StreamExt; use hyper::body::Bytes; -// use kube::config::Kubeconfig; -use log::{debug, error, info, warn}; use reqwest::{Method, header}; use serde::{Deserialize, Serialize}; use serde_json_any_key::json_to_map; @@ -74,6 +72,8 @@ use tokio::io::AsyncWriteExt; use tokio::sync::mpsc::{self, Sender}; use tokio_stream::wrappers::ReceiverStream; use tonic::{Request, Response, Status}; +// use kube::config::Kubeconfig; +use tracing::{debug, error, info, warn}; /***** CONSTANTS *****/ @@ -93,9 +93,9 @@ macro_rules! err { ($tx:ident,JobStatus:: $status:ident, $err:expr) => {{ let err = $err; - log::error!("{}", err.trace()); + tracing::error!("{}", err.trace()); if let Err(err) = update_client(&$tx, JobStatus::$status(format!("{}", err))).await { - log::error!("{}", trace!(("Failed to update client on error"), err)); + tracing::error!("{}", trace!(("Failed to update client on error"), err)); } Err(err) }}; diff --git a/brane-let/Cargo.toml b/brane-let/Cargo.toml index 4af460e7..63b07d24 100644 --- a/brane-let/Cargo.toml +++ b/brane-let/Cargo.toml @@ -14,19 +14,21 @@ path = "src/main.rs" [dependencies] anyhow = "1.0.66" base64 = "0.22.0" -clap = { version = "4.5.6", features = ["derive","env"] } dotenvy = "0.15.0" env_logger = "0.11.0" libc = "0.2.154" -log = "0.4.22" serde = { version = "1.0.204", features = ["derive"] } serde_json = "1.0.120" serde_yaml = { version = "0.0.10", package = "serde_yml" } -thiserror = "2.0.0" tokio = { version = "1.38.0", features = ["full", "time"] } tonic = "0.12.0" yaml-rust = { version = "0.8", package = "yaml-rust2" } +# Workspace dependencies +clap.workspace = true +thiserror.workspace = true +tracing.workspace = true + brane-ast = { path = "../brane-ast" } brane-exe = { path = "../brane-exe" } specifications = { path = "../specifications" } diff --git a/brane-let/src/callback.rs b/brane-let/src/callback.rs index c8f69e74..77c20cee 100644 --- a/brane-let/src/callback.rs +++ b/brane-let/src/callback.rs @@ -2,7 +2,7 @@ use anyhow::Result; use brane_clb::grpc::{CallbackKind, CallbackRequest, CallbackServiceClient}; // use brane_job::interface::FailureResult; use libc::{strsignal, c_int, c_char}; -use log::debug; +use tracing::debug; use std::error::Error; use std::ffi::CStr; use std::fmt::{Display, Formatter, Result as FResult}; diff --git a/brane-let/src/cli.rs b/brane-let/src/cli.rs index 19744a8d..2bd29a49 100644 --- a/brane-let/src/cli.rs +++ b/brane-let/src/cli.rs @@ -6,6 +6,8 @@ use clap::Parser; #[derive(Parser)] #[clap(version = env!("CARGO_PKG_VERSION"))] pub(crate) struct Cli { + #[clap(flatten)] + pub(crate) logging: specifications::cli::Tracing, #[clap(short, long, env = "BRANE_APPLICATION_ID")] pub(crate) application_id: String, #[clap(short, long, env = "BRANE_LOCATION_ID")] @@ -18,9 +20,6 @@ pub(crate) struct Cli { pub(crate) proxy_address: Option, #[clap(short, long, env = "BRANE_MOUNT_DFS")] pub(crate) mount_dfs: Option, - /// Prints debug info - #[clap(short, long, action, env = "DEBUG")] - pub(crate) debug: bool, #[clap(subcommand)] pub(crate) sub_command: SubCommand, } diff --git a/brane-let/src/common.rs b/brane-let/src/common.rs index ac79b95b..dfb6e016 100644 --- a/brane-let/src/common.rs +++ b/brane-let/src/common.rs @@ -14,9 +14,9 @@ use brane_ast::DataType; use brane_exe::FullValue; -use log::debug; use specifications::common::Parameter; use specifications::package::PackageKind; +use tracing::debug; use crate::errors::LetError; diff --git a/brane-let/src/exec_ecu.rs b/brane-let/src/exec_ecu.rs index 82f4d0f0..8cb1aaf7 100644 --- a/brane-let/src/exec_ecu.rs +++ b/brane-let/src/exec_ecu.rs @@ -19,11 +19,11 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use brane_exe::FullValue; -use log::{debug, info}; use specifications::container::{Action, ActionCommand, LocalContainerInfo}; use tokio::io::AsyncReadExt as _; use tokio::process::{Child as TokioChild, Command as TokioCommand}; use tokio::time::{self, Duration}; +use tracing::{debug, info}; // use crate::callback::Callback; use crate::common::{HEARTBEAT_DELAY, Map, PackageResult, PackageReturnState, assert_input}; diff --git a/brane-let/src/exec_nop.rs b/brane-let/src/exec_nop.rs index 18e2620a..3374e2aa 100644 --- a/brane-let/src/exec_nop.rs +++ b/brane-let/src/exec_nop.rs @@ -14,7 +14,7 @@ // use brane_exe::FullValue; -use log::{debug, info}; +use tracing::{debug, info}; // use crate::callback::Callback; use crate::common::PackageResult; diff --git a/brane-let/src/main.rs b/brane-let/src/main.rs index f98e85d2..fe91e7c3 100644 --- a/brane-let/src/main.rs +++ b/brane-let/src/main.rs @@ -25,8 +25,9 @@ use brane_let::{exec_ecu, exec_nop}; use clap::Parser; use cli::*; use dotenvy::dotenv; -use log::{LevelFilter, debug, warn}; use serde::de::DeserializeOwned; +use tracing::level_filters::LevelFilter; +use tracing::{debug, warn}; @@ -35,6 +36,10 @@ use serde::de::DeserializeOwned; const OUTPUT_PREFIX_NAME: &str = "ENABLE_STDOUT_PREFIX"; /// The thing we prefix to the output stdout so the Kubernetes engine can recognize valid output when it sees it. const OUTPUT_PREFIX: &str = "[OUTPUT] "; +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: LevelFilter = LevelFilter::INFO; +/// The environment variable used by env-filter in tracing subscriber +const LOG_LEVEL_ENV_VAR: &str = "BRANE_LET_LOG"; @@ -43,16 +48,12 @@ const OUTPUT_PREFIX: &str = "[OUTPUT] "; async fn main() { // Parse the arguments dotenv().ok(); - let cli::Cli { proxy_address, debug, sub_command, .. } = cli::Cli::parse(); + let cli::Cli { logging, proxy_address, sub_command, .. } = cli::Cli::parse(); + + let cli_log_level = logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); // Configure logger. - let mut logger = env_logger::builder(); - logger.format_module_path(false); - if debug { - logger.filter_level(LevelFilter::Debug).init(); - } else { - logger.filter_level(LevelFilter::Info).init(); - } debug!("BRANELET v{}", env!("CARGO_PKG_VERSION")); debug!("Initializing..."); @@ -97,7 +98,7 @@ async fn main() { match run(sub_command).await { Ok(code) => process::exit(code), Err(err) => { - log::error!("{}", err); + tracing::error!("{}", err); process::exit(-1); }, } @@ -161,7 +162,7 @@ async fn run( // Gnerate the line divider let lines = (0..80).map(|_| '-').collect::(); // Print to stderr - log::error!( + tracing::error!( "Internal package call return non-zero exit code {}\n\nstdout:\n{}\n{}\n{}\n\nstderr:\n{}\n{}\n{}\n\n", code, &lines, @@ -183,7 +184,7 @@ async fn run( // if let Err(err) = callback.stopped(signal).await { log::error!("Could not update driver on Stopped: {}", err); } // } else { // Print to stderr - log::error!("Internal package call was forcefully stopped with signal {}", signal); + tracing::error!("Internal package call was forcefully stopped with signal {}", signal); // } Ok(-1) diff --git a/brane-log/Cargo.toml b/brane-log/Cargo.toml new file mode 100644 index 00000000..19d7657b --- /dev/null +++ b/brane-log/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "brane-log" +edition = "2021" +rust-version = "1.74.1" +version.workspace = true +repository.workspace = true +authors.workspace = true +license.workspace = true + +[dependencies] +anyhow = "1.0.0" +async-stream = "0.3.0" +bincode = "1.3.0" +dotenvy = "0.15.0" +env_logger = "0.10.0" +futures = "0.3.0" +juniper = "0.15.0" +juniper_graphql_ws = "0.3.0" +juniper_warp = { version = "0.7.0", features = ["subscriptions"] } +tracing = "0.1.41" +prost = "0.11.0" +rdkafka = { version = "0.31.0", features = ["cmake-build"] } +scylla = "0.2.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +time = { version = "0.3.0", features = ["formatting"] } +tokio = { version = "1.0.0", features = ["full"] } +warp = "0.3.0" + +# Workspace dependencies +clap.workspace = true + +[lints] +workspace = true diff --git a/brane-log/src/main.rs b/brane-log/src/main.rs new file mode 100644 index 00000000..78eed2c7 --- /dev/null +++ b/brane-log/src/main.rs @@ -0,0 +1,134 @@ +use anyhow::Result; +use brane_log::ingestion; +use brane_log::schema::{Event, Query, Subscription}; +use brane_log::{Context, Schema}; +use clap::Parser; +use dotenvy::dotenv; +use futures::FutureExt; +use juniper::{self, EmptyMutation}; +use juniper_graphql_ws::ConnectionConfig; +use juniper_warp::{playground_filter, subscriptions::serve_graphql_ws}; +use tracing::LevelFilter; +use scylla::transport::Compression; +use scylla::{Session, SessionBuilder}; +use std::net::SocketAddr; +use std::sync::Arc; +use tokio::sync::watch; +use warp::ws::Ws; +use warp::Filter; + +#[derive(Parser)] +#[clap(version = env!("CARGO_PKG_VERSION"))] +struct Opts { + #[clap(short, long, default_value = "127.0.0.1:8081", env = "ADDRESS")] + /// Service address + address: String, + /// Scylla endpoint + #[clap(short, long, default_value = "127.0.0.1", env = "SCYLLA")] + scylla: String, + /// Kafka brokers + #[clap(short, long, default_value = "127.0.0.1:9092", env = "BROKERS")] + brokers: String, + /// Print debug info + #[clap(short, long, action, env = "DEBUG")] + debug: bool, + /// Topic to receive events from + #[clap(short, long = "evt-topics", env = "EVENT_TOPIC")] + event_topics: Vec, + /// Consumer group id + #[clap(short, long, default_value = "brane-log", env = "GROUP_ID")] + group_id: String, +} + +#[tokio::main] +async fn main() -> Result<()> { + dotenv().ok(); + let opts = Opts::parse(); + + // Configure logger. + let mut logger = env_logger::builder(); + logger.format_module_path(false); + + if opts.debug { + logger.filter_level(LevelFilter::Debug).init(); + } else { + logger.filter_level(LevelFilter::Info).init(); + } + + // Configure internal event watcher (used for subscriptions). + let (events_tx, events_rx) = watch::channel(Event::default()); + + // Configure Scylla cluster connection. + let scylla_session: Session = SessionBuilder::new() + .known_node(opts.scylla) + .compression(Some(Compression::Snappy)) + .build() + .await?; + + // Ensure Scylla keyspace and table. + ingestion::ensure_db_keyspace(&scylla_session).await?; + ingestion::ensure_db_tables(&scylla_session).await?; + + let scylla_session = Arc::new(scylla_session); + + // Spawn a single event ingestion worker. + tokio::spawn(ingestion::start_worker( + opts.brokers.clone(), + opts.group_id.clone(), + opts.event_topics.clone(), + events_tx, + scylla_session.clone(), + )); + + let events = events_rx.clone(); + + // Configure Wrap web server. + let schema = Schema::new(Query {}, EmptyMutation::new(), Subscription {}); + + let context_scylla = scylla_session.clone(); + let context_events_rx = events_rx.clone(); + let context = warp::any().map(move || Context { + scylla: context_scylla.clone(), + events_rx: context_events_rx.clone(), + }); + + let graphql_filter = juniper_warp::make_graphql_filter(schema, context.boxed()); + let root_node = Arc::new(Schema::new(Query {}, EmptyMutation::new(), Subscription {})); + + let routes = (warp::path("subscriptions").and(warp::ws()).map(move |ws: Ws| { + let root_node = root_node.clone(); + let events = events.clone(); + let scylla = scylla_session.clone(); + + ws.on_upgrade(move |websocket| async move { + serve_graphql_ws( + websocket, + root_node, + ConnectionConfig::new(Context { + scylla, + events_rx: events, + }), + ) + .map(|r| { + if let Err(e) = r { + println!("Websocket error: {e}"); + } + }) + .await + }) + })) + .map(|reply| { + // TODO#584: remove this workaround + warp::reply::with_header(reply, "Sec-WebSocket-Protocol", "graphql-ws") + }) + .or(warp::post().and(warp::path("graphql")).and(graphql_filter)) + .or(warp::get() + .and(warp::path("playground")) + .and(playground_filter("/graphql", Some("/subscriptions")))) + .with(warp::trace::request()); + + let address: SocketAddr = opts.address.clone().parse()?; + warp::serve(routes).run(address).await; + + Ok(()) +} diff --git a/brane-plr/Cargo.toml b/brane-plr/Cargo.toml index 799b0a54..009d5335 100644 --- a/brane-plr/Cargo.toml +++ b/brane-plr/Cargo.toml @@ -9,11 +9,7 @@ license.workspace = true [dependencies] async-recursion = "1.0.0" -clap = { version = "4.5.6", features = ["derive","env"] } dotenvy = "0.15.0" -error-trace.workspace = true -humanlog.workspace = true -log = "0.4.22" parking_lot = "0.12.1" rand = "0.9.0" reqwest = "0.12.0" @@ -22,6 +18,12 @@ tokio = { version = "1.38.0", default-features = false, features = ["macros", "r tonic = "0.12.0" warp = "0.3.2" +# Workspace dependencies +clap.workspace = true +error-trace.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true + brane-ast = { path = "../brane-ast" } brane-cfg = { path = "../brane-cfg" } brane-prx = { path = "../brane-prx" } diff --git a/brane-plr/src/cli.rs b/brane-plr/src/cli.rs index 94069ea7..a5b50eb0 100644 --- a/brane-plr/src/cli.rs +++ b/brane-plr/src/cli.rs @@ -5,9 +5,8 @@ use clap::Parser; #[derive(Parser)] #[clap(version = env!("CARGO_PKG_VERSION"))] pub(crate) struct Cli { - /// Print debug info - #[clap(short, long, action, help = "If given, prints additional logging information.", env = "TRACE")] - pub(crate) trace: bool, + #[clap(flatten)] + pub(crate) logging: specifications::cli::Tracing, /// Node environment metadata store. #[clap( diff --git a/brane-plr/src/main.rs b/brane-plr/src/main.rs index 2b71f290..1272f3d4 100644 --- a/brane-plr/src/main.rs +++ b/brane-plr/src/main.rs @@ -26,12 +26,16 @@ use brane_prx::client::ProxyClient; use clap::Parser; use dotenvy::dotenv; use error_trace::trace; -use humanlog::{DebugMode, HumanLogger}; -use log::{debug, error, info, warn}; use parking_lot::Mutex; use tokio::signal::unix::{Signal, SignalKind, signal}; +use tracing::{debug, error, info, warn}; use warp::Filter as _; +/***** CONSTANTS *****/ +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: tracing::level_filters::LevelFilter = tracing::level_filters::LevelFilter::INFO; +/// The environment variable used by env-filter in tracing subscriber +const LOG_LEVEL_ENV_VAR: &str = "BRANE_PLR_LOG"; /***** ENTRYPOINT *****/ @@ -41,10 +45,9 @@ async fn main() { dotenv().ok(); let opts = cli::Cli::parse(); - // Configure the logger. - if let Err(err) = HumanLogger::terminal(if opts.trace { DebugMode::Full } else { DebugMode::Debug }).init() { - eprintln!("WARNING: Failed to setup logger: {err} (no logging for this session)"); - } + let cli_log_level = opts.logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); + info!("Initializing brane-plr v{}...", env!("CARGO_PKG_VERSION")); // Load the config, making sure it's a central config @@ -82,7 +85,8 @@ async fn main() { .and(warp::path::end()) .and(warp::any().map(move || context.clone())) .and(warp::body::json()) - .and_then(planner::handle); + .and_then(planner::handle) + .with(warp::trace::request()); let paths = plan; // Launch it diff --git a/brane-plr/src/planner.rs b/brane-plr/src/planner.rs index ad42df65..b98895b1 100644 --- a/brane-plr/src/planner.rs +++ b/brane-plr/src/planner.rs @@ -31,7 +31,6 @@ use brane_prx::client::ProxyClient; use brane_tsk::api::get_data_index; use brane_tsk::errors::PlanError; use error_trace::trace; -use log::{debug, error, info}; use rand::prelude::IteratorRandom; use serde_json::Value; use specifications::address::Address; @@ -40,6 +39,7 @@ use specifications::package::Capability; use specifications::planning::{PlanningDeniedReply, PlanningReply, PlanningRequest}; use specifications::profiling::ProfileReport; use specifications::working::{CheckReply, CheckWorkflowRequest, JobServiceClient}; +use tracing::{debug, error, info}; use warp::http::StatusCode; use warp::reject::Rejection; use warp::reply::Response; diff --git a/brane-prx/Cargo.toml b/brane-prx/Cargo.toml index 4a102fc2..28e0a1c9 100644 --- a/brane-prx/Cargo.toml +++ b/brane-prx/Cargo.toml @@ -9,23 +9,26 @@ license.workspace = true [dependencies] anyhow = "1.0.66" -clap = { version = "4.5.6", features = ["derive","env"] } dotenvy = "0.15" env_logger = "0.11.0" -error-trace.workspace = true -log = "0.4.22" never-say-never = "6.6.666" reqwest = { version = "0.12.0", features = ["json"] } rustls = "0.21.6" serde = { version = "1.0.204", features = ["derive"] } serde_json = "1.0.120" socksx = { git = "https://github.com/braneframework/socksx", tag = "v2.0.0" } -thiserror = "2.0.0" tokio = { version = "1.38.0", default-features = false, features = ["macros", "rt", "signal"] } tokio-rustls = "0.24.0" url = "2.5.0" warp = "0.3.2" +# Workspace dependencies +clap.workspace = true +error-trace.workspace = true +thiserror.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true + brane-cfg = { path = "../brane-cfg" } brane-tsk = { path = "../brane-tsk" } specifications = { path = "../specifications" } diff --git a/brane-prx/src/cli.rs b/brane-prx/src/cli.rs index 973436d7..6f1df349 100644 --- a/brane-prx/src/cli.rs +++ b/brane-prx/src/cli.rs @@ -5,9 +5,8 @@ use clap::Parser; #[derive(Parser)] #[clap(name = "Brane proxy service", version = env!("CARGO_PKG_VERSION"), author, about = "A rudimentary, SOCKS-as-a-Service proxy service for outgoing connections from a domain.")] pub(crate) struct Cli { - /// Print debug info - #[clap(long, action, help = "If given, shows additional logging information.", env = "DEBUG")] - pub(crate) debug: bool, + #[clap(flatten)] + pub(crate) logging: specifications::cli::Tracing, /// Node environment metadata store. #[clap( diff --git a/brane-prx/src/client.rs b/brane-prx/src/client.rs index 1eb280a4..a2577dfe 100644 --- a/brane-prx/src/client.rs +++ b/brane-prx/src/client.rs @@ -17,12 +17,12 @@ use std::collections::HashMap; use std::str::FromStr; use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; -use log::{debug, info}; use reqwest::{Client, Request, Response}; use serde::Serialize; use specifications::address::Address; use specifications::package::PackageIndex; use specifications::working::{Error as JobServiceError, JobServiceClient}; +use tracing::{debug, info}; use url::Url; pub use crate::errors::ClientError as Error; diff --git a/brane-prx/src/main.rs b/brane-prx/src/main.rs index 1ebe283d..0af66512 100644 --- a/brane-prx/src/main.rs +++ b/brane-prx/src/main.rs @@ -29,10 +29,16 @@ use brane_prx::spec::Context; use clap::Parser; use dotenvy::dotenv; use error_trace::trace; -use log::{LevelFilter, debug, error, info, warn}; use tokio::signal::unix::{Signal, SignalKind, signal}; +use tracing::{debug, error, info, warn}; use warp::Filter; +/***** CONSTANTS *****/ +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: tracing::level_filters::LevelFilter = tracing::level_filters::LevelFilter::INFO; +/// The environment variable used by env-filter in tracing subscriber +const LOG_LEVEL_ENV_VAR: &str = "BRANE_PRX_LOG"; + /***** ENTRYPOINT *****/ @@ -41,15 +47,9 @@ async fn main() { dotenv().ok(); let args = cli::Cli::parse(); - // Configure logger. - let mut logger = env_logger::builder(); - logger.format_module_path(false); + let cli_log_level = args.logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); - if args.debug { - logger.filter_level(LevelFilter::Debug).init(); - } else { - logger.filter_level(LevelFilter::Info).init(); - } info!("Initializing brane-prx v{}...", env!("CARGO_PKG_VERSION")); // Load the config, making sure it's a worker config @@ -115,7 +115,8 @@ async fn main() { .and(warp::path::end()) .and(warp::body::bytes()) .and(context.clone()) - .and_then(manage::new_outgoing_path); + .and_then(manage::new_outgoing_path) + .with(warp::trace::request()); // Extract the proxy address let bind_addr: SocketAddr = match node_config.node { diff --git a/brane-prx/src/manage.rs b/brane-prx/src/manage.rs index d82c5398..c6e75c24 100644 --- a/brane-prx/src/manage.rs +++ b/brane-prx/src/manage.rs @@ -18,9 +18,9 @@ use std::fmt::{Display, Formatter, Result as FResult}; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::sync::{Arc, MutexGuard}; -use log::{debug, error, info}; use specifications::address::Address; use tokio::net::{TcpListener, TcpStream}; +use tracing::{debug, error, info}; use warp::http::StatusCode; use warp::hyper::body::Bytes; use warp::hyper::{Body, Response}; diff --git a/brane-prx/src/redirect.rs b/brane-prx/src/redirect.rs index bc9abfee..65fd87c4 100644 --- a/brane-prx/src/redirect.rs +++ b/brane-prx/src/redirect.rs @@ -22,7 +22,6 @@ use brane_cfg::certs::{load_certstore, load_identity}; use brane_cfg::info::Info as _; use brane_cfg::node::{NodeConfig, NodeSpecificConfig}; use brane_cfg::proxy::ProxyProtocol; -use log::{debug, error, info}; use never_say_never::Never; use rustls::client::ClientConfig; use rustls::{Certificate, ConfigBuilder, PrivateKey, RootCertStore, ServerName}; @@ -31,6 +30,7 @@ use specifications::address::Address; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls::TlsConnector; use tokio_rustls::client::TlsStream; +use tracing::{debug, error, info}; use url::Url; pub use crate::errors::RedirectError as Error; diff --git a/brane-reg/Cargo.toml b/brane-reg/Cargo.toml index a3506976..a3aca95d 100644 --- a/brane-reg/Cargo.toml +++ b/brane-reg/Cargo.toml @@ -8,24 +8,27 @@ repository.workspace = true license.workspace = true [dependencies] -clap = { version = "4.5.6", features = ["derive","env"] } +clap.workspace = true deliberation = { git = "https://github.com/braneframework/policy-reasoner" } dotenvy = "0.15.0" -enum-debug.workspace = true env_logger = "0.11.0" -error-trace.workspace = true -log = "0.4.22" reqwest = "0.12.0" rustls = "0.21.6" serde = { version = "1.0.204", features = ["rc"] } serde_json = "1.0.120" serde_yaml = { version = "0.0.10", package = "serde_yml" } tempfile = "3.10.1" -thiserror = "2.0.0" tokio = { version = "1.38.0", features = ["rt","rt-multi-thread","macros","io-util", "signal"] } tokio-rustls = "0.24.0" warp = "0.3.2" +# Workspace dependencies +enum-debug.workspace = true +error-trace.workspace = true +thiserror.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true + brane-ast = { path = "../brane-ast" } brane-cfg = { path = "../brane-cfg" } brane-exe = { path = "../brane-exe" } diff --git a/brane-reg/src/check.rs b/brane-reg/src/check.rs index 9be33628..4b4e207e 100644 --- a/brane-reg/src/check.rs +++ b/brane-reg/src/check.rs @@ -23,10 +23,10 @@ use brane_exe::pc::ProgramCounter; use brane_shr::formatters::BlockFormatter; use enum_debug::EnumDebug as _; use error_trace::trace; -use log::{debug, error, info}; use specifications::data::DataName; use specifications::profiling::ProfileReport; use specifications::registering::{CheckTransferReply, CheckTransferRequest}; +use tracing::{debug, error, info}; use warp::hyper::StatusCode; use warp::reject::Rejection; use warp::reply::{self, Reply, Response}; diff --git a/brane-reg/src/cli.rs b/brane-reg/src/cli.rs index c77f1467..d8f1df5c 100644 --- a/brane-reg/src/cli.rs +++ b/brane-reg/src/cli.rs @@ -5,8 +5,8 @@ use clap::Parser; /// Defines the arguments for the `brane-reg` service. #[derive(Parser)] pub(crate) struct Cli { - #[clap(long, action, help = "If given, provides additional debug prints on the logger.", env = "DEBUG")] - pub(crate) debug: bool, + #[clap(flatten)] + pub(crate) logging: specifications::cli::Tracing, /// Load everything from the node.yml file #[clap( diff --git a/brane-reg/src/data.rs b/brane-reg/src/data.rs index 42c31f28..bc212f4a 100644 --- a/brane-reg/src/data.rs +++ b/brane-reg/src/data.rs @@ -31,7 +31,6 @@ use brane_tsk::errors::AuthorizeError; use deliberation::spec::Verdict; use enum_debug::EnumDebug as _; use error_trace::{ErrorTrace as _, trace}; -use log::{debug, error, info}; use reqwest::header; use rustls::Certificate; use serde::{Deserialize, Serialize}; @@ -42,6 +41,7 @@ use specifications::registering::DownloadAssetRequest; use tempfile::TempDir; use tokio::fs as tfs; use tokio::io::AsyncReadExt; +use tracing::{debug, error, info}; use warp::http::HeaderValue; use warp::hyper::body::{Bytes, Sender}; use warp::hyper::{Body, StatusCode}; diff --git a/brane-reg/src/health.rs b/brane-reg/src/health.rs index 9f1f67b6..2eb69df6 100644 --- a/brane-reg/src/health.rs +++ b/brane-reg/src/health.rs @@ -13,7 +13,7 @@ //! `/health` path(s). // -use log::debug; +use tracing::debug; use warp::http::HeaderValue; use warp::hyper::Body; use warp::reply::Response; diff --git a/brane-reg/src/infra.rs b/brane-reg/src/infra.rs index 988d58c8..10dada4c 100644 --- a/brane-reg/src/infra.rs +++ b/brane-reg/src/infra.rs @@ -19,8 +19,8 @@ use brane_cfg::backend::BackendFile; use brane_cfg::info::Info as _; use brane_cfg::node::{NodeConfig, NodeSpecificConfig, WorkerConfig}; use error_trace::trace; -use log::{error, info}; use specifications::package::Capability; +use tracing::{error, info}; use warp::http::HeaderValue; use warp::hyper::Body; use warp::reply::Response; diff --git a/brane-reg/src/main.rs b/brane-reg/src/main.rs index fb4c15f8..2b84633f 100644 --- a/brane-reg/src/main.rs +++ b/brane-reg/src/main.rs @@ -24,10 +24,16 @@ use brane_reg::{check, data, health, infra, version}; use clap::Parser; use dotenvy::dotenv; use error_trace::{ErrorTrace as _, trace}; -use log::{LevelFilter, debug, error, info}; use rustls::Certificate; +use tracing::{debug, error, info}; use warp::Filter; +/***** CONSTANTS *****/ +/// The default log level for tracing_subscriber. Levels higher than this will be discarded. +const DEFAULT_LOG_LEVEL: tracing::level_filters::LevelFilter = tracing::level_filters::LevelFilter::INFO; +/// The environment variable used by env-filter in tracing subscriber +const LOG_LEVEL_ENV_VAR: &str = "BRANE_REG_LOG"; + /***** ENTYRPOINT *****/ @@ -37,14 +43,9 @@ async fn main() { dotenv().ok(); let args = cli::Cli::parse(); - // Setup the logger according to the debug flag - let mut logger = env_logger::builder(); - logger.format_module_path(false); - if args.debug { - logger.filter_level(LevelFilter::Debug).init(); - } else { - logger.filter_level(LevelFilter::Info).init(); - } + let cli_log_level = args.logging.log_level(DEFAULT_LOG_LEVEL); + specifications::tracing::setup_subscriber(LOG_LEVEL_ENV_VAR, cli_log_level); + info!("Initializing brane-reg v{}...", env!("CARGO_PKG_VERSION")); // Load the config, making sure it's a worker config @@ -128,7 +129,8 @@ async fn main() { .or(check_result) .or(infra_capabilities) .or(version) - .or(health); + .or(health) + .with(warp::trace::request()); // Extract the things we need from the config let worker: &WorkerConfig = match node_config.node.try_worker() { diff --git a/brane-reg/src/server.rs b/brane-reg/src/server.rs index f9e3bbd7..48f4a77d 100644 --- a/brane-reg/src/server.rs +++ b/brane-reg/src/server.rs @@ -24,13 +24,13 @@ use std::time::Duration; use brane_cfg::certs::{load_certstore, load_keypair}; use error_trace::trace; -use log::{debug, error, info, warn}; use rustls::server::{AllowAnyAnonymousOrAuthenticatedClient, ServerConfig, ServerConnection}; use rustls::{Certificate, PrivateKey, RootCertStore}; use tokio::net::TcpListener; use tokio::signal::unix::{Signal, SignalKind, signal}; use tokio_rustls::TlsAcceptor; use tokio_rustls::server::TlsStream; +use tracing::{debug, error, info, warn}; use warp::hyper::server::conn::Http; use warp::hyper::service::{self, Service}; use warp::{Filter, Reply}; diff --git a/brane-reg/src/store.rs b/brane-reg/src/store.rs index e1535ed3..83338014 100644 --- a/brane-reg/src/store.rs +++ b/brane-reg/src/store.rs @@ -18,9 +18,9 @@ use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; -use log::{debug, warn}; use specifications::data::AssetInfo; use tokio::fs as tfs; +use tracing::{debug, warn}; pub use crate::errors::StoreError as Error; diff --git a/brane-reg/src/version.rs b/brane-reg/src/version.rs index d11967e3..160a20d3 100644 --- a/brane-reg/src/version.rs +++ b/brane-reg/src/version.rs @@ -12,7 +12,7 @@ //! Implements the function(s) that handle the `/version` path(s). // -use log::debug; +use tracing::debug; use warp::http::HeaderValue; use warp::hyper::Body; use warp::reply::Response; diff --git a/brane-shr/Cargo.toml b/brane-shr/Cargo.toml index 1c6f280e..0a31b6ae 100644 --- a/brane-shr/Cargo.toml +++ b/brane-shr/Cargo.toml @@ -11,21 +11,22 @@ license.workspace = true async-compression = { version = "0.4.0", features = ["tokio","gzip"] } console = "0.15.5" dialoguer = { version = "0.11.0", features = ["completion", "history"] } -enum-debug.workspace = true fs2 = "0.4.0" hex = "0.4.3" -humanlog.workspace = true indicatif = "0.17.0" -log = "0.4.22" -regex = "1.5.0" +regex = "1.5.1" reqwest = { version = "0.12.0", features = ["stream"] } sha2 = "0.10.6" -thiserror = "2.0.0" tokio = { version = "1.38.0", features = ["rt","macros"] } tokio-stream = "0.1.6" tokio-tar = "0.3.0" url = "2.5.0" +# Workspace dependencies +enum-debug.workspace = true +thiserror.workspace = true +tracing.workspace = true + specifications = { path = "../specifications" } [dev-dependencies] diff --git a/brane-shr/src/address.rs b/brane-shr/src/address.rs index 96e04584..6243a718 100644 --- a/brane-shr/src/address.rs +++ b/brane-shr/src/address.rs @@ -23,7 +23,7 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::str::FromStr; use enum_debug::EnumDebug; -use log::debug; +use tracing::debug; use serde::{Deserialize, Serialize}; use serde::ser::Serializer; use serde::de::{self, Deserializer, Visitor}; diff --git a/brane-shr/src/fs.rs b/brane-shr/src/fs.rs index ebbeb571..e1ba1596 100644 --- a/brane-shr/src/fs.rs +++ b/brane-shr/src/fs.rs @@ -24,7 +24,6 @@ use async_compression::tokio::write::GzipEncoder; use console::{Style, style}; use fs2::FileExt as _; use indicatif::{ProgressBar, ProgressStyle}; -use log::{debug, warn}; use reqwest::{Client, Request, Response, StatusCode, Url}; use sha2::{Digest as _, Sha256}; use specifications::version::Version; @@ -32,6 +31,7 @@ use tokio::fs as tfs; use tokio::io::{self as tio, AsyncWriteExt}; use tokio_stream::StreamExt; use tokio_tar::{Archive, Builder, Entries, Entry}; +use tracing::{debug, warn}; use crate::formatters::Capitalizeable; diff --git a/brane-shr/src/input.rs b/brane-shr/src/input.rs index 112ecdd7..cacd0205 100644 --- a/brane-shr/src/input.rs +++ b/brane-shr/src/input.rs @@ -25,7 +25,7 @@ use std::{error, mem}; use dialoguer::theme::ColorfulTheme; use dialoguer::{Completion, Confirm, History, Input, Select}; -use log::warn; +use tracing::warn; /***** ERRORS *****/ diff --git a/brane-shr/src/kafka.rs b/brane-shr/src/kafka.rs index 11c4cabe..0e75eec7 100644 --- a/brane-shr/src/kafka.rs +++ b/brane-shr/src/kafka.rs @@ -14,7 +14,7 @@ use std::fmt::{Display, Formatter, Result as FResult}; -use log::{debug, info}; +use tracing::{debug, info}; use rdkafka::{ClientConfig, Offset, TopicPartitionList}; use rdkafka::admin::{AdminClient, AdminOptions, NewTopic, TopicReplication, TopicResult}; use rdkafka::consumer::Consumer; diff --git a/brane-shr/src/utilities.rs b/brane-shr/src/utilities.rs index d10bfebc..412ae86f 100644 --- a/brane-shr/src/utilities.rs +++ b/brane-shr/src/utilities.rs @@ -17,13 +17,12 @@ use std::fs::{self, DirEntry, ReadDir}; use std::future::Future; use std::path::{Path, PathBuf}; -use humanlog::{DebugMode, HumanLogger}; -use log::{debug, warn}; use regex::Regex; use specifications::container::ContainerInfo; use specifications::data::{AssetInfo, DataIndex, DataInfo}; use specifications::package::{PackageIndex, PackageInfo}; use tokio::runtime::{Builder, Runtime}; +use tracing::{debug, warn}; use url::{Host, Url}; @@ -298,11 +297,8 @@ where R: Future, { // Setup logger if told - if std::env::var("TEST_LOGGER").map(|value| value == "1" || value == "true").unwrap_or(false) { - if let Err(err) = HumanLogger::terminal(DebugMode::Full).init() { - eprintln!("WARNING: Failed to setup test logger: {err} (no logging for this session)"); - } - } + // TODO: Set up tracing subscriber + // See if we need to limit ourselves to particular files let test_files: Option> = std::env::var("TEST_FILES").ok().map(|test_file| test_file.split(',').map(|test_file| test_file.to_string()).collect()); diff --git a/brane-tsk/Cargo.toml b/brane-tsk/Cargo.toml index be262e62..76212703 100644 --- a/brane-tsk/Cargo.toml +++ b/brane-tsk/Cargo.toml @@ -16,10 +16,8 @@ bollard = "0.18.0" chrono = "0.4.35" console = "0.15.5" dialoguer = "0.11.0" -enum-debug.workspace = true futures-util = "0.3.30" graphql_client = "0.14.0" -log = "0.4.22" num-traits = "0.2.18" parking_lot = "0.12.1" rand = "0.9.0" @@ -28,13 +26,17 @@ serde = "1.0.204" serde_json = "1.0.120" serde_yaml = { version = "0.0.10", package = "serde_yml" } sha2 = "0.10.6" -thiserror = "2.0.0" tokio = "1.38.0" tokio-tar = "0.3.0" tokio-util = "0.7.1" tonic = "0.12.0" uuid = { version = "1.7.0", features = ["v4"] } +# Workspace dependencies +enum-debug.workspace = true +thiserror.workspace = true +tracing.workspace = true + brane-ast = { path = "../brane-ast" } brane-cfg = { path = "../brane-cfg" } brane-exe = { path = "../brane-exe" } @@ -43,8 +45,7 @@ specifications = { path = "../specifications" } [dev-dependencies] -clap = { version = "4.4.0", features = ["derive"] } -humanlog.workspace = true +clap.workspace = true lazy_static = "1.4.0" diff --git a/brane-tsk/src/caches.rs b/brane-tsk/src/caches.rs index edd40473..d512982b 100644 --- a/brane-tsk/src/caches.rs +++ b/brane-tsk/src/caches.rs @@ -20,11 +20,11 @@ use std::time::{Duration, Instant}; use brane_ast::locations::Location; use brane_shr::formatters::BlockFormatter; -use log::debug; use num_traits::AsPrimitive; use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use reqwest::{Response, StatusCode}; use specifications::address::Address; +use tracing::debug; /***** CONSTANTS *****/ diff --git a/brane-tsk/src/docker.rs b/brane-tsk/src/docker.rs index d8c8a1de..145039e6 100644 --- a/brane-tsk/src/docker.rs +++ b/brane-tsk/src/docker.rs @@ -28,7 +28,6 @@ use brane_exe::FullValue; use enum_debug::EnumDebug; use futures_util::StreamExt as _; use futures_util::stream::TryStreamExt as _; -use log::debug; use serde::de::{Deserializer, Visitor}; use serde::ser::Serializer; use serde::{Deserialize, Serialize}; @@ -40,6 +39,7 @@ use tokio::fs::{self as tfs, File as TFile}; use tokio::io::{self as tio, AsyncReadExt as _, AsyncWriteExt as _}; use tokio_tar::Archive; use tokio_util::codec::{BytesCodec, FramedRead}; +use tracing::debug; pub use crate::errors::DockerError as Error; use crate::errors::{ClientVersionParseError, ExecuteError}; diff --git a/brane-tsk/src/input.rs b/brane-tsk/src/input.rs index 6bd98eda..3fe5ddd3 100644 --- a/brane-tsk/src/input.rs +++ b/brane-tsk/src/input.rs @@ -24,10 +24,10 @@ use brane_exe::FullValue; use console::{Term, style}; use dialoguer::theme::ColorfulTheme; use dialoguer::{Confirm, Input as Prompt, Select}; -use log::debug; use specifications::data::DataIndex; use specifications::package::PackageInfo; use specifications::version::Version; +use tracing::debug; /***** ERRORS *****/ diff --git a/brane-tsk/src/k8s.rs b/brane-tsk/src/k8s.rs index 14e89f3d..64a0e9d5 100644 --- a/brane-tsk/src/k8s.rs +++ b/brane-tsk/src/k8s.rs @@ -34,7 +34,7 @@ use k8s_openapi::api::core::v1::{ContainerState, ContainerStateRunning, Containe use kube::api::{Api, DeleteParams, LogParams, PostParams, Resource}; use kube::config::{Kubeconfig, KubeConfigOptions}; use kube::runtime::wait::await_condition; -use log::{debug, info, warn}; +use tracing::{debug, info, warn}; use rand::Rng as _; use rand::distributions::Uniform; use serde::de::DeserializeOwned; diff --git a/brane-tsk/src/spec.rs b/brane-tsk/src/spec.rs index 500f2eb9..1b3b402f 100644 --- a/brane-tsk/src/spec.rs +++ b/brane-tsk/src/spec.rs @@ -17,8 +17,8 @@ use std::str::FromStr; use brane_ast::Workflow; use brane_exe::FullValue; -use log::warn; use specifications::working::TaskStatus; +use tracing::warn; use uuid::Uuid; use crate::errors::{ExecuteError, IdError, PlanError}; diff --git a/specifications/Cargo.toml b/specifications/Cargo.toml index 1269d3d7..92f77f0f 100644 --- a/specifications/Cargo.toml +++ b/specifications/Cargo.toml @@ -14,11 +14,8 @@ base64 = "0.22.0" base64ct = { version = "1.6.0", features = ["std"] } chrono = { version = "0.4.35", features = ["serde"] } const_format = "0.2.22" -enum-debug.workspace = true futures = "0.3.24" -# lazy_static = "1.4.0" jsonwebtoken = "9.2.0" -log = "0.4.22" parking_lot = { version = "0.12.1", features = ["serde"] } prost = "0.13.2" reqwest = { version = "0.12.0", features = ["json", "stream"] } @@ -28,11 +25,16 @@ serde_json = "1.0.120" serde_test = "1.0.0" serde_with = "3.0.0" serde_yaml = { version = "0.0.10", package = "serde_yml" } -strum = "0.27.0" -strum_macros = "0.27.0" -thiserror = "2.0.0" tonic = "0.12.0" uuid = { version = "1.7.0", features = ["serde", "v4"] } +# Workspace dependencies +enum-debug.workspace = true +thiserror.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +strum = { workspace = true, features = ["derive"] } +clap.workspace = true + [lints] workspace = true diff --git a/specifications/src/address.rs b/specifications/src/address.rs index dcf5f7f8..8af36233 100644 --- a/specifications/src/address.rs +++ b/specifications/src/address.rs @@ -22,10 +22,10 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::str::FromStr; use enum_debug::EnumDebug; -use log::trace; use serde::de::{self, Deserializer, Visitor}; use serde::ser::Serializer; use serde::{Deserialize, Serialize}; +use tracing::trace; /***** ERRORS *****/ diff --git a/specifications/src/brane.rs b/specifications/src/brane.rs new file mode 100644 index 00000000..c20c2663 --- /dev/null +++ b/specifications/src/brane.rs @@ -0,0 +1,111 @@ +use std::env::VarError; + +use strum::EnumIter; +use tracing::{debug, warn}; + +#[derive(Copy, Clone)] +pub enum ServiceKind { + Central(CentralKind), + Worker(WorkerKind), +} + +static BRANE_LOG_VAR: &str = "BRANE_LOG"; + +impl ServiceKind { + #[inline] + pub fn to_service_name(&self) -> &'static str { + match self { + Self::Central(central_kind) => central_kind.to_service_name(), + Self::Worker(worker_kind) => worker_kind.to_service_name(), + } + } + + #[inline] + pub fn to_env_var(&self) -> &'static str { + match self { + Self::Central(central_kind) => central_kind.to_env_var(), + Self::Worker(worker_kind) => worker_kind.to_env_var(), + } + } + + #[inline] + pub fn log_env_var(&self) -> String { format!("{}_LOG", self.to_env_var()) } + + pub fn get_tracing_env_filter(&self) -> Option { + let log_var = self.log_env_var(); + + match std::env::var(&log_var) { + Ok(val) => return Some(val), + Err(VarError::NotPresent) => debug!("Container specific log level was not set via {log_var}, checking `{BRANE_LOG_VAR}`"), + Err(VarError::NotUnicode(_)) => warn!("Malformed log level set via `{log_var}`. Falling back to using `{BRANE_LOG_VAR}`"), + }; + + match std::env::var(BRANE_LOG_VAR) { + Ok(val) => return Some(val), + Err(VarError::NotPresent) => debug!("`{BRANE_LOG_VAR}` was not set, Continuing with default logging"), + Err(VarError::NotUnicode(_)) => warn!("Malformed log level set using environment variable `{BRANE_LOG_VAR}`."), + }; + + None + } +} + +#[derive(EnumIter, Copy, Clone, Debug)] +pub enum CentralKind { + Api, + Drv, + Plr, + Prx, +} + +impl CentralKind { + #[inline] + pub fn to_service_name(&self) -> &'static str { + match self { + Self::Api => "brane-api", + Self::Drv => "brane-drv", + Self::Plr => "brane-plr", + Self::Prx => "brane-prx", + } + } + + #[inline] + pub fn to_env_var(&self) -> &'static str { + match self { + Self::Api => "BRANE_API", + Self::Drv => "BRANE_DRV", + Self::Plr => "BRANE_PLR", + Self::Prx => "BRANE_PRX", + } + } +} + +#[derive(EnumIter, Copy, Clone, Debug)] +pub enum WorkerKind { + Reg, + Job, + Chk, + Prx, +} + +impl WorkerKind { + #[inline] + pub fn to_service_name(&self) -> &'static str { + match self { + Self::Reg => "brane-reg", + Self::Job => "brane-job", + Self::Chk => "brane-chk", + Self::Prx => "brane-prx", + } + } + + #[inline] + pub fn to_env_var(&self) -> &'static str { + match self { + Self::Reg => "BRANE_REG", + Self::Job => "BRANE_JOB", + Self::Chk => "BRANE_CHK", + Self::Prx => "BRANE_PRX", + } + } +} diff --git a/specifications/src/cli.rs b/specifications/src/cli.rs new file mode 100644 index 00000000..7af8a829 --- /dev/null +++ b/specifications/src/cli.rs @@ -0,0 +1,49 @@ +use clap::Parser; +use tracing::Level; +use tracing::level_filters::LevelFilter; + +#[derive(Debug, Parser)] +pub struct Tracing { + /// If given, prints `info` and `debug` prints. + #[clap(long, global = true, help = "If given, prints additional information during execution.", group = "verbosity", env = "DEBUG")] + pub debug: bool, + /// If given, prints `info`, `debug` and `trace` prints. + #[clap(long, global = true, help = "If given, prints the largest amount of debug information as possible.", group = "verbosity", env = "TRACE")] + pub trace: bool, + /// Logging verbosity `-v` for debug, `-vv` for trace + #[arg(short, long, global = true, help = "If given, increments the log level by one step.", action = clap::ArgAction::Count, group = "verbosity")] + pub(crate) verbose: u8, + /// If given, disables logging levels info and higher. + #[clap(short, long, global = true, help = "If given, disables info logging", action = clap::ArgAction::Count, group = "verbosity")] + pub(crate) quiet: u8, +} + +impl Tracing { + // This code is heavily inspired by clap-verbosity-flag crate, however, it did not suit entirely + // as the trace and debug flags would have been a pain to introduce + pub fn log_level(&self, default_level: LevelFilter) -> LevelFilter { + if self.trace { + return LevelFilter::TRACE; + } else if self.debug { + return LevelFilter::DEBUG; + } + + let numeric_default_level: i16 = match default_level.into_level() { + Some(Level::TRACE) => 5, + Some(Level::DEBUG) => 4, + Some(Level::INFO) => 3, + Some(Level::WARN) => 2, + Some(Level::ERROR) => 1, + None => 0, + }; + + match numeric_default_level.saturating_add(self.verbose.into()).saturating_sub(self.quiet.into()) { + (..=0) => LevelFilter::OFF, + 1 => LevelFilter::ERROR, + 2 => LevelFilter::WARN, + 3 => LevelFilter::INFO, + 4 => LevelFilter::DEBUG, + (5..) => LevelFilter::TRACE, + } + } +} diff --git a/specifications/src/index.rs b/specifications/src/index.rs index 3cf24109..3646c49d 100644 --- a/specifications/src/index.rs +++ b/specifications/src/index.rs @@ -23,7 +23,7 @@ use std::fmt::{Debug, Display, Formatter, Result as FResult}; use std::fs::{self, DirEntry, ReadDir}; use std::path::{Path, PathBuf}; -use log::{debug, info, warn}; +use tracing::{debug, info, warn}; use reqwest::StatusCode; use reqwest::blocking as breqwest; use tokio::fs::{self as tfs, DirEntry as TDirEntry, ReadDir as TReadDir}; diff --git a/specifications/src/lib.rs b/specifications/src/lib.rs index 071ce5bc..2a90bb50 100644 --- a/specifications/src/lib.rs +++ b/specifications/src/lib.rs @@ -18,7 +18,9 @@ // Declare submodules pub mod address; pub mod arch; +pub mod brane; pub mod checking; +pub mod cli; pub mod common; pub mod container; pub mod data; @@ -30,5 +32,6 @@ pub mod planning; pub mod policy; pub mod profiling; pub mod registering; +pub mod tracing; pub mod version; pub mod working; diff --git a/specifications/src/package.rs b/specifications/src/package.rs index 0275cf8e..ba66089a 100644 --- a/specifications/src/package.rs +++ b/specifications/src/package.rs @@ -24,8 +24,7 @@ use enum_debug::EnumDebug; use serde::{Deserialize, Serialize}; use serde_json::Value as JValue; use serde_with::skip_serializing_none; -use strum::IntoEnumIterator; -use strum_macros::EnumIter; +use strum::{EnumIter, IntoEnumIterator}; use uuid::Uuid; use crate::common::{Function, Type}; diff --git a/specifications/src/policy.rs b/specifications/src/policy.rs index ecf41c8d..22758915 100644 --- a/specifications/src/policy.rs +++ b/specifications/src/policy.rs @@ -23,8 +23,8 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use base64ct::Encoding as _; use jsonwebtoken::jwk::{self, Jwk, JwkSet, KeyAlgorithm, OctetKeyParameters}; use jsonwebtoken::{Algorithm, EncodingKey, Header}; -use log::{debug, info, warn}; use serde::{Deserialize, Serialize}; +use tracing::{debug, info, warn}; /***** ERRORS *****/ diff --git a/specifications/src/profiling.rs b/specifications/src/profiling.rs index c7ba8d6a..964df5dd 100644 --- a/specifications/src/profiling.rs +++ b/specifications/src/profiling.rs @@ -31,9 +31,9 @@ use std::time::{Duration, Instant}; use chrono::{DateTime, Local}; use enum_debug::EnumDebug; -use log::warn; use parking_lot::{Mutex, MutexGuard}; use serde::{Deserialize, Serialize}; +use tracing::warn; /***** HELPER MACROS *****/ diff --git a/specifications/src/tracing.rs b/specifications/src/tracing.rs new file mode 100644 index 00000000..3b1e9058 --- /dev/null +++ b/specifications/src/tracing.rs @@ -0,0 +1,18 @@ +use tracing::info; +use tracing::level_filters::LevelFilter; +use tracing_subscriber::layer::SubscriberExt as _; +use tracing_subscriber::util::SubscriberInitExt as _; + +pub fn setup_subscriber(log_level_env_var: &str, default_log_level: LevelFilter) { + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer()) + .with( + tracing_subscriber::EnvFilter::builder() + .with_env_var(log_level_env_var) + .with_default_directive(default_log_level.into()) + .from_env_lossy(), + ) + .init(); + + info!("Logger initiated with log level {}", std::env::var(log_level_env_var).unwrap_or(default_log_level.to_string())); +}