From ce9d4b22587230959dce2c368eab7c415f08ae7d Mon Sep 17 00:00:00 2001 From: JKearnsl Date: Tue, 20 May 2025 00:31:31 +0300 Subject: [PATCH] fix: improve logging initialization --- Cargo.toml | 4 +- crates/server/Cargo.toml | 9 ++- crates/server/src/bin/command/users/add.rs | 6 +- crates/server/src/bin/command/users/list.rs | 2 +- crates/server/src/bin/mod.rs | 4 +- crates/server/src/bin/opt.rs | 46 +++++++++------ crates/server/src/bin/style.rs | 59 ++++++------------- .../src/runtime/session/generator/ip.rs | 3 +- crates/shared/src/keys/mod.rs | 30 +++------- 9 files changed, 70 insertions(+), 93 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 15e5ff7..71c4da1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,10 +26,10 @@ ctrlc = "3.4" chrono = { version = "0.4", features = ["serde"] } serde = { version = "1.0", features = ["derive"] } anyhow = "1.0.95" -etherparse = "0.17" +etherparse = "0.18" bincode = "2.0.1" # logging tracing = "0.1" -tracing-subscriber = "0.3" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-appender = "0.2" diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml index 6cc5605..c5cc053 100644 --- a/crates/server/Cargo.toml +++ b/crates/server/Cargo.toml @@ -47,8 +47,15 @@ tun-rs = { workspace = true } tokio = { workspace = true } socket2 = { workspace = true, optional = true } async-trait = "0.1" -hex = "0.4.3" rand = "0.9.1" tokio-tungstenite = { workspace = true, optional = true } futures = { workspace = true, optional = true } +[profile.release] +opt-level = 3 +lto = "fat" +panic = "abort" +strip = true + +[profile.release.package."*"] +opt-level = 3 \ No newline at end of file diff --git a/crates/server/src/bin/command/users/add.rs b/crates/server/src/bin/command/users/add.rs index d3f9611..0b872fe 100644 --- a/crates/server/src/bin/command/users/add.rs +++ b/crates/server/src/bin/command/users/add.rs @@ -64,9 +64,9 @@ impl AddCmd { println!("\nClient has been successfully created!"); - println!("\nPublic key {}", pk.to_hex()); - println!("Private key {}", format_opaque_bytes(sk.as_slice())); - println!("Pre-shared key {}", format_opaque_bytes(psk.as_slice())); + println!("\nPublicKey {}", pk); + println!("PrivateKey {}", format_opaque_bytes(sk.as_slice())); + println!("PreSharedKey {}", format_opaque_bytes(psk.as_slice())); let clients = Clients::new(database(&config.general.storage)?)?; clients.save(Client { diff --git a/crates/server/src/bin/command/users/list.rs b/crates/server/src/bin/command/users/list.rs index 7308aeb..e3b6344 100644 --- a/crates/server/src/bin/command/users/list.rs +++ b/crates/server/src/bin/command/users/list.rs @@ -18,7 +18,7 @@ impl ListCmd { let clients = Clients::new(database(&config.general.storage)?)?; let users: Vec<_> = clients.get_all().await.iter().map(|client| { UserRow { - pk: client.peer_pk.to_hex(), + pk: client.peer_pk.to_string(), created_at: client.created_at.to_rfc2822() } }).collect(); diff --git a/crates/server/src/bin/mod.rs b/crates/server/src/bin/mod.rs index abaa015..f881de5 100644 --- a/crates/server/src/bin/mod.rs +++ b/crates/server/src/bin/mod.rs @@ -16,7 +16,7 @@ const LOG_PREFIX: &str = "server.log"; #[tokio::main(flavor = "multi_thread")] async fn main() -> anyhow::Result<()> { let mut opt = Opt::parse(); - opt.init_logging(); + let _guard = opt.init_logging()?; inquire::set_global_render_config(render_config()); let config = opt.load_config(true)?; @@ -26,7 +26,7 @@ async fn main() -> anyhow::Result<()> { Commands::Users(cmd) => cmd.exec(config).await, Commands::Monitor => unimplemented!("Monitor command is not implemented"), Commands::Logs => unimplemented!("Logs command is not implemented"), - } + } Ok(()) } diff --git a/crates/server/src/bin/opt.rs b/crates/server/src/bin/opt.rs index 2125d25..b2544d4 100644 --- a/crates/server/src/bin/opt.rs +++ b/crates/server/src/bin/opt.rs @@ -1,8 +1,11 @@ -use std::{path::PathBuf, io::IsTerminal}; +use std::{path::PathBuf, io::IsTerminal, fs}; +use std::path::Path; +use chrono::Local; use clap::Parser; -use tracing::info; -use tracing::level_filters::LevelFilter; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, fmt, Layer}; +use tracing::{debug, info}; +use tracing_appender::non_blocking::WorkerGuard; +use tracing_appender::rolling::{RollingFileAppender, Rotation}; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, fmt, Layer, EnvFilter}; use server::config; use crate::{LOG_DIR, LOG_PREFIX, CONFIG_PATH_ENV}; use crate::command::Commands; @@ -29,33 +32,40 @@ pub struct Opt { } impl Opt { - pub fn init_logging(&mut self) { - let log_level = LevelFilter::from_level(if self.debug { - tracing::Level::DEBUG - } else { - tracing::Level::INFO - }); - - let file_appender = tracing_appender::rolling::daily(LOG_DIR, LOG_PREFIX); - let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); + pub fn init_logging(&mut self) -> anyhow::Result { + let log_dir_path = Path::new(LOG_DIR); + if !Path::new(LOG_DIR).exists() { + fs::create_dir_all(log_dir_path).expect("Failed to create log directory"); + } + + let appender = RollingFileAppender::builder() + .rotation(Rotation::DAILY) + .filename_prefix(LOG_PREFIX) + .build(LOG_DIR)?; + + let (non_blocking, guard) = tracing_appender::non_blocking(appender); + let filter = if self.debug { "server=debug" } else { "server=info" }; + let file_layer = fmt::layer() .with_writer(non_blocking) .with_ansi(false) - .with_filter(log_level); - + .with_filter(EnvFilter::new(filter)); + let console_layer = fmt::layer() .with_ansi(std::io::stdout().is_terminal()) - .with_filter(log_level); - + .with_filter(EnvFilter::new(filter)); + tracing_subscriber::registry() .with(file_layer) .with(console_layer) .init(); + + Ok(guard) } pub fn load_config(&self, auto_create: bool) -> anyhow::Result { - info!("loading configuration from file: {}", self.config.display()); + debug!("loading configuration from file: {}", self.config.display()); match self.config.exists() { false => match auto_create { diff --git a/crates/server/src/bin/style.rs b/crates/server/src/bin/style.rs index ce47601..f66c8b2 100644 --- a/crates/server/src/bin/style.rs +++ b/crates/server/src/bin/style.rs @@ -1,3 +1,4 @@ +use std::io::Read; use inquire::ui::{Attributes, Color, RenderConfig, StyleSheet, Styled}; pub fn styles() -> clap::builder::Styles { @@ -67,55 +68,29 @@ pub fn format_opaque_bytes(bytes: &[u8]) -> String { if bytes.len() < 8 { String::new() } else { - /* - // TODO: Hm, this can allow the same color for both, should rejig things to avoid this - // Select foreground and background colors based on the first 8 bytes. - let fg_color_index = bytes[0] % 8; - let bg_color_index = bytes[4] % 8; - - // ANSI escape codes for foreground and background colors. - let fg_color_code = 37; // 30 through 37 are foreground colors - let bg_color_code = 40; // 40 through 47 are background colors - */ - - // to be more general, perhaps this should be configurable - // an opaque address needs less space than an opaque memo, etc let max_bytes = 32; let rem = if bytes.len() > max_bytes { - bytes[0..max_bytes].to_vec() + &bytes[0..max_bytes] } else { - bytes.to_vec() + bytes }; - // Convert the rest of the bytes to hexadecimal. - let hex_str = hex::encode_upper(rem); - let opaque_chars: String = hex_str - .chars() - .map(|c| { + let hex_str: String = rem.iter().map(|b| format!("{:02x}", b)).collect(); + + let block_chars = [ + "\u{2595}", "\u{2581}", "\u{2582}", "\u{2583}", "\u{2584}", "\u{2585}", + "\u{2586}", "\u{2587}", "\u{2588}", "\u{2589}", "\u{259A}", "\u{259B}", + "\u{259C}", "\u{259D}", "\u{259E}", "\u{259F}" + ]; + + hex_str.chars() + .filter_map(|c| { match c { - '0' => "\u{2595}", - '1' => "\u{2581}", - '2' => "\u{2582}", - '3' => "\u{2583}", - '4' => "\u{2584}", - '5' => "\u{2585}", - '6' => "\u{2586}", - '7' => "\u{2587}", - '8' => "\u{2588}", - '9' => "\u{2589}", - 'A' => "\u{259A}", - 'B' => "\u{259B}", - 'C' => "\u{259C}", - 'D' => "\u{259D}", - 'E' => "\u{259E}", - 'F' => "\u{259F}", - _ => "", + '0'..='9' => Some(block_chars[c.to_digit(16).unwrap() as usize].to_string()), + 'a'..='f' => Some(block_chars[c.to_digit(16).unwrap() as usize].to_string()), + _ => None, } - .to_string() }) - .collect(); - - //format!("\u{001b}[{};{}m{}", fg_color_code, bg_color_code, block_chars) - opaque_chars + .collect() } } diff --git a/crates/server/src/runtime/session/generator/ip.rs b/crates/server/src/runtime/session/generator/ip.rs index 8af965c..e68044b 100644 --- a/crates/server/src/runtime/session/generator/ip.rs +++ b/crates/server/src/runtime/session/generator/ip.rs @@ -1,6 +1,5 @@ -use std::collections::HashSet; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use dashmap::DashSet; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; pub struct IpAddressGenerator { current: IpAddr, diff --git a/crates/shared/src/keys/mod.rs b/crates/shared/src/keys/mod.rs index a94e39b..6490ef5 100644 --- a/crates/shared/src/keys/mod.rs +++ b/crates/shared/src/keys/mod.rs @@ -19,21 +19,6 @@ impl Key { OsRng.fill_bytes(&mut key); Self(key) } - - pub fn to_hex(&self) -> String { - self.0.iter().map(|b| format!("{:02x}", b)).collect() - } - - pub fn from_hex(hex: &str) -> Result { - if hex.len() != SIZE * 2 { - return Err(anyhow::anyhow!("invalid key size, expected {} but actual {}", SIZE * 2, hex.len())); - } - let mut key = [0u8; SIZE]; - for (i, byte) in hex.as_bytes().chunks(2).enumerate() { - key[i] = u8::from_str_radix(std::str::from_utf8(byte)?, 16)?; - } - Ok(Self(key)) - } } impl Deref for Key { @@ -64,6 +49,13 @@ impl TryFrom<&str> for Key { } } +impl Display for Key { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", STANDARD_NO_PAD.encode(self.0)) + } +} + + impl Into<[u8; SIZE]> for Key { fn into(self) -> [u8; SIZE] { self.0 @@ -76,19 +68,13 @@ impl From<[u8; SIZE]> for Key { } } -impl Display for Key { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{:?}", &self.0) - } -} - impl Serialize for Key { fn serialize(&self, serializer: S) -> Result where S: Serializer, { if serializer.is_human_readable() { - let s = STANDARD_NO_PAD.encode(&self.0); + let s = STANDARD_NO_PAD.encode(self.0); serializer.serialize_str(&s) } else { serializer.serialize_bytes(&self.0)