From edae4419c1cc529a78d06370728dab0c255a1f5b Mon Sep 17 00:00:00 2001 From: Sebastian Pipping Date: Fri, 23 Jun 2023 23:23:32 +0200 Subject: [PATCH] logging.rs: Move log styling into logging module Uses log feature "kv_unstable" to support sub levels of level "info". --- Cargo.lock | 9 ++++++++ Cargo.toml | 2 +- src/exec.rs | 6 ++--- src/logging.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++---- src/network.rs | 14 ++++++++---- 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8abb830..43db62d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,6 +186,9 @@ name = "log" version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +dependencies = [ + "value-bag", +] [[package]] name = "memchr" @@ -265,6 +268,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "value-bag" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4d330786735ea358f3bc09eea4caa098569c1c93f342d9aca0514915022fe7e" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 7eb2f75..e2cba43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ anstream = "0.3.2" clap = { version = "4.3.4", features = ["cargo", "color"] } indoc = "2.0.1" lazy_static = "1.4.0" -log = { version = "0.4.19" } +log = { version = "0.4.19", features = ["kv_unstable"] } regex = "1.8.4" subprocess = "0.2.9" diff --git a/src/exec.rs b/src/exec.rs index 19f51a9..12568a1 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -31,15 +31,15 @@ fn process_popen_result(popen_result: PopenResult, command: &str) -> match popen_result { Ok(exit_status) => exit_code_from(exit_status), Err(PopenError::IoError(error)) if error.kind() == ErrorKind::PermissionDenied => { - error!("[-] Command '{command}' could not be run: permission denied."); + error!("Command '{command}' could not be run: permission denied."); 126 } Err(PopenError::IoError(error)) if error.kind() == ErrorKind::NotFound => { - error!("[-] Command '{command}' not found."); + error!("Command '{command}' not found."); 127 } Err(error) => { - error!("[-] Command '{command}' failed with unexpected error: {error}."); + error!("Command '{command}' failed with unexpected error: {error}."); 255 } } diff --git a/src/logging.rs b/src/logging.rs index dc5c9c6..2892aac 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -3,12 +3,52 @@ // Copyright (c) 2023 Sebastian Pipping // SPDX-License-Identifier: MIT -use log::{set_logger, set_max_level, Level, LevelFilter, Log, Metadata, Record}; +use log::{kv::ToValue, kv::Value, set_logger, set_max_level, LevelFilter, Log, Metadata, Record}; static CUSTOM_LOG: CustomLog = CustomLog {}; struct CustomLog {} +#[derive(Copy, Clone, Debug, PartialEq)] +pub(crate) enum SubLevel { + Starting, + Succeeded, + Failed, +} + +impl From for SubLevel { + fn from(value: u64) -> Self { + match value { + 0 => SubLevel::Starting, + 1 => SubLevel::Succeeded, + _ => SubLevel::Failed, + } + } +} + +impl ToValue for SubLevel { + fn to_value(&self) -> Value { + match self { + SubLevel::Starting => 0u64.to_value(), + SubLevel::Succeeded => 1u64.to_value(), + SubLevel::Failed => 2u64.to_value(), + } + } +} + +#[cfg(test)] +#[test] +fn test_sublevel_casting() { + assert_eq!(SubLevel::Starting.to_value().to_u64().unwrap(), 0); + assert_eq!(SubLevel::Succeeded.to_value().to_u64().unwrap(), 1); + assert_eq!(SubLevel::Failed.to_value().to_u64().unwrap(), 2); + + assert_eq!(SubLevel::from(0), SubLevel::Starting); + assert_eq!(SubLevel::from(1), SubLevel::Succeeded); + assert_eq!(SubLevel::from(2), SubLevel::Failed); + assert_eq!(SubLevel::from(3), SubLevel::Failed); +} + impl Log for CustomLog { fn enabled(&self, _metadata: &Metadata) -> bool { true @@ -19,10 +59,22 @@ impl Log for CustomLog { return; } - if record.level() == Level::Error { - eprintln!("{}", record.args()); - } else { - println!("{}", record.args()); + let value: Value = record + .key_values() + .get("sublevel".into()) + .unwrap_or(Value::from(SubLevel::Failed as u64)); + let sublevel = SubLevel::from(value.to_u64().expect("malformed sublevel")); + + match sublevel { + SubLevel::Starting => { + println!("[*] {}", record.args()); + } + SubLevel::Succeeded => { + println!("[+] {}", record.args()); + } + SubLevel::Failed => { + eprintln!("[-] {}", record.args()); + } } } diff --git a/src/network.rs b/src/network.rs index 506cfe8..b7d9349 100644 --- a/src/network.rs +++ b/src/network.rs @@ -3,6 +3,7 @@ // Copyright (c) 2023 Sebastian Pipping // SPDX-License-Identifier: MIT +use crate::logging::SubLevel; use log::{error, info}; use std::io; use std::net::{Shutdown, SocketAddr, TcpStream, ToSocketAddrs}; @@ -124,9 +125,11 @@ pub(crate) fn wait_for_service( let forever = timeout_seconds == 0; if forever { - info!("[*] Waiting for {host_and_port} without a timeout..."); + info!(target: module_path!(), sublevel = SubLevel::Starting; + "Waiting for {host_and_port} without a timeout..."); } else { - info!("[*] Waiting {timeout_seconds} seconds for {host_and_port}..."); + info!(target: module_path!(), sublevel = SubLevel::Starting; + "Waiting {timeout_seconds} seconds for {host_and_port}..."); } let timeout = if timeout_seconds == 0 { @@ -140,12 +143,13 @@ pub(crate) fn wait_for_service( match connect_result { Ok(_) => { let duration = timer.elapsed().as_secs(); - info!("[+] {host_and_port} is available after {duration} seconds."); + info!(target: module_path!(), sublevel = SubLevel::Succeeded; + "{host_and_port} is available after {duration} seconds."); } Err(ref error) => { error!( - "[-] {host_and_port} timed out after waiting for {timeout_seconds} seconds ({error})." - ); + "{host_and_port} timed out after waiting for {timeout_seconds} seconds ({error})." + ); } }