From 16175368ab311a7912004e29b90cacbd192dad51 Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 2 Aug 2024 07:44:21 +0800 Subject: [PATCH] docs: add docs and some inplace fixes (#21) Signed-off-by: tison --- Cargo.toml | 2 +- src/append/mod.rs | 9 ++++--- src/logger.rs | 68 ++++++++++++++++++++++++++++++++++++----------- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3d182d4..e1a754b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ license = "Apache-2.0" readme = "README.md" repository = "https://github.com/tisonkun/logforth" rust-version = "1.71.0" -version = "0.4.0" +version = "0.5.0" [package.metadata.docs.rs] all-features = true diff --git a/src/append/mod.rs b/src/append/mod.rs index 8fbf872..97b0778 100644 --- a/src/append/mod.rs +++ b/src/append/mod.rs @@ -15,10 +15,13 @@ use std::fmt; #[cfg(feature = "fastrace")] -pub use fastrace::*; +pub use fastrace::FastraceEvent; #[cfg(feature = "opentelemetry")] -pub use opentelemetry::*; -pub use stdio::*; +pub use opentelemetry::OpentelemetryLog; +#[cfg(feature = "rolling_file")] +pub use rolling_file::RollingFile; +pub use stdio::Stderr; +pub use stdio::Stdout; use crate::layout::IdenticalLayout; use crate::layout::Layout; diff --git a/src/logger.rs b/src/logger.rs index 6f6310a..c7b7788 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -22,6 +22,15 @@ use crate::append::Append; use crate::filter::Filter; use crate::filter::FilterResult; use crate::layout::Layout; + +/// A grouped set of appenders, filters, and optional layout. +/// +/// The [Logger] facade dispatches log records to one or more [Dispatch] instances. +/// Each [Dispatch] instance contains a set of filters, appenders, and an optional layout. +/// +/// `filters` are used to determine whether a log record should be passed to the appenders. +/// `appends` are used to write log records to a destination. Each appender has its own +/// default layout. If the [Dispatch] has a layout, it will be used instead of the default layout. #[derive(Debug)] pub struct Dispatch { filters: Vec, @@ -36,6 +45,9 @@ impl Default for Dispatch { } impl Dispatch { + /// Create a new incomplete [Dispatch] instance. + /// + /// At least one append must be added to the [Dispatch] before it can be used. pub fn new() -> Dispatch { Self { filters: vec![], @@ -44,11 +56,14 @@ impl Dispatch { } } + /// Add a [Filter] to the [Dispatch]. pub fn filter(mut self, filter: impl Into) -> Dispatch { self.filters.push(filter.into()); self } + /// Add the preferred [Layout] to the [Dispatch]. At most one layout can be added to a + /// [Dispatch]. pub fn layout(self, layout: impl Into) -> Dispatch { Dispatch { filters: self.filters, @@ -59,10 +74,13 @@ impl Dispatch { } impl Dispatch { - pub fn append(self, append: impl Append) -> Dispatch { + /// Add an [Append] to the [Dispatch]. + pub fn append(mut self, append: impl Append) -> Dispatch { + self.appends.push(Box::new(append)); + Dispatch { filters: self.filters, - appends: vec![Box::new(append)], + appends: self.appends, layout: self.layout, } } @@ -83,7 +101,6 @@ impl Dispatch { fn log(&self, record: &Record) -> anyhow::Result<()> { let layout = self.layout.as_ref(); - for append in &self.appends { match layout { Some(layout) => layout.format(record, &|record| append.append(record))?, @@ -92,7 +109,6 @@ impl Dispatch { .format(record, &|record| append.append(record))?, } } - Ok(()) } @@ -103,27 +119,36 @@ impl Dispatch { } } +/// A logger facade that dispatches log records to one or more [Dispatch] instances. +/// +/// This struct implements [log::Log] to bridge Logforth's logging implementations +/// with the [log] crate. #[derive(Debug)] -pub struct Logger { +pub struct Logger { dispatches: Vec, } -impl Default for Logger { +impl Default for Logger { fn default() -> Self { Self::new() } } -impl Logger { - pub fn new() -> Self { +impl Logger { + /// Create a new [Logger] instance. + /// + /// The [Logger] instance is incomplete and must have at least one [Dispatch] added to it. + pub fn new() -> Logger { Self { dispatches: vec![] } } +} - pub fn dispatch(mut self, dispatch: Dispatch) -> Self { - self.dispatches.push(dispatch); - self - } - +impl Logger { + /// Set up the global logger with the [Logger] instance. + /// + /// # Errors + /// + /// An error is returned if the global logger has already been set. pub fn apply(self) -> Result<(), log::SetLoggerError> { log::set_boxed_logger(Box::new(self))?; log::set_max_level(LevelFilter::Trace); @@ -131,9 +156,21 @@ impl Logger { } } +impl Logger { + /// Add a [Dispatch] to the [Logger]. + pub fn dispatch(mut self, dispatch: Dispatch) -> Logger { + self.dispatches.push(dispatch); + Logger { + dispatches: self.dispatches, + } + } +} + impl log::Log for Logger { - fn enabled(&self, _: &Metadata) -> bool { - true + fn enabled(&self, metadata: &Metadata) -> bool { + self.dispatches + .iter() + .any(|dispatch| dispatch.enabled(metadata)) } fn log(&self, record: &Record) { @@ -153,6 +190,7 @@ impl log::Log for Logger { } } +// TODO(tisonkun): logback and log4j2 support custom error handling (status listener). fn handle_error(record: &Record, error: anyhow::Error) { let Err(fallback_error) = write!( std::io::stderr(),