feat: logging without log crate

This commit is contained in:
Vladimir Rubin 2025-04-26 21:03:39 +03:00
parent 6063f5cb0a
commit 709c9a81e0
Signed by: vavakado
GPG key ID: CAB744727F36B524
5 changed files with 210 additions and 177 deletions

170
Cargo.lock generated
View file

@ -17,15 +17,6 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "android-tzdata" name = "android-tzdata"
version = "0.1.1" version = "0.1.1"
@ -41,56 +32,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
dependencies = [
"anstyle",
"once_cell",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "async-broadcast" name = "async-broadcast"
version = "0.7.2" version = "0.7.2"
@ -336,12 +277,6 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]] [[package]]
name = "concurrent-queue" name = "concurrent-queue"
version = "2.5.0" version = "2.5.0"
@ -409,29 +344,6 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "env_filter"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
"log",
"regex",
]
[[package]]
name = "env_logger"
version = "0.11.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"jiff",
"log",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.2" version = "1.0.2"
@ -541,8 +453,6 @@ name = "hinoirisetr"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"env_logger",
"log",
"notify-rust", "notify-rust",
"serde", "serde",
"tokio", "tokio",
@ -583,36 +493,6 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "jiff"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6"
dependencies = [
"jiff-static",
"log",
"portable-atomic",
"portable-atomic-util",
"serde",
]
[[package]]
name = "jiff-static"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.77" version = "0.3.77"
@ -838,21 +718,6 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "portable-atomic"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
[[package]]
name = "portable-atomic-util"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
dependencies = [
"portable-atomic",
]
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@ -901,35 +766,6 @@ version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.24" version = "0.1.24"
@ -1233,12 +1069,6 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"

View file

@ -5,8 +5,6 @@ edition = "2024"
[dependencies] [dependencies]
chrono = "0.4.40" chrono = "0.4.40"
env_logger = "0.11.8"
log = "0.4.27"
notify-rust = "4.11.7" notify-rust = "4.11.7"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
toml = "0.8" toml = "0.8"

View file

@ -6,9 +6,10 @@ use std::path::Path;
use std::process::Command; use std::process::Command;
use chrono::{DateTime, Local, Timelike}; use chrono::{DateTime, Local, Timelike};
use log::{debug, trace};
use serde::Deserialize; use serde::Deserialize;
pub mod log;
#[derive(Debug, Deserialize, Copy, Clone)] #[derive(Debug, Deserialize, Copy, Clone)]
#[serde(default)] #[serde(default)]
pub struct Config { pub struct Config {

200
src/log.rs Normal file
View file

@ -0,0 +1,200 @@
use std::fmt::{Display, Formatter};
use std::sync::atomic::{AtomicU8, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
/// Levels of logging verbosity
#[derive(PartialEq, PartialOrd, Ord, Eq, Debug, Clone, Copy)]
pub enum LogLevel {
Error = 1,
Warn = 2,
Info = 3,
Debug = 4,
Trace = 5,
}
static GLOBAL_LOG_LEVEL: AtomicU8 = AtomicU8::new(LogLevel::Info as u8);
// Check if a year is a leap year
fn is_leap_year(year: u32) -> bool {
(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
}
// Convert seconds since epoch to YYYY-MM-DD HH:MM:SS (UTC)
fn format_timestamp(seconds: u64) -> String {
let mut days = (seconds / 86_400) as u32; // Total days since epoch
let seconds_in_day = (seconds % 86_400) as u32;
let hours = seconds_in_day / 3600;
let minutes = (seconds_in_day % 3600) / 60;
let seconds = seconds_in_day % 60;
// Calculate year
let mut year = 1970;
while days > 0 {
let days_in_year = if is_leap_year(year) { 366 } else { 365 };
if days >= days_in_year {
days -= days_in_year;
year += 1;
} else {
break;
}
}
// Month lengths (non-leap and leap year variants)
let month_lengths = if is_leap_year(year) {
[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
} else {
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
};
// Calculate month and day
let mut month = 1;
for &len in month_lengths.iter() {
if days < len {
break;
}
days -= len;
month += 1;
}
let day = days + 1; // Days are 1-based
format!(
"{:04}-{:02}-{:02} {:02}:{:02}:{:02}",
year, month, day, hours, minutes, seconds
)
}
/// Set the global log level at runtime
pub fn set_log_level(level: LogLevel) {
GLOBAL_LOG_LEVEL.store(level as u8, Ordering::Relaxed);
}
/// Get the current global log level
pub fn get_log_level() -> LogLevel {
match GLOBAL_LOG_LEVEL.load(Ordering::Relaxed) {
1 => LogLevel::Error,
2 => LogLevel::Warn,
3 => LogLevel::Info,
4 => LogLevel::Debug,
5 => LogLevel::Trace,
_ => LogLevel::Info,
}
}
impl Display for LogLevel {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
// ANSI color codes for terminal output
const RED: &str = "\x1b[31m"; // Error
const YELLOW: &str = "\x1b[33m"; // Warn
const GREEN: &str = "\x1b[32m"; // Info
const CYAN: &str = "\x1b[36m"; // Debug
const MAGENTA: &str = "\x1b[35m"; // Trace
const RESET: &str = "\x1b[0m"; // Reset color
match self {
LogLevel::Error => write!(f, "{}[{:>5}]{}", RED, "ERROR", RESET),
LogLevel::Warn => write!(f, "{}[{:>5}]{}", YELLOW, "WARN", RESET),
LogLevel::Info => write!(f, "{}[{:>5}]{}", GREEN, "INFO", RESET),
LogLevel::Debug => write!(f, "{}[{:>5}]{}", CYAN, "DEBUG", RESET),
LogLevel::Trace => write!(f, "{}[{:>5}]{}", MAGENTA, "TRACE", RESET),
}
}
}
/// Internal logger: prints if level is <= current global level
#[doc(hidden)]
pub fn log_internal(level: LogLevel, file: &str, line: u32, msg: &str) {
if (level as u8) <= (get_log_level() as u8) {
let timestamp = format_timestamp(
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
);
if level == LogLevel::Trace {
println!("{} |{timestamp}| {file}:{line} - {msg}", LogLevel::Trace);
} else {
println!("{level} |{timestamp}| - {msg}");
}
}
}
/// Log an error-level message
#[macro_export]
macro_rules! error {
($($arg:tt)+) => {
$crate::log::log_internal(
$crate::log::LogLevel::Error,
file!(),
line!(),
&format!($($arg)+),
);
};
}
/// Log a warning-level message
#[macro_export]
macro_rules! warn {
($($arg:tt)+) => {
$crate::log::log_internal(
$crate::log::LogLevel::Warn,
file!(),
line!(),
&format!($($arg)+),
);
};
}
/// Log an info-level message
#[macro_export]
macro_rules! info {
($($arg:tt)+) => {
$crate::log::log_internal(
$crate::log::LogLevel::Info,
file!(),
line!(),
&format!($($arg)+),
);
};
}
/// Log a debug-level message (only in debug builds)
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! debug {
($($arg:tt)+) => {
$crate::log::log_internal(
$crate::log::LogLevel::Debug,
file!(),
line!(),
&format!($($arg)+),
);
};
}
/// No-op debug in release builds
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! debug {
($($arg:tt)+) => {};
}
/// Log a trace-level message (only in debug builds)
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! trace {
($($arg:tt)+) => {
$crate::log::log_internal(
$crate::log::LogLevel::Trace,
file!(),
line!(),
&format!($($arg)+),
);
};
}
/// No-op trace in release builds
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! trace {
($($arg:tt)+) => {};
}

View file

@ -5,8 +5,7 @@ use std::sync::{Arc, OnceLock};
use std::time::Duration; use std::time::Duration;
use chrono::Local; use chrono::Local;
use hinoirisetr::{Config, apply_settings, compute_settings}; use hinoirisetr::{apply_settings, compute_settings, debug, error, info, trace, warn, Config};
use log::{debug, error, info, trace, warn};
use notify_rust::Notification; use notify_rust::Notification;
use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::net::UnixListener; use tokio::net::UnixListener;
@ -100,8 +99,13 @@ async fn socket_server(disabled: Arc<AtomicBool>, notify: Arc<Notify>) {
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
env_logger::init(); info!("starting the daemon");
log::info!("starting the daemon"); warn!("log level: {:?}", hinoirisetr::log::get_log_level());
error!("log level: {:?}", hinoirisetr::log::get_log_level());
trace!("log level: {:?}", hinoirisetr::log::get_log_level());
debug!("log level: {:?}", hinoirisetr::log::get_log_level());
hinoirisetr::log::set_log_level(hinoirisetr::log::LogLevel::Trace);
if !is_binary_available("hyprctl") { if !is_binary_available("hyprctl") {
error!("hyprctl is not available, exiting."); error!("hyprctl is not available, exiting.");