Replace log crate with tracing

This commit is contained in:
Jackson Coxson
2025-10-23 09:49:38 -06:00
parent 18b8b7295c
commit a297eed156
91 changed files with 323 additions and 342 deletions

View File

@@ -3,75 +3,12 @@
use std::{
ffi::{CStr, c_char},
fs::File,
sync::Once,
};
use log::LevelFilter;
use simplelog::{
ColorChoice, CombinedLogger, Config, SharedLogger, TermLogger, TerminalMode, WriteLogger,
};
/// Initializes the logger
///
/// # Arguments
/// * [`console_level`] - The level to log to the file
/// * [`file_level`] - The level to log to the file
/// * [`file_path`] - If not null, the file to write logs to
///
/// ## Log Level
/// 0. Disabled
/// 1. Error
/// 2. Warn
/// 3. Info
/// 4. Debug
/// 5. Trace
///
/// # Returns
/// 0 for success, -1 if the file couldn't be created, -2 if a logger has been initialized, -3 for invalid path string
///
/// # Safety
/// Pass a valid CString for file_path. Pass valid log levels according to the enum
#[unsafe(no_mangle)]
pub unsafe extern "C" fn idevice_init_logger(
console_level: IdeviceLogLevel,
file_level: IdeviceLogLevel,
file_path: *mut c_char,
) -> IdeviceLoggerError {
let mut loggers: Vec<Box<dyn SharedLogger>> = Vec::new();
let level: LevelFilter = console_level.into();
loggers.push(TermLogger::new(
level,
Config::default(),
TerminalMode::Mixed,
ColorChoice::Auto,
));
if !file_path.is_null() {
let file_path = match unsafe { CStr::from_ptr(file_path) }.to_str() {
Ok(f) => f.to_string(),
Err(_) => {
return IdeviceLoggerError::InvalidPathString;
}
};
let level: LevelFilter = file_level.into();
loggers.push(WriteLogger::new(
level,
Config::default(),
match File::create(file_path) {
Ok(f) => f,
Err(e) => {
println!("Failed to create path: {e:?}");
return IdeviceLoggerError::FileError;
}
},
));
}
if CombinedLogger::init(loggers).is_err() {
IdeviceLoggerError::AlreadyInitialized
} else {
IdeviceLoggerError::Success
}
}
use tracing::Level;
use tracing_subscriber::{EnvFilter, Layer, fmt::writer::BoxMakeWriter};
use tracing_subscriber::{Registry, fmt, layer::SubscriberExt, util::SubscriberInitExt};
#[repr(C)]
pub enum IdeviceLoggerError {
@@ -92,33 +29,99 @@ pub enum IdeviceLogLevel {
Trace = 5,
}
impl TryFrom<u8> for IdeviceLogLevel {
type Error = ();
fn try_from(value: u8) -> Result<Self, Self::Error> {
Ok(match value {
0 => Self::Disabled,
1 => Self::ErrorLevel,
2 => Self::Warn,
3 => Self::Info,
4 => Self::Debug,
5 => Self::Trace,
_ => {
return Err(());
}
})
}
}
impl From<IdeviceLogLevel> for LevelFilter {
impl From<IdeviceLogLevel> for Level {
fn from(value: IdeviceLogLevel) -> Self {
match value {
IdeviceLogLevel::Disabled => LevelFilter::Off,
IdeviceLogLevel::ErrorLevel => LevelFilter::Error,
IdeviceLogLevel::Warn => LevelFilter::Warn,
IdeviceLogLevel::Info => LevelFilter::Info,
IdeviceLogLevel::Debug => LevelFilter::Debug,
IdeviceLogLevel::Trace => LevelFilter::Trace,
IdeviceLogLevel::Disabled => Level::ERROR, // won't matter, filter will disable
IdeviceLogLevel::ErrorLevel => Level::ERROR,
IdeviceLogLevel::Warn => Level::WARN,
IdeviceLogLevel::Info => Level::INFO,
IdeviceLogLevel::Debug => Level::DEBUG,
IdeviceLogLevel::Trace => Level::TRACE,
}
}
}
impl IdeviceLogLevel {
fn as_filter(&self) -> String {
match self {
IdeviceLogLevel::Disabled => "off",
IdeviceLogLevel::ErrorLevel => "error",
IdeviceLogLevel::Warn => "warn",
IdeviceLogLevel::Info => "info",
IdeviceLogLevel::Debug => "debug",
IdeviceLogLevel::Trace => "trace",
}
.to_string()
}
}
// ensures we only init once
static INIT: Once = Once::new();
/// Initializes the global logger
///
/// # Safety
/// Pass a valid file path string
#[unsafe(no_mangle)]
pub unsafe extern "C" fn idevice_init_logger(
console_level: IdeviceLogLevel,
file_level: IdeviceLogLevel,
file_path: *mut c_char,
) -> IdeviceLoggerError {
let mut init_result = IdeviceLoggerError::Success;
INIT.call_once(|| {
let console_filter = console_level.as_filter();
let file_filter = file_level.as_filter();
let mut layers = Vec::new();
// Console layer
if console_level != IdeviceLogLevel::Disabled {
let console_layer = fmt::layer()
.with_writer(std::io::stdout)
.with_ansi(true)
.with_target(false)
.with_filter(EnvFilter::new(console_filter));
layers.push(console_layer.boxed());
}
// File layer
if !file_path.is_null() && file_level != IdeviceLogLevel::Disabled {
let path = match unsafe { CStr::from_ptr(file_path).to_str() } {
Ok(p) => p,
Err(_) => {
init_result = IdeviceLoggerError::InvalidPathString;
return;
}
};
let file = match File::create(path) {
Ok(f) => f,
Err(_) => {
init_result = IdeviceLoggerError::FileError;
return;
}
};
let file_layer = fmt::layer()
.with_writer(BoxMakeWriter::new(file))
.with_ansi(false)
.with_target(false)
.with_filter(EnvFilter::new(file_filter));
layers.push(file_layer.boxed());
}
// Compose and set as global subscriber
let subscriber = Registry::default().with(layers);
subscriber.init();
});
// If it was already initialized, Once won't run again
if !INIT.is_completed() {
IdeviceLoggerError::AlreadyInitialized
} else {
init_result
}
}