#[cfg(any(
all(target_os = "android", feature = "native", feature = "android-ndk"),
all(doc, not(doctest))
))]
mod android_sink;
#[cfg(feature = "multi-thread")]
pub(crate) mod async_sink;
mod dedup_sink;
mod file_sink;
#[cfg(any(
all(target_os = "linux", feature = "native", feature = "libsystemd"),
all(doc, not(doctest))
))]
mod journald_sink;
mod rotating_file_sink;
mod std_stream_sink;
#[cfg(any(all(windows, feature = "native"), all(doc, not(doctest))))]
mod win_debug_sink;
mod write_sink;
use std::ops::Deref;
#[cfg(any(
all(target_os = "android", feature = "native", feature = "android-ndk"),
all(doc, not(doctest))
))]
pub use android_sink::*;
#[cfg(feature = "multi-thread")]
pub use async_sink::*;
pub use dedup_sink::*;
pub use file_sink::*;
#[cfg(any(
all(target_os = "linux", feature = "native", feature = "libsystemd"),
all(doc, not(doctest))
))]
pub use journald_sink::*;
pub use rotating_file_sink::*;
pub use std_stream_sink::*;
#[cfg(any(all(windows, feature = "native"), all(doc, not(doctest))))]
pub use win_debug_sink::*;
pub use write_sink::*;
use crate::{
formatter::{Formatter, FullFormatter},
sync::*,
AtomicLevelFilter, Error, ErrorHandler, Level, LevelFilter, Record, Result,
};
pub struct SinkProp {
level_filter: AtomicLevelFilter,
formatter: RwLockMappable<Box<dyn Formatter>>,
error_handler: RwLock<ErrorHandler>,
}
impl Default for SinkProp {
fn default() -> Self {
Self {
level_filter: AtomicLevelFilter::new(LevelFilter::All),
formatter: RwLockMappable::new(Box::new(FullFormatter::new())),
error_handler: RwLock::new(ErrorHandler::default()),
}
}
}
impl SinkProp {
#[must_use]
pub fn level_filter(&self) -> LevelFilter {
self.level_filter.get()
}
pub fn set_level_filter(&self, level_filter: LevelFilter) {
self.level_filter.set(level_filter)
}
pub fn formatter<'a>(&'a self) -> impl Deref<Target = dyn Formatter> + 'a {
RwLockMappableReadGuard::map(self.formatter.read(), |f| &**f)
}
pub fn set_formatter<F>(&self, formatter: F)
where
F: Formatter + 'static,
{
self.set_formatter_boxed(Box::new(formatter));
}
pub fn set_formatter_boxed(&self, formatter: Box<dyn Formatter>) {
*self.formatter.write() = formatter;
}
pub fn call_error_handler(&self, err: Error) {
self.error_handler.read_expect().call(err)
}
pub(crate) fn call_error_handler_internal(&self, from: impl AsRef<str>, err: Error) {
self.error_handler.read_expect().call_internal(from, err)
}
pub fn set_error_handler<F: Into<ErrorHandler>>(&self, handler: F) {
*self.error_handler.write_expect() = handler.into();
}
}
pub trait GetSinkProp {
fn prop(&self) -> &SinkProp;
}
pub trait SinkPropAccess {
#[must_use]
fn level_filter(&self) -> LevelFilter;
fn set_level_filter(&self, level_filter: LevelFilter);
fn set_formatter(&self, formatter: Box<dyn Formatter>);
fn set_error_handler(&self, handler: ErrorHandler);
}
impl<S: GetSinkProp> SinkPropAccess for S {
fn level_filter(&self) -> LevelFilter {
self.prop().level_filter()
}
fn set_level_filter(&self, level_filter: LevelFilter) {
self.prop().set_level_filter(level_filter);
}
fn set_formatter(&self, formatter: Box<dyn Formatter>) {
self.prop().set_formatter_boxed(formatter);
}
fn set_error_handler(&self, handler: ErrorHandler) {
self.prop().set_error_handler(handler);
}
}
pub trait Sink: SinkPropAccess + Sync + Send {
#[must_use]
fn should_log(&self, level: Level) -> bool {
self.level_filter().test(level)
}
fn log(&self, record: &Record) -> Result<()>;
fn flush(&self) -> Result<()>;
fn flush_on_exit(&self) -> Result<()> {
self.flush()
}
}
pub type Sinks = Vec<Arc<dyn Sink>>;