From e95d79db66b66cb91dacaf966bfb2ec722ebfcf2 Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Thu, 20 May 2021 03:11:51 +0900 Subject: [PATCH] client: add verbose logging --- Cargo.lock | 2 ++ client/Cargo.toml | 1 + client/src/main.rs | 52 +++++++++++++++++++++++++--------------------- client/src/util.rs | 40 +++++++++++++++++++++++++++++++++++ shared/Cargo.toml | 1 + 5 files changed, 72 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d44f64c..d5fe3a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,6 +160,7 @@ dependencies = [ "ipnetwork", "lazy_static", "libc", + "log", "regex", "serde", "serde_json", @@ -934,6 +935,7 @@ dependencies = [ "indoc", "ipnetwork", "lazy_static", + "log", "publicip", "regex", "serde", diff --git a/client/Cargo.toml b/client/Cargo.toml index 75fe8a4..9c5800c 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -21,6 +21,7 @@ indoc = "1" ipnetwork = { git = "https://github.com/mcginty/ipnetwork" } # pending https://github.com/achanda/ipnetwork/pull/129 lazy_static = "1" libc = "0.2" +log = "0.4" regex = { version = "1", default-features = false, features = ["std"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/client/src/main.rs b/client/src/main.rs index f4724c6..c212d84 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -42,6 +42,9 @@ struct Opts { #[structopt(subcommand)] command: Option, + #[structopt(short, parse(from_occurrences))] + verbosity: u64, + #[structopt(flatten)] network: NetworkOpt, } @@ -406,7 +409,7 @@ fn fetch( .into()); } - println!("{} bringing up the interface.", "[*]".dimmed()); + log::info!("bringing up the interface."); let resolved_endpoint = config.server.external_endpoint.resolve()?; wg::up( interface, @@ -422,7 +425,7 @@ fn fetch( )? } - println!("{} fetching state from server.", "[*]".dimmed()); + log::info!("fetching state from server."); let mut store = DataStore::open_or_create(&interface)?; let State { peers, cidrs } = Api::new(&config.server).http("GET", "/user/state")?; @@ -492,13 +495,13 @@ fn fetch( update_hosts_file(interface, path, &peers)?; } - println!( - "\n{} updated interface {}\n", - "[*]".dimmed(), + println!(); + log::info!( + "updated interface {}\n", interface.as_str_lossy().yellow() ); } else { - println!("{}", " peers are already up to date.".green()); + log::info!("{}", "peers are already up to date.".green()); } store.set_cidrs(cidrs); store.update_peers(peers)?; @@ -539,13 +542,13 @@ fn uninstall(interface: &InterfaceName, network: NetworkOpt) -> Result<(), Error fn add_cidr(interface: &InterfaceName, opts: AddCidrOpts) -> Result<(), Error> { let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; - println!("Fetching CIDRs"); + log::info!("Fetching CIDRs"); let api = Api::new(&server); let cidrs: Vec = api.http("GET", "/admin/cidrs")?; let cidr_request = prompts::add_cidr(&cidrs, &opts)?; - println!("Creating CIDR..."); + log::info!("Creating CIDR..."); let cidr: Cidr = api.http_form("POST", "/admin/cidrs", cidr_request)?; printdoc!( @@ -567,9 +570,9 @@ fn add_peer(interface: &InterfaceName, opts: AddPeerOpts) -> Result<(), Error> { let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let api = Api::new(&server); - println!("Fetching CIDRs"); + log::info!("Fetching CIDRs"); let cidrs: Vec = api.http("GET", "/admin/cidrs")?; - println!("Fetching peers"); + log::info!("Fetching peers"); let peers: Vec = api.http("GET", "/admin/peers")?; let cidr_tree = CidrTree::new(&cidrs[..]); @@ -597,7 +600,7 @@ fn enable_or_disable_peer(interface: &InterfaceName, enable: bool) -> Result<(), let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let api = Api::new(&server); - println!("Fetching peers."); + log::info!("Fetching peers."); let peers: Vec = api.http("GET", "/admin/peers")?; if let Some(peer) = prompts::enable_or_disable_peer(&peers[..], enable)? { @@ -605,7 +608,7 @@ fn enable_or_disable_peer(interface: &InterfaceName, enable: bool) -> Result<(), contents.is_disabled = !enable; api.http_form("PUT", &format!("/admin/peers/{}", id), contents)?; } else { - println!("exited without disabling peer."); + log::info!("exiting without disabling peer."); } Ok(()) @@ -615,7 +618,7 @@ fn add_association(interface: &InterfaceName, opts: AddAssociationOpts) -> Resul let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let api = Api::new(&server); - println!("Fetching CIDRs"); + log::info!("Fetching CIDRs"); let cidrs: Vec = api.http("GET", "/admin/cidrs")?; let association = if let (Some(ref cidr1), Some(ref cidr2)) = (opts.cidr1, opts.cidr2) { @@ -631,7 +634,7 @@ fn add_association(interface: &InterfaceName, opts: AddAssociationOpts) -> Resul } else if let Some((cidr1, cidr2)) = prompts::add_association(&cidrs[..])? { (cidr1, cidr2) } else { - println!("exited without adding association."); + log::info!("exiting without adding association."); return Ok(()); }; @@ -651,15 +654,15 @@ fn delete_association(interface: &InterfaceName) -> Result<(), Error> { let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let api = Api::new(&server); - println!("Fetching CIDRs"); + log::info!("Fetching CIDRs"); let cidrs: Vec = api.http("GET", "/admin/cidrs")?; - println!("Fetching associations"); + log::info!("Fetching associations"); let associations: Vec = api.http("GET", "/admin/associations")?; if let Some(association) = prompts::delete_association(&associations[..], &cidrs[..])? { api.http("DELETE", &format!("/admin/associations/{}", association.id))?; } else { - println!("exited without adding association."); + log::info!("exiting without adding association."); } Ok(()) @@ -669,9 +672,9 @@ fn list_associations(interface: &InterfaceName) -> Result<(), Error> { let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let api = Api::new(&server); - println!("Fetching CIDRs"); + log::info!("Fetching CIDRs"); let cidrs: Vec = api.http("GET", "/admin/cidrs")?; - println!("Fetching associations"); + log::info!("Fetching associations"); let associations: Vec = api.http("GET", "/admin/associations")?; for association in associations { @@ -705,13 +708,13 @@ fn set_listen_port( if let Some(listen_port) = prompts::set_listen_port(&config.interface, unset)? { wg::set_listen_port(interface, listen_port, network.backend)?; - println!("{} the interface is updated", "[*]".dimmed(),); + log::info!("the interface is updated"); config.interface.listen_port = listen_port; config.write_to_interface(interface)?; - println!("{} the config file is updated", "[*]".dimmed(),); + log::info!("the config file is updated"); } else { - println!("exited without updating listen port."); + log::info!("exiting without updating the listen port."); } Ok(()) @@ -739,7 +742,7 @@ fn override_endpoint( EndpointContents::from(endpoint), )?; } else { - println!("exited without overriding endpoint."); + log::info!("exiting without overriding endpoint."); } Ok(()) @@ -771,7 +774,7 @@ fn show( .collect::>(); if devices.is_empty() { - println!("No innernet networks currently running."); + log::info!("No innernet networks currently running."); return Ok(()); } @@ -917,6 +920,7 @@ fn print_peer(peer: &PeerState, short: bool, level: usize) { fn main() { let opt = Opts::from_args(); + util::init_logger(opt.verbosity); if let Err(e) = run(opt) { eprintln!("\n{} {}\n", "[ERROR]".red(), e); diff --git a/client/src/util.rs b/client/src/util.rs index 7153faa..0635b4a 100644 --- a/client/src/util.rs +++ b/client/src/util.rs @@ -1,10 +1,50 @@ use crate::{ClientError, Error}; use colored::*; +use log::{Level, LevelFilter}; use serde::{de::DeserializeOwned, Serialize}; use shared::{interface_config::ServerInfo, INNERNET_PUBKEY_HEADER}; use std::time::Duration; use ureq::{Agent, AgentBuilder}; +static LOGGER: Logger = Logger; +struct Logger; +impl log::Log for Logger { + fn enabled(&self, metadata: &log::Metadata) -> bool { + metadata.level() <= log::max_level() && (log::max_level() == LevelFilter::Trace + || metadata.target().starts_with("shared::") + || metadata.target() == "innernet") + } + + fn log(&self, record: &log::Record) { + if self.enabled(record.metadata()) { + let level_str = match record.level() { + Level::Error => "[E]".red(), + Level::Warn => "[!]".yellow(), + Level::Info => "[*]".dimmed(), + Level::Debug => "[D]".blue(), + Level::Trace => "[T]".purple(), + }; + if record.level() <= LevelFilter::Debug && record.target() != "innernet" { + println!("{} {} {}", level_str, format!("[{}]", record.target()).dimmed(), record.args()); + } else { + println!("{} {}", level_str, record.args()); + } + } + } + + fn flush(&self) {} +} + +pub fn init_logger(verbosity: u64) { + let level = match verbosity { + 0 => log::LevelFilter::Info, + 1 => log::LevelFilter::Debug, + _ => log::LevelFilter::Trace, + }; + log::set_max_level(level); + log::set_logger(&LOGGER).unwrap(); +} + pub fn human_duration(duration: Duration) -> String { match duration.as_secs() { n if n < 1 => "just now".cyan().to_string(), diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 38e5829..28948fb 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -12,6 +12,7 @@ dialoguer = "0.8" indoc = "1" ipnetwork = { git = "https://github.com/mcginty/ipnetwork" } # pending https://github.com/achanda/ipnetwork/pull/129 lazy_static = "1" +log = "0.4" publicip = { path = "../publicip" } regex = "1" serde = { version = "1", features = ["derive"] }