1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
//! Provides sinks to flexibly output log messages to specified targets.
//!
//! # Sink
//!
//! Sinks are the objects that actually write logs to their targets. Each sink
//! should be responsible for only single target (e.g file, console, database),
//! and each sink has its own private instance of [`Formatter`] object.
//!
//! A sink has its own level filter that is not shared with the logger, and a
//! [`Logger`] can combine multiple [`Sink`]s.
//!
//! # Combined sink
//!
//! A combined sink is also a sink, but instead of having its own target and
//! formatter, it combines other sinks (as sub-sinks).
//!
//! Operations on a combined sink will be forwarded to its sub-sinks according
//! to the implementation.
//!
//! # Asynchronous combined sink
//!
//! Asynchronous combined sink is a type of combined sink. Expensive operations
//! (such as `log` and `flush`) on asynchronous sinks will be performed
//! asynchronously on other threads.
//!
//! Since there is no waiting, errors that occur while performing asynchronous
//! operations will not be returned to the upper level, and instead the error
//! handler of the sink will be called.
//!
//! Users should only use asynchronous combined sinks to wrap actual sinks that
//! require a long time for operations (e.g. involving UDP sends), otherwise
//! they will not get a performance boost or even worse.
//!
//! Since the thread pool has a capacity limit, the queue may be full in some
//! cases. When users encounter this situation, they have the following options:
//!
//! - Adjust to a larger capacity via [`ThreadPoolBuilder::capacity`].
//!
//! - Adjust the overflow policy via [`AsyncPoolSinkBuilder::overflow_policy`].
//!
//! - Set up an error handler on asynchronous combined sinks via
//! [`AsyncPoolSinkBuilder::error_handler`]. The handler will be called when
//! a record is dropped or an operation has failed.
//!
//! [`Logger`]: crate::logger::Logger
//! [`ThreadPoolBuilder::capacity`]: crate::ThreadPoolBuilder::capacity
#[cfg(feature = "multi-thread")]
pub(crate) mod async_sink;
mod file_sink;
mod helper;
#[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;
#[cfg(feature = "multi-thread")]
pub use async_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, sync::*, ErrorHandler, Level, LevelFilter, Record, Result};
/// A trait for sinks.
pub trait Sink: Sync + Send {
/// Determines if a log message with the specified level would be logged.
#[must_use]
fn should_log(&self, level: Level) -> bool {
self.level_filter().compare(level)
}
/// Logs a record.
///
/// Implementors should always call [`Sink::should_log`] internally to
/// filter records.
fn log(&self, record: &Record) -> Result<()>;
/// Flushes any buffered records.
fn flush(&self) -> Result<()>;
/// Gets the log level filter.
#[must_use]
fn level_filter(&self) -> LevelFilter;
/// Sets the log level filter.
fn set_level_filter(&self, level_filter: LevelFilter);
/// Sets the formatter.
fn set_formatter(&self, formatter: Box<dyn Formatter>);
/// Sets a error handler.
///
/// Any errors that occur in `Sink` will be returned as directly as possible
/// (e.g. returned to [`Logger`]), but some errors that are not likely to be
/// returned directly will call this error handler. Most of these errors are
/// uncommon.
///
/// If no handler is set, errors will be print to `stderr` and then ignored.
///
/// [`Logger`]: crate::logger::Logger
fn set_error_handler(&self, handler: Option<ErrorHandler>);
}
/// A container for [`Sink`]s.
pub type Sinks = Vec<Arc<dyn Sink>>;