refactor: start replacing log crate with custom macros (WIP)
Added custom logging macros to main.rs to prepare for removing the log crate dependency: - Added LogLevel enum and LOG_LEVEL static - Created log_error!, log_warn!, log_info!, log_debug! macros - Replaced log calls in main.rs with custom macros - Made format_timestamp() public for use in macros Still TODO: - Update websocket_client.rs, health.rs, version.rs - Remove log from Cargo.toml This is work in progress toward removing more dependencies.
This commit is contained in:
parent
55fb691440
commit
0daaf9ed68
1 changed files with 74 additions and 38 deletions
112
src/main.rs
112
src/main.rs
|
|
@ -6,14 +6,76 @@ mod version;
|
||||||
mod websocket_client;
|
mod websocket_client;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use log::{error, info, warn, LevelFilter, Metadata, Record};
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
use websocket_client::AgentClient;
|
use websocket_client::AgentClient;
|
||||||
|
|
||||||
|
// Log levels
|
||||||
|
static LOG_LEVEL: std::sync::OnceLock<LogLevel> = std::sync::OnceLock::new();
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
enum LogLevel {
|
||||||
|
Error = 1,
|
||||||
|
Warn = 2,
|
||||||
|
Info = 3,
|
||||||
|
Debug = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogLevel {
|
||||||
|
fn from_str(s: &str) -> Self {
|
||||||
|
match s.to_lowercase().as_str() {
|
||||||
|
"error" => LogLevel::Error,
|
||||||
|
"warn" => LogLevel::Warn,
|
||||||
|
"info" => LogLevel::Info,
|
||||||
|
"debug" => LogLevel::Debug,
|
||||||
|
_ => LogLevel::Info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! log_error {
|
||||||
|
($($arg:tt)*) => {{
|
||||||
|
let level = LOG_LEVEL.get().copied().unwrap_or(LogLevel::Info);
|
||||||
|
if level >= LogLevel::Error {
|
||||||
|
let ts = $crate::format_timestamp();
|
||||||
|
eprintln!("[{}] [ERROR] {}", ts, format!($($arg)*));
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! log_warn {
|
||||||
|
($($arg:tt)*) => {{
|
||||||
|
let level = LOG_LEVEL.get().copied().unwrap_or(LogLevel::Info);
|
||||||
|
if level >= LogLevel::Warn {
|
||||||
|
let ts = $crate::format_timestamp();
|
||||||
|
eprintln!("[{}] [WARN] {}", ts, format!($($arg)*));
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! log_info {
|
||||||
|
($($arg:tt)*) => {{
|
||||||
|
let level = LOG_LEVEL.get().copied().unwrap_or(LogLevel::Info);
|
||||||
|
if level >= LogLevel::Info {
|
||||||
|
let ts = $crate::format_timestamp();
|
||||||
|
eprintln!("[{}] [INFO] {}", ts, format!($($arg)*));
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! log_debug {
|
||||||
|
($($arg:tt)*) => {{
|
||||||
|
let level = LOG_LEVEL.get().copied().unwrap_or(LogLevel::Info);
|
||||||
|
if level >= LogLevel::Debug {
|
||||||
|
let ts = $crate::format_timestamp();
|
||||||
|
eprintln!("[{}] [DEBUG] {}", ts, format!($($arg)*));
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
/// Format current timestamp as "YYYY-MM-DD HH:MM:SS.mmm"
|
/// Format current timestamp as "YYYY-MM-DD HH:MM:SS.mmm"
|
||||||
fn format_timestamp() -> String {
|
pub fn format_timestamp() -> String {
|
||||||
let now = SystemTime::now()
|
let now = SystemTime::now()
|
||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
@ -78,36 +140,10 @@ fn days_to_month_day(days: u16, is_leap: bool) -> (u8, u8) {
|
||||||
(12, 31) // Fallback
|
(12, 31) // Fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Minimal logger that writes to stderr with timestamps
|
|
||||||
struct SimpleLogger {
|
|
||||||
level: LevelFilter,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl log::Log for SimpleLogger {
|
|
||||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
|
||||||
metadata.level() <= self.level
|
|
||||||
}
|
|
||||||
|
|
||||||
fn log(&self, record: &Record) {
|
|
||||||
if self.enabled(record.metadata()) {
|
|
||||||
let timestamp = format_timestamp();
|
|
||||||
eprintln!("[{}] [{}] {}", timestamp, record.level(), record.args());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_logger() {
|
fn init_logger() {
|
||||||
let level = env::var("RUST_LOG")
|
let level_str = env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string());
|
||||||
.unwrap_or_else(|_| "info".to_string())
|
let level = LogLevel::from_str(&level_str);
|
||||||
.parse::<LevelFilter>()
|
LOG_LEVEL.set(level).ok();
|
||||||
.unwrap_or(LevelFilter::Info);
|
|
||||||
|
|
||||||
let logger = SimpleLogger { level };
|
|
||||||
log::set_boxed_logger(Box::new(logger))
|
|
||||||
.map(|()| log::set_max_level(level))
|
|
||||||
.ok();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert HTTP(S) URL to WebSocket URL
|
/// Convert HTTP(S) URL to WebSocket URL
|
||||||
|
|
@ -144,7 +180,7 @@ async fn main() {
|
||||||
|
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
info!("Towerops agent starting");
|
log_info!("Towerops agent starting");
|
||||||
|
|
||||||
// Check for newer Docker image version
|
// Check for newer Docker image version
|
||||||
version::check_for_updates();
|
version::check_for_updates();
|
||||||
|
|
@ -152,12 +188,12 @@ async fn main() {
|
||||||
// Convert HTTP(S) URL to WebSocket URL
|
// Convert HTTP(S) URL to WebSocket URL
|
||||||
let ws_url = convert_to_websocket_url(&args.api_url);
|
let ws_url = convert_to_websocket_url(&args.api_url);
|
||||||
|
|
||||||
info!("WebSocket URL: {}", ws_url);
|
log_info!("WebSocket URL: {}", ws_url);
|
||||||
|
|
||||||
// Start simple health endpoint (no storage needed for WebSocket mode)
|
// Start simple health endpoint (no storage needed for WebSocket mode)
|
||||||
tokio::spawn(async {
|
tokio::spawn(async {
|
||||||
if let Err(e) = health::start_health_server(8080).await {
|
if let Err(e) = health::start_health_server(8080).await {
|
||||||
warn!("Health server error: {}", e);
|
log_warn!("Health server error: {}", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -170,7 +206,7 @@ async fn main() {
|
||||||
attempt += 1;
|
attempt += 1;
|
||||||
|
|
||||||
if attempt > 1 {
|
if attempt > 1 {
|
||||||
info!(
|
log_info!(
|
||||||
"Retry attempt {} - waiting {} seconds before reconnecting",
|
"Retry attempt {} - waiting {} seconds before reconnecting",
|
||||||
attempt,
|
attempt,
|
||||||
retry_delay.as_secs()
|
retry_delay.as_secs()
|
||||||
|
|
@ -184,21 +220,21 @@ async fn main() {
|
||||||
// Connect to Towerops server via WebSocket
|
// Connect to Towerops server via WebSocket
|
||||||
let mut client = match AgentClient::connect(&ws_url, &args.token).await {
|
let mut client = match AgentClient::connect(&ws_url, &args.token).await {
|
||||||
Ok(client) => {
|
Ok(client) => {
|
||||||
info!("Successfully connected to server");
|
log_info!("Successfully connected to server");
|
||||||
// Reset retry delay on successful connection
|
// Reset retry delay on successful connection
|
||||||
retry_delay = Duration::from_secs(1);
|
retry_delay = Duration::from_secs(1);
|
||||||
attempt = 0;
|
attempt = 0;
|
||||||
client
|
client
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Failed to connect to server: {}", e);
|
log_error!("Failed to connect to server: {}", e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run the agent event loop
|
// Run the agent event loop
|
||||||
if let Err(e) = client.run().await {
|
if let Err(e) = client.run().await {
|
||||||
error!("Agent disconnected: {}", e);
|
log_error!("Agent disconnected: {}", e);
|
||||||
// Loop will retry with backoff
|
// Loop will retry with backoff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue