From 4c7f006d092b564a46bd326032636950d2e7c7bb Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 2 Aug 2024 21:01:09 +0800 Subject: [PATCH] docs: add more docs (#29) Signed-off-by: tison --- Cargo.toml | 2 +- src/append/fastrace.rs | 1 + src/append/mod.rs | 4 ++- src/append/opentelemetry.rs | 5 ++++ src/append/rolling_file/append.rs | 2 ++ src/append/stdio.rs | 2 ++ src/filter/custom.rs | 18 ++++++++++++++ src/filter/mod.rs | 3 +++ src/layout/custom.rs | 17 +++++++++++++ src/layout/identical.rs | 4 +++ src/layout/json.rs | 11 +++++++++ src/layout/kv.rs | 1 + src/layout/mod.rs | 3 +++ src/layout/text.rs | 18 ++++++++++++++ src/lib.rs | 41 +++++++++++++++++++++++++++++++ src/logger.rs | 30 +++++++++++----------- 16 files changed, 145 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index feb2cde..a061004 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.7.1" +version = "0.7.2" [package.metadata.docs.rs] all-features = true diff --git a/src/append/fastrace.rs b/src/append/fastrace.rs index 2cefb83..dddb82c 100644 --- a/src/append/fastrace.rs +++ b/src/append/fastrace.rs @@ -19,6 +19,7 @@ use log::Record; use crate::append::Append; use crate::layout::KvDisplay; +/// An appender that adds log records to fastrace as an event associated to the current span. #[derive(Default, Debug, Clone)] pub struct FastraceEvent; diff --git a/src/append/mod.rs b/src/append/mod.rs index 29889bb..dac6750 100644 --- a/src/append/mod.rs +++ b/src/append/mod.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Dispatch log records to the appropriate target. + use std::fmt; #[cfg(feature = "fastrace")] @@ -41,7 +43,7 @@ pub trait Append: fmt::Debug + Send + Sync + 'static { /// Flushes any buffered records. fn flush(&self) {} - /// Default layout to use when [Dispatch][crate::logger::Dispatch] does not configure a + /// Default layout to use when [`Dispatch`][crate::logger::Dispatch] does not configure a /// preferred layout. fn default_layout(&self) -> Layout { Layout::Identical(IdenticalLayout) diff --git a/src/append/opentelemetry.rs b/src/append/opentelemetry.rs index 31aca46..03c2c60 100644 --- a/src/append/opentelemetry.rs +++ b/src/append/opentelemetry.rs @@ -28,6 +28,10 @@ use opentelemetry_sdk::logs::LoggerProvider; use crate::append::Append; +/// The communication protocol to opentelemetry that used when exporting data. +/// +/// This is a logical re-exported [`opentelemetry_otlp::Protocol`] to avoid version lock-in to +/// `opentelemetry_otlp`. #[non_exhaustive] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum OpentelemetryWireProtocol { @@ -36,6 +40,7 @@ pub enum OpentelemetryWireProtocol { HttpJson, } +/// An appender that sends log records to opentelemetry. #[derive(Debug)] pub struct OpentelemetryLog { name: String, diff --git a/src/append/rolling_file/append.rs b/src/append/rolling_file/append.rs index 055a6aa..17ba095 100644 --- a/src/append/rolling_file/append.rs +++ b/src/append/rolling_file/append.rs @@ -17,6 +17,8 @@ use log::Record; use crate::append::rolling_file::non_blocking::NonBlocking; use crate::append::Append; +/// An appender that writes log records to a file that rolls over when it reaches a certain date +/// time. #[derive(Debug)] pub struct RollingFile { writer: NonBlocking, diff --git a/src/append/stdio.rs b/src/append/stdio.rs index 59d4510..b010fdd 100644 --- a/src/append/stdio.rs +++ b/src/append/stdio.rs @@ -16,6 +16,7 @@ use std::io::Write; use crate::append::Append; +/// An appender that prints log records to stdout. #[derive(Default, Debug)] pub struct Stdout; @@ -31,6 +32,7 @@ impl Append for Stdout { } } +/// An appender that prints log records to stderr. #[derive(Default, Debug)] pub struct Stderr; diff --git a/src/filter/custom.rs b/src/filter/custom.rs index a5cdb70..ebbba0c 100644 --- a/src/filter/custom.rs +++ b/src/filter/custom.rs @@ -19,6 +19,24 @@ use log::Metadata; use crate::filter::Filter; use crate::filter::FilterResult; +/// A filter that you can pass the custom filter function. +/// +/// The custom filter function accepts [`&log::Metadata`][Metadata] and returns the +/// [`FilterResult`]. For example: +/// +/// ```rust +/// use log::Metadata; +/// use logforth::filter::CustomFilter; +/// use logforth::filter::FilterResult; +/// +/// let filter = CustomFilter::new(|metadata: &Metadata| { +/// if metadata.target() == "my_crate" { +/// FilterResult::Accept +/// } else { +/// FilterResult::Neutral +/// } +/// }); +/// ``` pub struct CustomFilter { f: Box FilterResult + Send + Sync + 'static>, } diff --git a/src/filter/mod.rs b/src/filter/mod.rs index 3617713..a7fa944 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -12,12 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Determinate whether a log record should be processed. + pub use self::custom::CustomFilter; pub use self::level::LevelFilter; mod custom; mod level; +/// The result of a filter may return. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FilterResult { /// The record will be processed without further filtering. diff --git a/src/layout/custom.rs b/src/layout/custom.rs index a5a149c..b0a2de9 100644 --- a/src/layout/custom.rs +++ b/src/layout/custom.rs @@ -27,6 +27,23 @@ type FormatFunction = dyn Fn(&Record, &dyn Fn(Arguments) -> anyhow::Result<()>) + Sync + 'static; +/// A layout that you can pass the custom layout function. +/// +/// The custom layout function accepts [`&log::Record`][Record], formats it into [Arguments], and +/// then passes to the closure. For example: +/// +/// ```rust +/// use std::fmt::Arguments; +/// +/// use log::Record; +/// use logforth::layout::CustomLayout; +/// +/// let layout = CustomLayout::new( +/// |record: &Record, f: &dyn Fn(Arguments) -> anyhow::Result<()>| { +/// f(format_args!("{} - {}", record.level(), record.args())) +/// }, +/// ); +/// ``` pub struct CustomLayout { f: Box, } diff --git a/src/layout/identical.rs b/src/layout/identical.rs index a34999c..68b676a 100644 --- a/src/layout/identical.rs +++ b/src/layout/identical.rs @@ -16,6 +16,10 @@ use std::fmt::Arguments; use crate::layout::Layout; +/// A layout that returns log record as is. +/// +/// This is mainly used as the default implementation for +/// [`Append::default_layout`][crate::append::Append::default_layout]. #[derive(Debug, Default, Clone, Copy)] pub struct IdenticalLayout; diff --git a/src/layout/json.rs b/src/layout/json.rs index 3298965..70af646 100644 --- a/src/layout/json.rs +++ b/src/layout/json.rs @@ -23,6 +23,17 @@ use serde_json::Value; use crate::layout::Layout; +/// A layout that formats log record as JSON lines. +/// +/// Output format: +/// +/// ```json +/// {"timestamp":"2024-08-01T13:57:05.099261Z","level":"ERROR","module_path":"rolling_file","file":"rolling_file.rs","line":48,"message":"Hello error!","kvs":{}} +/// {"timestamp":"2024-08-01T13:57:05.099313Z","level":"WARN","module_path":"rolling_file","file":"rolling_file.rs","line":49,"message":"Hello warn!","kvs":{}} +/// {"timestamp":"2024-08-01T13:57:05.099338Z","level":"INFO","module_path":"rolling_file","file":"rolling_file.rs","line":50,"message":"Hello info!","kvs":{}} +/// {"timestamp":"2024-08-01T13:57:05.099362Z","level":"DEBUG","module_path":"rolling_file","file":"rolling_file.rs","line":51,"message":"Hello debug!","kvs":{}} +/// {"timestamp":"2024-08-01T13:57:05.099386Z","level":"TRACE","module_path":"rolling_file","file":"rolling_file.rs","line":52,"message":"Hello trace!","kvs":{}} +/// ``` #[derive(Default, Debug, Clone)] pub struct JsonLayout; diff --git a/src/layout/kv.rs b/src/layout/kv.rs index 9acf52a..57eee61 100644 --- a/src/layout/kv.rs +++ b/src/layout/kv.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +/// A helper struct to format log's key-value pairs. pub struct KvDisplay<'kvs> { kv: &'kvs dyn log::kv::Source, } diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 56ce6cb..261335e 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Describe how to format a log record. + pub use custom::CustomLayout; pub use identical::IdenticalLayout; #[cfg(feature = "json")] @@ -27,6 +29,7 @@ mod json; mod kv; mod text; +/// A layout describes how to format a log record. #[derive(Debug)] pub enum Layout { Identical(IdenticalLayout), diff --git a/src/layout/text.rs b/src/layout/text.rs index 6de907d..589812a 100644 --- a/src/layout/text.rs +++ b/src/layout/text.rs @@ -23,11 +23,29 @@ use log::Level; use crate::layout::KvDisplay; use crate::layout::Layout; +/// A layout that formats log record as text. +/// +/// Output format: +/// +/// ```text +/// 2024-08-02T12:49:03.102343Z ERROR simple_stdio: examples/simple_stdio.rs:32 Hello error! +/// 2024-08-02T12:49:03.102442Z WARN simple_stdio: examples/simple_stdio.rs:33 Hello warn! +/// 2024-08-02T12:49:03.102447Z INFO simple_stdio: examples/simple_stdio.rs:34 Hello info! +/// 2024-08-02T12:49:03.102450Z DEBUG simple_stdio: examples/simple_stdio.rs:35 Hello debug! +/// 2024-08-02T12:49:03.102453Z TRACE simple_stdio: examples/simple_stdio.rs:36 Hello trace! +/// ``` +/// +/// By default, log levels are colored. You can turn on the `no-color` feature flag to disable this +/// feature. +/// +/// You can also customize the color of each log level by setting the `colors` field with a +/// [`LevelColor`] instance. #[derive(Default, Debug, Clone)] pub struct TextLayout { pub colors: LevelColor, } +/// Customize the color of each log level. #[derive(Debug, Clone)] pub struct LevelColor { pub error: Color, diff --git a/src/lib.rs b/src/lib.rs index cbc538a..8af14dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,47 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! # A versatile and extensible logging implementation +//! +//! ## Usage +//! +//! Add the dependencies to your `Cargo.toml` with: +//! +//! ```shell +//! cargo add log +//! cargo add logforth +//! ``` +//! +//! Here, [`log`] is the logging facade and `logforth` is the logging implementation. +//! +//! Then, you can use the logger with: +//! +//! ```rust +//! use log::LevelFilter; +//! use logforth::append; +//! use logforth::layout::TextLayout; +//! use logforth::Dispatch; +//! use logforth::Logger; +//! +//! Logger::new() +//! .dispatch( +//! Dispatch::new() +//! .filter(LevelFilter::Trace) +//! .layout(TextLayout::default()) +//! .append(append::Stdout), +//! ) +//! .apply() +//! .unwrap(); +//! +//! log::error!("Hello error!"); +//! log::warn!("Hello warn!"); +//! log::info!("Hello info!"); +//! log::debug!("Hello debug!"); +//! log::trace!("Hello trace!"); +//! ``` +//! +//! Read more demos under the [examples](https://github.com/tisonkun/logforth/tree/main/examples) directory. + pub mod append; pub mod filter; pub mod layout; diff --git a/src/logger.rs b/src/logger.rs index 34d1129..3a219d4 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -25,12 +25,12 @@ 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. +/// 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. +/// default layout. If the [`Dispatch`] has a layout, it will be used instead of the default layout. #[derive(Debug)] pub struct Dispatch { filters: Vec, @@ -45,9 +45,9 @@ impl Default for Dispatch { } impl Dispatch { - /// Create a new incomplete [Dispatch] instance. + /// Create a new incomplete [`Dispatch`] instance. /// - /// At least one append must be added to the [Dispatch] before it can be used. + /// At least one append must be added to the [`Dispatch`] before it can be used. pub fn new() -> Dispatch { Self { filters: vec![], @@ -56,14 +56,14 @@ impl Dispatch { } } - /// Add a [Filter] to the [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]. + /// 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, @@ -74,7 +74,7 @@ impl Dispatch { } impl Dispatch { - /// Add an [Append] to the [Dispatch]. + /// Add an [`Append`] to the [`Dispatch`]. pub fn append(mut self, append: impl Append) -> Dispatch { self.appends.push(Box::new(append)); @@ -119,10 +119,10 @@ impl Dispatch { } } -/// A logger facade that dispatches log records to one or more [Dispatch] instances. +/// 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. +/// This struct implements [`log::Log`] to bridge Logforth's logging implementations +/// with the [`log`] crate. #[derive(Debug)] pub struct Logger { dispatches: Vec, @@ -135,20 +135,20 @@ impl Default for Logger { } impl Logger { - /// Create a new [Logger] instance. + /// Create a new [`Logger`] instance. pub fn new() -> Logger { Self { dispatches: vec![] } } } impl Logger { - /// Add a [Dispatch] to the [Logger]. + /// Add a [`Dispatch`] to the [`Logger`]. pub fn dispatch(mut self, dispatch: Dispatch) -> Logger { self.dispatches.push(dispatch); self } - /// Set up the global logger with the [Logger] instance. + /// Set up the global logger with the [`Logger`] instance. /// /// # Errors ///