feat: add logging capabilities

This commit is contained in:
Alexander Navarro 2025-05-08 16:52:01 -04:00
parent 3d12877e27
commit 56888931bd
3 changed files with 48 additions and 80 deletions

View file

@ -1,9 +1,11 @@
use clap::Parser; use clap::{Parser, ValueEnum};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt;
use std::path::PathBuf; use std::path::PathBuf;
use tracing_core::{Level, LevelFilter}; use tracing_core::LevelFilter;
pub enum VerbosityFilter { #[derive(ValueEnum, Clone, Debug, Deserialize, Serialize)]
pub enum VerbosityLevel {
Off, Off,
Error, Error,
Warn, Warn,
@ -12,61 +14,45 @@ pub enum VerbosityFilter {
Trace, Trace,
} }
impl VerbosityFilter { impl Default for VerbosityLevel {
fn with_offset(&self, offset: i16) -> VerbosityFilter { fn default() -> Self {
let value = match self { VerbosityLevel::Error
Self::Off => 0_i16,
Self::Error => 1,
Self::Warn => 2,
Self::Info => 3,
Self::Debug => 4,
Self::Trace => 5,
};
match value.saturating_add(offset) {
i16::MIN..=0 => Self::Off,
1 => Self::Error,
2 => Self::Warn,
3 => Self::Info,
4 => Self::Debug,
5..=i16::MAX => Self::Trace,
} }
}
} }
impl From<LevelFilter> for VerbosityFilter { impl fmt::Display for VerbosityLevel {
fn from(level: LevelFilter) -> Self { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match level { match self {
LevelFilter::OFF => Self::Off, VerbosityLevel::Off => {
LevelFilter::ERROR => Self::Error, write!(f, "off")
LevelFilter::WARN => Self::Warn, }
LevelFilter::INFO => Self::Info, VerbosityLevel::Error => {
LevelFilter::DEBUG => Self::Debug, write!(f, "error")
LevelFilter::TRACE => Self::Trace, }
VerbosityLevel::Warn => {
write!(f, "warn")
}
VerbosityLevel::Info => {
write!(f, "info")
}
VerbosityLevel::Debug => {
write!(f, "debug")
}
VerbosityLevel::Trace => {
write!(f, "trace")
}
} }
} }
} }
impl From<VerbosityFilter> for Option<Level> { impl Into<LevelFilter> for VerbosityLevel {
fn from(filter: VerbosityFilter) -> Self { fn into(self) -> LevelFilter {
match filter { match self {
VerbosityFilter::Off => None, VerbosityLevel::Off => LevelFilter::OFF,
VerbosityFilter::Error => Some(Level::ERROR), VerbosityLevel::Error => LevelFilter::ERROR,
VerbosityFilter::Warn => Some(Level::WARN), VerbosityLevel::Warn => LevelFilter::WARN,
VerbosityFilter::Info => Some(Level::INFO), VerbosityLevel::Info => LevelFilter::INFO,
VerbosityFilter::Debug => Some(Level::DEBUG), VerbosityLevel::Debug => LevelFilter::DEBUG,
VerbosityFilter::Trace => Some(Level::TRACE), VerbosityLevel::Trace => LevelFilter::TRACE,
}
}
}
impl From<Option<Level>> for VerbosityFilter {
fn from(level: Option<Level>) -> Self {
match level {
None => Self::Off,
Some(Level::ERROR) => Self::Error,
Some(Level::WARN) => Self::Warn,
Some(Level::INFO) => Self::Info,
Some(Level::DEBUG) => Self::Debug,
Some(Level::TRACE) => Self::Trace,
} }
} }
} }
@ -77,40 +63,19 @@ pub struct Config {
#[arg( #[arg(
long, long,
short = 'v', short = 'v',
action = clap::ArgAction::Count, default_value_t,
global = true, global = true,
help = "Increase logging verbosity", help = "Increase logging verbosity"
)] )]
verbose: u8, log_level: VerbosityLevel,
#[arg(
long,
short = 'q',
action = clap::ArgAction::Count,
global = true,
help = "Decrease logging verbosity",
conflicts_with = "verbose",
)]
quiet: u8,
} }
impl Config { impl Config {
pub fn path(&self) -> &PathBuf { pub fn path(&self) -> &PathBuf {
&self.path &self.path
} }
/// Gets the filter that should be applied to the logger.
///
pub fn filter(&self) -> VerbosityFilter {
let offset = self.verbose as i16 - self.quiet as i16;
VerbosityFilter::Error.with_offset(offset)
}
pub fn tracing_level(&self) -> Option<tracing_core::Level> { pub fn log_level(&self) -> LevelFilter {
self.filter().into() self.log_level.clone().into()
}
/// Get the tracing level filter.
pub fn tracing_level_filter(&self) -> tracing_core::LevelFilter {
self.filter().into()
} }
} }

View file

@ -22,6 +22,9 @@ pub enum Error {
#[error(transparent)] #[error(transparent)]
ParseJson(#[from] serde_json::Error), ParseJson(#[from] serde_json::Error),
#[error(transparent)]
Config(#[from] figment::Error),
} }
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;

View file

@ -5,7 +5,7 @@ use readwise_bulk_upload::sql::TaskManager;
use readwise_bulk_upload::{Error, Result}; use readwise_bulk_upload::{Error, Result};
use std::fs::File; use std::fs::File;
use tracing_subscriber; use tracing_subscriber;
use figment::{Figment, providers::{Serialized, Env, Format}}; use figment::{Figment, providers::{Serialized, Env}};
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
@ -15,7 +15,7 @@ async fn main() -> Result<()> {
.extract()?; .extract()?;
tracing_subscriber::fmt() tracing_subscriber::fmt()
.with_max_level(args.verbose) .with_max_level(args.log_level())
.init(); .init();
let file = File::open(args.path()).map_err(|_| { let file = File::open(args.path()).map_err(|_| {