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.
139 lines
2.8 KiB
139 lines
2.8 KiB
use super::*;
|
|
use std::{
|
|
fmt,
|
|
};
|
|
use lazy_static::lazy_static;
|
|
|
|
/// Logging mode
|
|
#[derive(Debug,Clone,PartialEq,Eq,Hash)]
|
|
pub enum Mode
|
|
{
|
|
/// Output nothing
|
|
None,
|
|
/// Only print errors
|
|
Error,
|
|
/// Only print warnings
|
|
Warn,
|
|
/// Verbose message
|
|
Verbose,
|
|
/// Debug messages
|
|
Debug,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq,Eq,Hash)]
|
|
pub enum Level
|
|
{
|
|
Debug,
|
|
Info,
|
|
Warning,
|
|
Error,
|
|
Fatal,
|
|
}
|
|
|
|
const LEVELS_FOR: &[(Mode, &[Level]); 5] = &[
|
|
(Mode::None, &[]),
|
|
(Mode::Error, &[Level::Fatal, Level::Error]),
|
|
(Mode::Warn, &[Level::Fatal, Level::Error, Level::Warning]),
|
|
(Mode::Verbose, &[Level::Fatal, Level::Error, Level::Warning, Level::Info]),
|
|
(Mode::Debug, &[Level::Fatal, Level::Error, Level::Warning, Level::Info, Level::Debug]),
|
|
];
|
|
|
|
impl Mode
|
|
{
|
|
/// Can we print this level?
|
|
#[inline]
|
|
pub fn level(&self, lv: Level) -> Option<Level>
|
|
{
|
|
if lv.mode_ok(self) {
|
|
Some(lv)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Level
|
|
{
|
|
/// Can we print for `mode`?
|
|
pub fn mode_ok(&self, mode: &Mode) -> bool
|
|
{
|
|
use std::collections::{HashMap, HashSet};
|
|
lazy_static! {
|
|
static ref MAP: HashMap<&'static Mode, HashSet<&'static Level>> = {
|
|
let mut m = HashMap::new();
|
|
for (key, values) in LEVELS_FOR.iter() {
|
|
let mut set = HashSet::new();
|
|
for value in values.iter() {
|
|
set.insert(value);
|
|
}
|
|
m.insert(key, set);
|
|
}
|
|
m
|
|
};
|
|
}
|
|
|
|
if let Some(values) = MAP.get(mode) {
|
|
if values.contains(self) {
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
} else {
|
|
unreachable!()
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Level
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
{
|
|
match self {
|
|
Level::Debug => write!(f, "DEBUG"),
|
|
Level::Info => write!(f, "INFO"),
|
|
Level::Warning => write!(f, "WARN"),
|
|
Level::Error => write!(f, "ERROR"),
|
|
Level::Fatal => write!(f, "FATAL"),
|
|
_ => write!(f, "(unbound)"),
|
|
}
|
|
}
|
|
}
|
|
|
|
macro_rules! log {
|
|
($level:tt, $mode:expr => $format:expr, $($rest:expr),*) => {
|
|
{
|
|
if let Some(level) = $mode.level($crate::log::Level::$level) {
|
|
println!("{} [{}]: {}", $crate::log::timestamp(), level, format!($format, $($rest)*));
|
|
true
|
|
} else {
|
|
false
|
|
};
|
|
}
|
|
};
|
|
($mode:expr => $format:expr, $($rest:expr),*) => {
|
|
{
|
|
log!(Info, $mode => $format, $($rest)*);
|
|
}
|
|
};
|
|
($level:expr, $format:expr, $($rest:expr),*) => {
|
|
if let Some(level) = $level {
|
|
println!("{} [{}]: {}", $crate::log::timestamp(), level, format!($format, $($rest)*));
|
|
true
|
|
} else {
|
|
false
|
|
};
|
|
};
|
|
}
|
|
|
|
pub fn timestamp() -> String
|
|
{
|
|
use chrono::{
|
|
offset::Utc,
|
|
DateTime,
|
|
};
|
|
let time: DateTime<Utc> = std::time::SystemTime::now().into();
|
|
time.format("%Y.%m.%d %h:%M:%S").to_string()
|
|
}
|
|
|
|
//log!(Level::Debug, cmode => "Hello {}", "hi");
|