#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
use core as std;
use log::{Log, Metadata, Record, SetLoggerError};
pub mod target;
pub mod timing;
pub mod targets;
use target::TargetResults;
pub struct Logger<Targ, Time>
where
Targ: target::Targets + Send + Sync + 'static,
Time: timing::Timing + Send + Sync + 'static
{
pub targets: Targ,
pub start: Time
}
impl<Targ, Time> Logger<Targ, Time>
where
Targ: target::Targets + Send + Sync + 'static,
Time: timing::Timing + Send + Sync + 'static
{
pub fn new(targets: Targ, start: Time) -> Self {
Logger { targets, start }
}
pub fn start(&self) -> &Time {
&self.start
}
pub fn start_mut(&mut self) -> &mut Time {
&mut self.start
}
#[cfg(feature = "std")]
pub fn init_boxed(self) -> Result<(), SetLoggerError> {
let max_level = self.targets.max_level();
log::set_max_level(max_level);
let logger = Box::new(self);
log::set_boxed_logger(logger)?;
Ok(())
}
pub fn init_static(&'static self) -> Result<(), SetLoggerError> {
let max_level = self.targets.max_level();
log::set_max_level(max_level);
log::set_logger(self)?;
Ok(())
}
pub unsafe fn init_static_racy(&'static self) -> Result<(), SetLoggerError> {
let max_level = self.targets.max_level();
log::set_max_level(max_level);
log::set_logger_racy(self)?;
Ok(())
}
#[cfg(feature = "std")]
fn on_error(&self, error: &dyn std::fmt::Display) {
eprintln!("{}", error);
}
#[cfg(not(feature = "std"))]
fn on_error(&self, error: &dyn core::fmt::Display) {
}
}
impl<Targ, Time> Log for Logger<Targ, Time>
where
Targ: target::Targets + Send + Sync + 'static,
Time: timing::Timing + Send + Sync + 'static
{
fn enabled(&self, metadata: &Metadata) -> bool {
self.targets.max_level() >= metadata.level()
}
fn log(&self, record: &Record) {
let now = Time::now();
let duration_since_start = now.duration_since(&self.start);
let results = self.targets.write(duration_since_start, record);
results.log_errors(|err| self.on_error(err));
}
fn flush(&self) {
let results = self.targets.flush();
results.log_errors(|err| self.on_error(err));
}
}