You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
videl/src/progress/logging.rs

276 lines
6.3 KiB

//! Logging
use super::*;
use std::{
str,
fmt,
error,
};
use recolored::Colorize;
/// The logging level
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Level
{
Trace,
Debug,
Info,
Warning,
Error,
Fatal,
}
impl fmt::Display for Level
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}", match self {
Level::Trace => "TRACE".purple(),
Level::Debug => "DEBUG".blue(),
Level::Info => "INFO".green(),
Level::Warning => "WARNING".yellow(),
Level::Error => "ERROR".red(),
Level::Fatal => "FATAL".bright_red(),
})
}
}
impl str::FromStr for Level
{
type Err = LevelParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.trim().to_lowercase();
Ok(match s.as_str() {
"trace" => Level::Trace,
"debug" => Level::Debug,
"info" => Level::Info,
"warning" => Level::Warning,
"error" => Level::Error,
"fatal" => Level::Fatal,
_ => return Err(LevelParseError(s)),
})
}
}
#[derive(Debug)]
pub struct LevelParseError(String);
impl error::Error for LevelParseError{}
impl fmt::Display for LevelParseError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{:?} is not a valid logging level", self.0)
}
}
impl Level
{
fn is_err(&self) -> bool
{
match self {
Self::Error |
Self::Fatal |
Self::Warning => true,
_ => false,
}
}
fn should_print(&self, other: &Self) -> bool
{
other >= self
}
}
impl Default for Level
{
#[inline]
fn default() -> Self
{
Self::Info
}
}
/// Contains logging state
#[derive(Debug)]
pub struct Logger<B: ProgressBar = Bar>
{
level: Level,
progress: Handle<B>,
}
impl<B: ProgressBar> Clone for Logger<B>
{
fn clone(&self) -> Self
{
Self {
level: self.level,
progress: self.progress.clone(),
}
}
}
impl<B: ProgressBar> Logger<B>
{
/// Create a new logging state
pub fn new(progress: Handle<B>, level: Level) -> Self
{
Self{progress, level}
}
/// Get a reference of the progress handle
pub fn progress(&self) -> &Handle<B>
{
&self.progress
}
/// Get a mutable reference of the progress handle
pub fn progress_mut(&mut self) -> &mut Handle<B>
{
&mut self.progress
}
/// Get the logging level
pub fn level(&self) -> &Level
{
&self.level
}
/// Set the logging level
pub fn level_mut(&mut self) -> &mut Level
{
&mut self.level
}
fn gen_string(&self, level: &Level, disp: impl fmt::Display) -> String
{
format!("[ {} ]: \t{}", level, disp)
}
pub async fn print_display(&mut self, level: Level, disp: impl fmt::Display) -> Result<impl Future<Output=Result<Response, Error>>, Error>
{
if self.level.should_print(&level) {
let string = self.gen_string(&level, disp);
self.progress.send_command(if level.is_err() {CommandKind::LineErr(string)} else {CommandKind::Line(string)}).await
.map_err(Error::Progress)
.map(|x| x
.map_err(Error::Progress))
} else {
Err(Error::Level)
}
}
pub async fn print_display_and_wait(&mut self, level: Level, disp: impl fmt::Display) -> Result<Response, Error>
{
Ok(self.print_display(level, disp).await?.await?)
}
pub async fn print_display_and_detach(&mut self, level: Level, disp: impl fmt::Display) -> Result<(), Error>
{
let _ = self.print_display(level, disp).await?;
Ok(())
}
}
#[non_exhaustive]
#[derive(Debug)]
pub enum Error
{
Progress(WorkerCommError),
Level,
}
impl error::Error for Error
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(match &self {
Self::Progress(p) => p,
_ => return None,
})
}
}
impl fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Progress(_) => write!(f, "sending to progress worker failed"),
Self::Level => write!(f, "invalid level for write"),
}
}
}
impl From<WorkerCommError> for Error
{
#[inline] fn from(from: WorkerCommError) -> Self
{
Self::Progress(from)
}
}
#[macro_export] macro_rules! trace {
(yield $logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_wait($crate::progress::logging::Level::Trace, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
($logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_detach($crate::progress::logging::Level::Trace, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
}
#[macro_export] macro_rules! debug {
(yield $logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_wait($crate::progress::logging::Level::Debug, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
($logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_detach($crate::progress::logging::Level::Debug, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
}
#[macro_export] macro_rules! info {
(yield $logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_wait($crate::progress::logging::Level::Info, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
($logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_detach($crate::progress::logging::Level::Info, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
}
#[macro_export] macro_rules! warn {
(yield $logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_wait($crate::progress::logging::Level::Warn, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
($logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_detach($crate::progress::logging::Level::Warn, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
}
#[macro_export] macro_rules! error {
(yield $logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_wait($crate::progress::logging::Level::Error, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
($logger:expr => $msg:literal $($rest:tt)*) => {
{
let _ = $logger.print_display_and_detach($crate::progress::logging::Level::Error, ::lazy_format::lazy_format!($msg $($rest)*)).await;
}
};
}