diff --git a/spdlog/src/formatter/full_formatter.rs b/spdlog/src/formatter/full_formatter.rs index b919408..8f0808e 100644 --- a/spdlog/src/formatter/full_formatter.rs +++ b/spdlog/src/formatter/full_formatter.rs @@ -10,28 +10,28 @@ use crate::{ }; #[rustfmt::skip] -/// A full info log records formatter. +/// Full information logs formatter. /// -/// It is the default formatter for sinks. +/// It is the default formatter for most sinks. /// /// Log messages formatted by it look like: /// /// - Default: /// ///
-///    [2022-11-02 09:23:12.263] [info] hello, world!
+///    [2022-11-02 09:23:12.263] [info] hello, world!
 ///    
/// /// - If the logger has a name: /// ///
-///    [2022-11-02 09:23:12.263] [logger-name] [info] hello, world!
+///    [2022-11-02 09:23:12.263] [logger-name] [info] hello, world!
 ///    
/// /// - If crate feature `source-location` is enabled: /// ///
-///    [2022-11-02 09:23:12.263] [info] [mod::path, src/main.rs:4] hello, world!
+///    [2022-11-02 09:23:12.263] [logger-name] [info] [mod::path, src/main.rs:4] hello, world!
 ///    
#[derive(Clone)] pub struct FullFormatter { diff --git a/spdlog/src/formatter/mod.rs b/spdlog/src/formatter/mod.rs index 878812d..d87a26e 100644 --- a/spdlog/src/formatter/mod.rs +++ b/spdlog/src/formatter/mod.rs @@ -1,8 +1,52 @@ //! Provides formatters for sink formatting log records. //! -//! Usually use [`Sink::set_formatter`] to set the formatter of a sink. +//! # Formatter +//! +//! Each normal Sink owns a Formatter, which is used to format each log. +//! +//! The default formatter for most sinks is [`FullFormatter`], you can call +//! [`Sink::set_formatter`] to replace it with another formatter. +//! +//! The easiest way to make a custom formatter is to build a pattern, see +//! [Compile-time and runtime pattern +//! formatter](#compile-time-and-runtime-pattern-formatter) below. If pattern +//! isn't flexible enough for you, you need to implement [`Formatter`] trait for +//! your own formatter struct. See the implementation of [`FullFormatter`] and +//! [./examples] directory for examples. +//! +//! # Compile-time and runtime pattern formatter +//! +//! spdlog-rs supports formatting your log records according to a pattern +//! string. There are 2 ways to construct a pattern: +//! +//! - Macro [`pattern!`]: Builds a pattern at compile-time. +//! - Macro [`runtime_pattern!`]: Builds a pattern at runtime. +//! +//! ``` +//! use spdlog::formatter::{pattern, PatternFormatter}; +//! # use spdlog::sink::{Sink, WriteSink}; +//! +//! # fn main() -> Result<(), Box> { +//! // This pattern is built at compile-time, the template accepts only a literal string. +//! let pattern = pattern!("[{date} {time}.{millisecond}] [{level}] {payload}{eol}"); +//! +//! #[cfg(feature = "runtime-pattern")] +//! { +//! use spdlog::formatter::runtime_pattern; +//! +//! // This pattern is built at runtime, the template accepts a runtime string. +//! let input = "[{date} {time}.{millisecond}] [{level}] {payload}{eol}"; +//! let pattern = runtime_pattern!(input)?; +//! } +//! +//! // Use the compile-time or runtime pattern. +//! # let your_sink = WriteSink::builder().target(vec![]).build()?; +//! your_sink.set_formatter(Box::new(PatternFormatter::new(pattern))); +//! # Ok(()) } +//! ``` //! //! [`Sink::set_formatter`]: crate::sink::Sink::set_formatter +//! [./examples]: https://github.com/SpriteOvO/spdlog-rs/tree/main/spdlog/examples mod full_formatter; #[cfg(any( @@ -26,7 +70,7 @@ pub use pattern_formatter::*; use crate::{Record, Result, StringBuf}; -/// A trait for log records formatters. +/// Represents a formatter that can be used for formatting logs. /// /// # Examples /// @@ -75,13 +119,7 @@ impl FmtExtraInfo { } } -/// The builder of [`FmtExtraInfo`]. -/// -/// # Examples -/// -/// See the implementation of [`FullFormatter`] and [./examples] directory. -/// -/// [./examples]: https://github.com/SpriteOvO/spdlog-rs/tree/main/spdlog/examples +#[allow(missing_docs)] #[derive(Clone, Eq, PartialEq, Hash, Debug, Default)] pub struct FmtExtraInfoBuilder { info: FmtExtraInfo, diff --git a/spdlog/src/formatter/pattern_formatter/mod.rs b/spdlog/src/formatter/pattern_formatter/mod.rs index 922b8a9..5b2b34b 100644 --- a/spdlog/src/formatter/pattern_formatter/mod.rs +++ b/spdlog/src/formatter/pattern_formatter/mod.rs @@ -29,7 +29,7 @@ use crate::{ }; #[rustfmt::skip] // rustfmt currently breaks some empty lines if `#[doc = include_str!("xxx")]` exists -/// Build a pattern from a template literal string at compile-time. +/// Builds a pattern from a template literal string at compile-time. /// /// It accepts inputs in the form: /// @@ -304,7 +304,7 @@ use crate::{ /// ); /// ``` /// -/// # Appendix: A Full List of Built-in Patterns +/// # Appendix: Full List of Built-in Patterns /// /// | Placeholders | Description | Example | /// | --------------------- | ---------------------------- | -------------------------------------------- | @@ -354,7 +354,7 @@ use crate::{ /// [`FullFormatter`]: crate::formatter::FullFormatter pub use ::spdlog_macros::pattern; -/// A formatter that formats log records according to a specified pattern. +/// Formats logs according to a specified pattern. #[derive(Clone)] pub struct PatternFormatter

{ pattern: P, @@ -392,20 +392,22 @@ where } } -/// Provide context for patterns. +/// Provides context for patterns. +/// +/// There is nothing to set up here at the moment, reserved for future use. #[derive(Clone, Debug)] pub struct PatternContext { fmt_info_builder: FmtExtraInfoBuilder, } impl PatternContext { - /// Create a new `PatternContext` object. + /// Creates a new `PatternContext` object. #[must_use] fn new(fmt_info_builder: FmtExtraInfoBuilder) -> Self { Self { fmt_info_builder } } - /// Set the style range of the log message written by the patterns. + /// Sets the style range of the log message written by the patterns. /// /// This function is reserved for use by the style range pattern. Other /// built-in patterns should not use this function. User-defined @@ -416,26 +418,24 @@ impl PatternContext { } } -/// A pattern. +/// Represents a pattern for replacing a placeholder in templates. /// -/// A pattern is like a formatter, except that multiple patterns can be combined -/// in various ways to create a new pattern. The [`PatternFormatter`] struct -/// provides a [`Formatter`] that formats log records according to a given -/// pattern. +/// A pattern will be used to replace placeholders that appear in a template +/// string. Multiple patterns can form a new pattern. The [`PatternFormatter`] +/// formats logs according to a given pattern. /// /// # Built-in Patterns /// -/// `spdlog` provides a rich set of built-in patterns. See the [`pattern`] +/// `spdlog-rs` provides a rich set of built-in patterns. See the [`pattern`] /// macro. /// /// # Custom Patterns /// /// There are 3 approaches to create your own pattern: -/// - Define a new type and implements this trait; -/// - Use the [`pattern`] macro to create a pattern from a literal template +/// - Define a new type and implement this trait; +/// - Use [`pattern`] macro to create a pattern from a literal template string. +/// - Use [`runtime_pattern`] macro to create a pattern from a runtime template /// string. -/// - Use the [`runtime_pattern`] macro to create a pattern from a runtime -/// template string. pub trait Pattern: Send + Sync + DynClone { /// Format this pattern against the given log record and write the formatted /// message into the output buffer. diff --git a/spdlog/src/formatter/pattern_formatter/runtime.rs b/spdlog/src/formatter/pattern_formatter/runtime.rs index ef768e7..8d643a2 100644 --- a/spdlog/src/formatter/pattern_formatter/runtime.rs +++ b/spdlog/src/formatter/pattern_formatter/runtime.rs @@ -17,7 +17,7 @@ type PatternCreator = Box Box>; type PatternRegistry = GenericPatternRegistry; type PatternKind = GenericPatternKind; -/// Build a pattern from a template string at runtime. +/// Builds a pattern from a template string at runtime. /// /// It accepts inputs in the form: /// @@ -58,7 +58,7 @@ type PatternKind = GenericPatternKind; pub use spdlog_macros::runtime_pattern; #[rustfmt::skip] // rustfmt currently breaks some empty lines if `#[doc = include_str!("xxx")]` exists -/// A runtime pattern built via [`runtime_pattern!`] macro. +/// Runtime pattern built via [`runtime_pattern!`] macro. /// /// ## Basic Usage /// diff --git a/spdlog/src/lib.rs b/spdlog/src/lib.rs index b290ebb..b419c71 100644 --- a/spdlog/src/lib.rs +++ b/spdlog/src/lib.rs @@ -1,9 +1,26 @@ -//! A fast and combinable Rust logging crate. +//! Fast, highly configurable Rust logging crate. //! -//! It is inspired by the C++ logging library [spdlog], so if you are familiar -//! with C++ `spdlog`, you should be able to get started with this crate quite -//! easily. Of course, there are some differences, you can see [Significant -//! differences from C++ spdlog](#significant-differences-from-c-spdlog) below. +//! It is inspired by the C++ logging library [spdlog], and we share most of the +//! same concepts. So if you are already familiar with C++ `spdlog`, you should +//! be able to get started with this crate quite easily. Of course, there are +//! some differences, you can see [Significant differences from C++ +//! spdlog](#significant-differences-from-c-spdlog) below. +//! +//! # Table of contents +//! +//! - [Getting started](#getting-started) +//! - [Compile-time filters](#compile-time-filters) +//! - [Crate feature flags](#crate-feature-flags) +//! - [Supported Rust versions](#supported-rust-versions) +//! - Overview of features +//! - [Configured via environment variable](init_env_level) +//! - [Compile-time and runtime pattern formatter] +//! - [Asynchronous support] +//! - [Compatible with log crate](LogCrateProxy) +//! +//! [Configured via environment variable]: #configured-via-environment-variable +//! [Compile-time and runtime pattern formatter]: formatter/index.html#compile-time-and-runtime-pattern-formatter +//! [Asynchronous support]: sink/index.html#asynchronous-combined-sink //! //! # Getting started //! @@ -13,118 +30,127 @@ //! spdlog-rs = "0.3" //! ``` //! -//! `spdlog-rs` is out-of-the-box, it has a default logger, so users can output -//! logs to terminal by default without any configuration. For more details -//! about the default logger, please read the documentation of -//! [`default_logger`]. -//! -//! The basic use of this crate is through these logging macros: [`trace!`], -//! [`debug!`], [`info!`], [`warn!`], [`error!`], [`critical!`] and [`log!`], -//! where [`critical!`] represents the most severe log messages and [`trace!`] -//! the most verbose. Each of these macros accept format strings similarly to -//! [`println!`]. All log macros and common types are already under [`prelude`] -//! module. -//! -//! [`Logger`] and [`sink`] are the most important components of `spdlog-rs`. -//! Make sure to read their documentation. In short, a logger contains a -//! combination of sinks, and sinks implement writing log messages to actual -//! targets. -//! -//! ## Examples +//! `spdlog-rs` is highly configurable, but also works out-of-the-box for +//! lightweight projects. By default, logs will be output to `stdout` and +//! `stderr`. //! //! ``` //! use spdlog::prelude::*; //! -//! info!("hello world!"); -//! warn!("3 + 2 = {}", 5); +//! // Non-severe logs (trace, debug) are ignored by default. +//! // If you wish to enable all logs, call +//! spdlog::default_logger().set_level_filter(spdlog::LevelFilter::All); +//! +//! info!("hello, world!"); //! error!("oops!"); +//! debug!("3 + 2 = {}", 5); //! ``` //! //! Output: //! //!

-//! [2022-11-02 09:23:12.263] [info] hello, world!
-//! [2022-11-02 09:23:12.263] [warn] 3 + 2 = 5
-//! [2022-11-02 09:23:12.263] [error] oops!
+//! [2022-11-02 09:23:12.263] [info] hello, world!
+//! [2022-11-02 09:23:12.263] [error] oops!
+//! [2022-11-02 09:23:12.263] [debug] 3 + 2 = 5
 //! 
//! -//! If you want to learn more advanced features such as *asynchronous sink*, -//! *compile-time pattern formatter*, etc., please see [./examples] -//! directory. +//! The basic use is through these logging macros: [`trace!`], [`debug!`], +//! [`info!`], [`warn!`], [`error!`], [`critical!`], where `critical!` +//! represents the most severe logs and `trace!` the most verbose. Each of these +//! macros accept format strings similarly to [`println!`]. All log macros +//! and common types are already under [`prelude`] module. //! -//! ## Help +//! ## Sink //! -//! If you have any questions or need help while using this crate, feel free to -//! [open a discussion]. For feature requests or bug reports, please [open an -//! issue]. +//! Many real programs want more than just displaying logs to the terminal. //! -//! # Overview of features +//! [`Sink`]s are the objects that actually write logs to their targets. If you +//! want logs to be written to files as well, [`FileSink`] is what you need. //! -//! - [Compatible with log crate](#compatible-with-log-crate) -//! - [Asynchronous support](#asynchronous-support) -//! - [Configured via environment -//! variable](#configured-via-environment-variable) -//! - [Compile-time and runtime pattern -//! formatter](#compile-time-and-runtime-pattern-formatter) -//! - [Compile-time filters](#compile-time-filters) -//! -//! # Compatible with log crate -//! -//! This is optional and is controlled by crate feature `log`. +//! ``` +//! # use std::sync::Arc; +//! use spdlog::{prelude::*, sink::FileSink}; +//! +//! # fn main() -> spdlog::Result<()> { +//! let path = "path/to/somewhere.log"; +//! +//! # let path = concat!(env!("OUT_DIR"), "/doctest-out/crate-1.txt"); +//! let new_logger = spdlog::default_logger().fork_with(|new| { +//! let file_sink = Arc::new(FileSink::builder().path(path).build()?); +//! new.sinks_mut().push(file_sink); +//! Ok(()) +//! })?; +//! # let backup = spdlog::default_logger(); +//! spdlog::set_default_logger(new_logger); +//! +//! info!("from now on, logs will be written to both stdout/stderr and the file"); +//! # spdlog::set_default_logger(backup); +//! # Ok(()) } +//! ``` //! -//! The compatibility with [log crate] is mainly through a proxy layer -//! [`LogCrateProxy`]. Call [`init_log_crate_proxy`] function to enable the -//! proxy layer, and all logs from [log crate] will be handled by it. You can -//! use it to output [log crate] logs of upstream dependencies or to quickly -//! migrate from [log crate] for your projects. +//! Take a look at [`sink`] module for more interesting sinks, such as +//! [`RotatingFileSink`] that automatically rotates files by time point or file +//! size, and [`AsyncPoolSink`] that outputs logs asynchronously. //! -//! [`LogCrateProxy`] forwards all logs from [log crate] to [`default_logger`] -//! by default, you can call [`log_crate_proxy()`] to get a reference to this -//! proxy to configure it. +//! ## Logger //! -//! See [./examples] directory for examples. +//! A complex program may consist of many separated components. //! -//! # Asynchronous support +//! [`Logger`] manages, controls and invokes multiple sinks within it. In +//! addition to having the global [`default_logger`], more loggers are allowed +//! to be configured, stored and used independently. //! -//! See [Asynchronous combined sink]. +//! Logging macros provide an optional parameter `logger`. If it is specified, +//! logs will be processed by the specified logger instead of the global default +//! logger. //! -//! # Configured via environment variable +//! And benefiting from the fact that a logger uses `Arc` to store sinks, a sink +//! can be set and used by more than one logger, and you can combine them as you +//! like. //! -//! Users can optionally configure the level filter of loggers via the -//! environment variable `SPDLOG_RS_LEVEL`. +//! ``` +//! use spdlog::prelude::*; +//! # use spdlog::Result; //! -//! For more details, see the documentation of [`init_env_level`]. +//! struct AppDatabase { +//! logger: Logger, +//! // Database info... +//! } //! -//! # Compile-time and runtime pattern formatter +//! impl AppDatabase { +//! fn new() -> Result { +//! let logger = Logger::builder() +//! .name("database") +//! // .sink( ... ) +//! // .sink( ... ) +//! // .level_filter( ... ) +//! // ... +//! .build()?; +//! Ok(Self { logger, /* Database info... */ }) +//! } +//! +//! fn query(&self) -> T { +//! let data = /* Query from the database */ +//! # 114514; +//! trace!(logger: self.logger, "queried data {}", data); +//! data +//! # ; unreachable!() +//! } +//! } //! -//! spdlog-rs supports formatting your log records according to a pattern -//! string. There are 2 ways to construct a pattern: +//! struct AppNetwork { /* ... */ } +//! struct AppAuth { /* ... */ } +//! struct AppBlahBlah { /* ... */ } +//! ``` //! -//! - Macro [`pattern!`]: Builds a pattern at compile-time. -//! - Macro [`runtime_pattern!`]: Builds a pattern at runtime. +//! ## Learn more //! -//! ``` -//! use spdlog::formatter::{pattern, PatternFormatter}; -//! #[cfg(feature = "runtime-pattern")] -//! use spdlog::formatter::runtime_pattern; -//! # use spdlog::sink::{Sink, WriteSink}; -//! -//! # fn main() -> Result<(), Box> { -//! // This pattern is built at compile-time, the template accepts only a literal string. -//! let pattern = pattern!("[{date} {time}.{millisecond}] [{level}] {payload}{eol}"); -//! -//! #[cfg(feature = "runtime-pattern")] -//! { -//! // This pattern is built at runtime, the template accepts a runtime string. -//! let input = "[{date} {time}.{millisecond}] [{level}] {payload}{eol}"; -//! let pattern = runtime_pattern!(input)?; -//! } +//! Directory [./examples] contains more advanced usage examples. You can learn +//! them along with their documentation. //! -//! // Use the compile-time or runtime pattern. -//! # let your_sink = WriteSink::builder().target(vec![]).build()?; -//! your_sink.set_formatter(Box::new(PatternFormatter::new(pattern))); -//! # Ok(()) } -//! ``` +//! If you have any trouble while using this crate, please don't hesitate to +//! [open a discussion] for help. For feature requests or bug reports, please +//! [open an issue]. //! //! # Compile-time filters //! @@ -156,34 +182,33 @@ //! debug, and info level logs in release builds with //! `features = ["level-debug", "release-level-warn"]`. //! -//! # Crate Feature Flags +//! # Crate feature flags //! //! The following crate feature flags are available in addition to the filters. //! They are configured in your `Cargo.toml`. //! //! - `source-location` allows recording the source location of each log. When -//! it is enabled the default formatter [`FullFormatter`] will always format -//! the source location information, and some formatting patterns related to -//! source location will be available. If you do not want the source location +//! it is enabled, the source location will be present in [`Record`] and +//! visible to [`Formatter`], and formatting patterns related to source +//! location will be available. If you do not want the source location //! information to appear in your binary file, you may prefer not to enable //! it. //! //! - `flexible-string` improves the performance of formatting records, however -//! contains unsafe code. For more details, see the documentation of +//! it contains unsafe code. For more details, see the documentation of //! [`StringBuf`]. //! -//! - `log` see [Compatible with log crate](#compatible-with-log-crate) above. +//! - `log` enables the compatibility with [log crate]. //! //! - `native` enables platform-specific components, such as -//! [`sink::WinDebugSink`], [`sink::JournaldSink`], etc. Note If the -//! component requires additional system dependencies, then more granular -//! features need to be enabled as well. See the documentation of the -//! component for these details. +//! [`sink::WinDebugSink`] for Windows, [`sink::JournaldSink`] for Linux, +//! etc. Note If the component requires additional system dependencies, then +//! more granular features need to be enabled as well. //! //! - `runtime-pattern` enables the ability to build patterns with runtime //! template string. See [`RuntimePattern`] for more details. //! -//! # Supported Rust Versions +//! # Supported Rust versions //! //!