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.
276 lines
6.3 KiB
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;
|
|
}
|
|
};
|
|
}
|