logger hooks

master
Avril 4 years ago
parent 92d88ce74a
commit 55b71a10dc
Signed by: flanchan
GPG Key ID: 284488987C31F630

10
Cargo.lock generated

@ -284,6 +284,15 @@ dependencies = [
"slab",
]
[[package]]
name = "generational-arena"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d3b771574f62d0548cee0ad9057857e9fc25d7a3335f140c84f6acd0bf601"
dependencies = [
"cfg-if",
]
[[package]]
name = "gimli"
version = "0.22.0"
@ -383,6 +392,7 @@ dependencies = [
"chrono",
"config_struct",
"futures",
"generational-arena",
"lazy_static",
"libc",
"notify",

@ -39,6 +39,7 @@ recolored = "1.9.3"
chrono = "0.4"
libc = "0.2"
cfg-if = "0.1"
generational-arena = "0.2"
[build-dependencies]
rustc_version = "0.2"

@ -6,3 +6,4 @@ timeout = 5
# Logging options
[log]
default_time_local = false
date_format = "%Y-%m-%d %H:%M:%S %Z"

@ -59,6 +59,7 @@ pub mod build
pub use super::*;
pub const DEFAULT_LOCAL_TIME: bool = CONFIG.log.default_time_local;
pub const DATE_FORMAT: std::borrow::Cow<'static, str> = CONFIG.log.date_format;
}
/// Print the status of `build.toml` vars

@ -63,7 +63,7 @@ pub type Event = event::EventKind;
/// Max event backlog (not used if `unlimited_watcher` is set)
const GLOBAL_BACKLOG: usize = config::build::hot::BACKLOG; //100;
/// Timeout for hook dispatches in seconds. Only set if `watcher_timeout` feature is enabled.
const GLOBAL_TIMEOUT: u64 = config::build::hot::TIMEOUT;
const GLOBAL_TIMEOUT: u64 = config::build::hot::TIMEOUT; //5
/// Decontruct a notify event into event kind and full paths.
#[inline]
@ -178,7 +178,7 @@ impl Hook {
/// A hook container for `Oneesan`
#[derive(Debug, Clone)]
pub struct HookContainer(Arc<RwLock<Vec<Hook>>>);
pub struct HookContainer(Arc<RwLock<Vec<Hook>>>); //TODO: Change to Arena
impl HookContainer
{

@ -1,519 +0,0 @@
//! Global logging state
use super::util::*;
use std::{
fmt::{
self,
Display,
},
io::{
self,
Write,
},
borrow::Borrow,
sync::{RwLock},
};
use once_cell::sync::OnceCell;
/// Print local time by default
const DEFAULT_USE_LOCAL_TIME: bool = crate::config::build::log::DEFAULT_LOCAL_TIME;
/// Logging level
#[derive(PartialEq,Copy,Eq,Debug,Clone,Hash,Ord,PartialOrd)]
pub enum Level
{
Silent,
Error,
Warn,
Info,
Debug,
}
/// Contains backtrace info from where the log macro was invoked
#[derive(Debug)]
pub struct Trace
{
line: Option<usize>,
file: Option<&'static str>,
column: Option<usize>,
display: Opaque<RwLock<Option<String>>>,
}
impl Clone for Trace
{
#[inline]
fn clone(&self) -> Self
{
Self {
line: self.line.clone(),
file: self.file.clone(),
column: self.column.clone(),
display: Opaque::new(RwLock::new(None)),
}
}
}
impl std::hash::Hash for Trace
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H)
{
self.line.hash(state);
self.file.hash(state);
self.column.hash(state);
}
}
impl std::cmp::PartialEq for Trace
{
fn eq(&self, other: &Self)->bool
{
self.line == other.line &&
self.file == other.file &&
self.column == other.column
}
}
impl Trace
{
/// Create a new `Trace` manually. Generally not desireable, use `get_trace!()` instead.
pub fn new(file: Option<&'static str>, line: Option<u32>, column: Option<u32>) -> Self
{
use std::convert::TryInto;
let this = Self{
file,
line: line.and_then(|x| x.try_into().ok()),
column: column.and_then(|x| x.try_into().ok()),
display: Opaque::new(RwLock::new(None)),
};
this
}
fn genstring(&self) -> Result<String, fmt::Error>
{
let mut out = String::new();
use std::fmt::Write as FmtWrite;
write!(out, "{}", self.file.unwrap_or("(unbound)"))?;
if let Some(line) = self.line {
write!(&mut out, ":{}", line)?;
} else {
write!(&mut out, ":?")?;
}
if let Some(column) = self.column {
write!(&mut out, ":{}", column)?;
} else {
write!(&mut out, ":?")?;
}
Ok(out)
}
}
impl std::fmt::Display for Trace
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
{
let read = self.display.read().expect("Poisoned");
if let Some(opt) = read.as_ref()
{
write!(f, "{}", opt)?;
return Ok(());
}
}
let out = self.genstring()?;
write!(f, "{}", out)?;
let mut write = self.display.write().expect("Poisoned");
*write = Some(out);
Ok(())
}
}
impl Default for Trace
{
#[inline]
fn default() -> Self
{
Self{
line:None,
file:None,
column:None,
display: Opaque::new(RwLock::new(None)),
}
}
}
/// Get a source code trace of the current file, line and column.
#[macro_export] macro_rules! get_trace
{
() => {
$crate::log::Trace::new(Some(file!()), Some(line!()), Some(column!()))
}
}
/// Append this trait to allow you to
pub trait AsLevel: fmt::Display + Borrow<Level>{
/// Used for derived levels
fn prefix(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}/", Borrow::<Level>::borrow(self))
}
}
impl AsLevel for Level{
#[inline] fn prefix(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result{Ok(())}
}
impl AsLevel for &Level{
#[inline] fn prefix(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result{Ok(())}
}
impl Default for Level
{
#[inline]
fn default() -> Level
{
#[cfg(debug_assertions)]
return Level::Debug;
#[cfg(not(debug_assertions))]
return Level::Warn;
}
}
impl std::fmt::Display for Level
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
use recolored::Colorize;
write!(f, "{}", match &self {
Self::Silent => "Fatal".bright_red().bold(),
Self::Error => "Error".red(),
Self::Warn => "Warning".yellow(),
Self::Info => "Info".normal(),
Self::Debug => "Debug".dimmed(),
})
}
}
/// A logger that prints to stdout and stderr idk.
/// # TODO
/// Make this a trait and have variants that print to files and such
#[derive(Debug)]
pub struct Logger
{
level: Level,
title: String,
use_local_time: bool,
}
static INSTANCE: OnceCell<Logger> = OnceCell::new();
impl Logger
{
pub fn new(level: Level) -> Self
{
Self {
level,
title: String::new(),
use_local_time: DEFAULT_USE_LOCAL_TIME,
}
}
#[inline]
pub fn global() -> &'static Logger
{
INSTANCE.get().expect("[logger] uninitialised")
}
fn initialise(level: Level) -> &'static Logger
{
INSTANCE.set(Logger::new(level)).expect("[logger] already initialised");
Logger::global()
}
pub fn println<W,L,D,T>(&self, mut to: W, level: L, what: D, trace: T) -> io::Result<()>
where W: Write,
L: AsLevel,
D: Display,
T: Borrow<Trace>
{
//lol
enum Date {
Local(chrono::DateTime<chrono::offset::Local>),
Utc(chrono::DateTime<chrono::offset::Utc>),
}
impl std::fmt::Display for Date
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Local(l) => write!(f, "{}", l.format("%Y-%m-%d %H:%M:%S %Z")),
Self::Utc(l) => write!(f, "{}", l.format("%Y-%m-%d %H:%M:%S %Z")),
}
}
}
impl From<chrono::DateTime<chrono::offset::Local>> for Date
{
#[inline]
fn from(from: chrono::DateTime<chrono::offset::Local>) -> Self
{
Self::Local(from)
}
}
impl From<chrono::DateTime<chrono::offset::Utc>> for Date
{
#[inline]
fn from(from: chrono::DateTime<chrono::offset::Utc>) -> Self
{
Self::Utc(from)
}
}
if &self.level >= level.borrow() {
let now: Date = if self.use_local_time {
chrono::offset::Local::now().into()
} else {
chrono::offset::Utc::now().into()
};
write!(to, "{} ", now)?;
if self.title.len() > 0 {
write!(to, " <{}>\t", self.title)?;
} else {
write!(to, " <{}>\t", trace.borrow())?;
}
write!(to," [")?;
struct Prefix<'a,L: AsLevel>(&'a L);
impl<'a,L: AsLevel> std::fmt::Display for Prefix<'a, L>
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
self.0.prefix(f)
}
}
write!(to, "{}", Prefix(&level))?; //what a mess...
write!(to, "{}", level)?;
write!(to, "]: ")?;
writeln!(to, "{}", what)?;
}
Ok(())
}
}
#[cfg(any(debug_assertions,feature="debug_logger"))]
#[macro_export] macro_rules! debug {
($obj:expr) => {
{
let stdout = std::io::stdout();
let stdout = stdout.lock();
$crate::log::Logger::global().println(stdout, $crate::log::Level::Debug, $obj, get_trace!()).expect("i/o error");
}
};
($fmt:literal, $($args:expr),*) => {
debug!(format!($fmt, $($args,)*));
};
}
#[cfg(not(any(debug_assertions,feature="debug_logger")))]
#[macro_export] macro_rules! debug {
($obj:expr) => {{}};
($fmt:literal, $($args:expr),*) => {{}};
}
#[cfg(any(debug_assertions,feature="debug_logger"))]
#[macro_export] macro_rules! status {
($obj:expr) => {
{
struct Status;
use std::{
borrow::Borrow,
fmt,
};
impl Borrow<$crate::log::Level> for Status {
fn borrow(&self) -> &$crate::log::Level
{
&$crate::log::Level::Debug
}
}
impl fmt::Display for Status
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
use recolored::Colorize;
write!(f, "{}", "Status".blue())
}
}
impl $crate::log::AsLevel for Status{}
let stdout = std::io::stdout();
let stdout = stdout.lock();
$crate::log::Logger::global().println(stdout, Status, $obj, $crate::get_trace!()).expect("i/o error");
}
};
($fmt:literal, $($args:expr),*) => {
status!(format!($fmt, $($args,)*));
};
}
#[cfg(not(any(debug_assertions,feature="debug_logger")))]
#[macro_export] macro_rules! status {
($obj:expr) => {{}};
($fmt:literal, $($args:expr),*) => {{}};
}
#[macro_export] macro_rules! info {
($obj:expr) => {
{
let stdout = std::io::stdout();
let stdout = stdout.lock();
$crate::log::Logger::global().println(stdout, $crate::log::Level::Info, $obj, $crate::get_trace!()).expect("i/o error");
}
};
($fmt:literal, $($args:expr),*) => {
$crate::info!(format!($fmt, $($args,)*));
};
}
#[macro_export] macro_rules! important {
($obj:expr) => {
{
struct Important;
use std::{
borrow::Borrow,
fmt,
};
impl Borrow<$crate::log::Level> for Important {
fn borrow(&self) -> &$crate::log::Level
{
&$crate::log::Level::Info
}
}
impl fmt::Display for Important
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
use recolored::Colorize;
write!(f, "{}", "Important".bright_blue())
}
}
impl $crate::log::AsLevel for Important{}
let stdout = std::io::stdout();
let stdout = stdout.lock();
$crate::log::Logger::global().println(stdout, Important, $obj, $crate::get_trace!()).expect("i/o error");
}
};
($fmt:literal, $($args:expr),*) => {
$crate::important!(format!($fmt, $($args,)*));
};
}
#[macro_export] macro_rules! warn {
($obj:expr) => {
{
let stderr = std::io::stderr();
let stderr = stderr.lock();
$crate::log::Logger::global().println(stderr, $crate::log::Level::Warn, $obj, $crate::get_trace!()).expect("i/o error");
}
};
($fmt:literal, $($args:expr),*) => {
$crate::warn!(format!($fmt, $($args,)*));
};
}
#[macro_export] macro_rules! dangerous {
($obj:expr) => {
{
struct Dangerous;
use std::{
borrow::Borrow,
fmt,
};
impl Borrow<$crate::log::Level> for Dangerous {
fn borrow(&self) -> &$crate::log::Level
{
&$crate::log::Level::Warn
}
}
impl fmt::Display for Dangerous
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
use recolored::Colorize;
write!(f, "{}", "Dangerous".bright_yellow())
}
}
impl $crate::log::AsLevel for Dangerous{}
let stderr = std::io::stderr();
let stderr = stderr.lock();
$crate::log::Logger::global().println(stderr, Dangerous, $obj, $crate::get_trace!()).expect("i/o error");
}
};
($fmt:literal, $($args:expr),*) => {
$crate::dangerous!(format!($fmt, $($args,)*));
};
}
#[macro_export] macro_rules! error {
($obj:expr) => {
{
let stderr = std::io::stderr();
let stderr = stderr.lock();
$crate::log::Logger::global().println(stderr, $crate::log::Level::Error, $obj, $crate::get_trace!()).expect("i/o error");
}
};
($fmt:literal, $($args:expr),*) => {
$crate::error!(format!($fmt, $($args,)*));
};
}
#[macro_export] macro_rules! fatal {
($obj:expr) => {
{
let stdout = std::io::stdout();
let stdout = stdout.lock();
$crate::log::Logger::global().println(stdout, $crate::log::Level::Silent, $obj, $crate::get_trace!()).expect("i/o error");
std::process::exit(-1)
}
};
($fmt:literal, $($args:expr),*) => {
$crate::fatal!(format!($fmt, $($args,)*));
};
}
/// Initialise the global logger instance. If logging macros are called before this, they will panic.
#[inline]
pub fn init(level: Level)
{
Logger::initialise(level);
}
/// The global logger's level
#[inline]
pub fn level() -> &'static Level
{
&Logger::global().level
}
Loading…
Cancel
Save