Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor documentation and examples #67

Draft
wants to merge 1 commit into
base: main-dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 21 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,25 @@
[![](https://img.shields.io/badge/docs.rs-spdlog--rs-ff69b4?style=flat-square&logo=rust)](https://docs.rs/spdlog-rs)
[![](https://img.shields.io/github/actions/workflow/status/SpriteOvO/spdlog-rs/ci.yml?branch=main&style=flat-square&logo=githubactions&logoColor=white)](https://github.com/SpriteOvO/spdlog-rs/actions/workflows/ci.yml)

A fast and combinable Rust logging crate, inspired by the C++ logging library [spdlog].
Fast, highly configurable Rust logging crate, inspired by the C++ logging library [spdlog].

## Features

- Very fast (see [Benchmarks]).
- Various log targets:
- Standard streams with optional colors.
- Files.
- Rotating log files by file size.
- Rotating log files hourly.
- Rotating log files daily.
- ... (more targets are implementing, PRs are welcome)
- Extendable with custom log targets.
- Compatible with [log crate] (optional).
- Asynchronous support.
- Configured via environment variable.
- Custom formatting.
- Log filtering - log levels can be modified in runtime as well as in compile time.
- Compatible with `log` crate.
- Custom log formats:
- compile-time zero-cost pattern or runtime pattern;
- manually implementing for more flexibility.
- Various combinable sinks:
- standard streams with optional color support;
- files (single file, rotating hourly, daily or by file size);
- platform-specific (e.g. `journald` on Linux, `OutputDebugStringW` on Windows);
- ... and able to implement one yourself.
- Configuring via environment variables or TOML[^1].
- More readable level filters.

[^1]: TOML deserialization support is working in progress, tracking issue [#25]

## Getting started

Expand All @@ -32,11 +33,11 @@ Add this to `Cargo.toml`:
spdlog-rs = "0.3"
```

The documentation of this crate is hosted on [docs.rs], and you can find examples under [./examples] directory.
The documentation of this crate is hosted on [docs.rs], and you can learn examples under [./examples] directory along with it.

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].
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].

## Supported Rust Versions
## Supported Rust versions

<!--
When updating this, also update:
Expand All @@ -55,22 +56,18 @@ The current minimum supported Rust version is 1.56.

Licensed under either of

* Apache License, Version 2.0
([LICENSE-APACHE](/LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license
([LICENSE-MIT](/LICENSE-MIT) or http://opensource.org/licenses/MIT)
* Apache License, Version 2.0 ([LICENSE-APACHE](/LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](/LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

[spdlog]: https://github.com/gabime/spdlog
[Benchmarks]: https://github.com/SpriteOvO/spdlog-rs/blob/main/spdlog/benches/README.md
[log crate]: https://crates.io/crates/log
[#25]: https://github.com/SpriteOvO/spdlog-rs/issues/25
[./examples]: https://github.com/SpriteOvO/spdlog-rs/tree/main/spdlog/examples
[docs.rs]: https://docs.rs/spdlog-rs/
[open a discussion]: https://github.com/SpriteOvO/spdlog-rs/discussions/new
Expand Down
57 changes: 27 additions & 30 deletions spdlog/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
//! Provides error types.
//!
//! # Default error handler
//!
//! If a logger or sink does not have an error handler set up, a default error
//! handler will be used, which will print the error to `stderr`.

use std::{
fmt::{self, Display},
Expand All @@ -13,94 +18,87 @@ use crate::utils::const_assert;
#[cfg(feature = "multi-thread")]
use crate::{sink::Task, RecordOwned};

/// The error type of this crate.
/// Contains most errors of this crate.
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum Error {
/// The variant returned by [`Formatter`]s when an error occurs in
/// formatting a record.
/// Returned by [`Formatter`]s when an error occurs in formatting a record.
///
/// [`Formatter`]: crate::formatter::Formatter
#[error("format record error: {0}")]
FormatRecord(fmt::Error),

/// The variant returned by [`Sink`]s when an error occurs in writing a
/// record to the target.
/// Returned by [`Sink`]s when an error occurs in writing a record to the
/// target.
///
/// [`Sink`]: crate::sink::Sink
#[error("write record error: {0}")]
WriteRecord(io::Error),

/// The variant returned by [`Sink`]s when an error occurs in flushing the
/// buffer.
/// Returned by [`Sink`]s when an error occurs in flushing the buffer.
///
/// [`Sink`]: crate::sink::Sink
#[error("flush buffer error: {0}")]
FlushBuffer(io::Error),

/// The variant returned by [`Sink`]s when an error occurs in creating a
/// directory.
/// Returned by [`Sink`]s when an error occurs in creating a directory.
///
/// [`Sink`]: crate::sink::Sink
#[error("create directory error: {0}")]
CreateDirectory(io::Error),

/// The variant returned by [`Sink`]s when an error occurs in opening a
/// file.
/// Returned by [`Sink`]s when an error occurs in opening a file.
///
/// [`Sink`]: crate::sink::Sink
#[error("open file error: {0}")]
OpenFile(io::Error),

/// The variant returned by [`Sink`]s when an error occurs in querying the
/// metadata of a file.
/// Returned by [`Sink`]s when an error occurs in querying the metadata of a
/// file.
///
/// [`Sink`]: crate::sink::Sink
#[error("query file metadata error: {0}")]
QueryFileMetadata(io::Error),

/// The variant returned by [`Sink`]s when an error occurs in renaming a
/// file.
/// Returned by [`Sink`]s when an error occurs in renaming a file.
///
/// [`Sink`]: crate::sink::Sink
#[error("rename file error: {0}")]
RenameFile(io::Error),

/// The variant returned by [`Sink`]s when an error occurs in removing a
/// file.
/// Returned by [`Sink`]s when an error occurs in removing a file.
///
/// [`Sink`]: crate::sink::Sink
#[error("remove file error: {0}")]
RemoveFile(io::Error),

/// The variant returned by [`from_str`] when the string doesn't match any
/// of the log levels.
/// Returned by [`from_str`] when the string doesn't match any of the log
/// levels.
///
/// [`from_str`]: std::str::FromStr::from_str
#[error("attempted to convert a string that doesn't match an existing log level: {0}")]
ParseLevel(String),

/// The variant returned if an invalid argument was passed in.
/// Returned if an invalid argument was passed in.
#[error("invalid argument {0}")]
InvalidArgument(#[from] InvalidArgumentError),

/// The variant returned by [`Sink`]s when an error occurs in sending to the
/// channel.
/// Returned by [`Sink`]s when an error occurs in sending to the channel.
///
/// [`Sink`]: crate::sink::Sink
#[cfg(feature = "multi-thread")]
#[error("failed to send message to channel: {0}")]
SendToChannel(SendToChannelError, SendToChannelErrorDropped),

/// The variant returned by [`runtime_pattern!`] when the
/// pattern is failed to be built at runtime.
/// Returned by [`runtime_pattern!`] when the pattern is failed to be built
/// at runtime.
///
/// [`runtime_pattern!`]: crate::formatter::runtime_pattern
#[cfg(feature = "runtime-pattern")]
#[error("failed to build pattern at runtime: {0}")]
BuildPattern(BuildPatternError),

/// This variant returned when multiple errors occurred.
/// Returned when multiple errors occurred.
#[error("{0:?}")]
Multiple(Vec<Error>),

Expand All @@ -109,7 +107,7 @@ pub enum Error {
__ForInternalTestsUseOnly(i32),
}

/// This error type contains a variety of possible invalid arguments.
/// Indicates that an invalid parameter was specified.
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum InvalidArgumentError {
Expand All @@ -135,7 +133,7 @@ pub enum InvalidArgumentError {
ThreadPoolCapacity(String),
}

/// This error indicates that an invalid logger name was set.
/// Indicates that an invalid logger name was set.
///
/// See the documentation of [`LoggerBuilder::name`] for the name requirements.
///
Expand Down Expand Up @@ -164,7 +162,7 @@ impl Display for SetLoggerNameError {
}
}

/// The more detailed error type of sending to channel.
/// Indicates that an error occurred while sending to channel.
#[cfg(feature = "multi-thread")]
#[derive(Error, Debug)]
#[non_exhaustive]
Expand Down Expand Up @@ -249,8 +247,7 @@ impl SendToChannelErrorDropped {
}
}

/// This error indicates that an error occurred while building a pattern at
/// compile-time.
/// Indicates that an error occurred while building a pattern at compile-time.
#[cfg(feature = "runtime-pattern")]
#[derive(Error, Debug)]
#[error("{0}")]
Expand Down
10 changes: 5 additions & 5 deletions spdlog/src/formatter/full_formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
///
/// <pre>
/// [2022-11-02 09:23:12.263] [<font color="#11D116">info</font>] hello, world!
/// [2022-11-02 09:23:12.263] [<font color="#0DBC79">info</font>] hello, world!
/// </pre>
///
/// - If the logger has a name:
///
/// <pre>
/// [2022-11-02 09:23:12.263] [logger-name] [<font color="#11D116">info</font>] hello, world!
/// [2022-11-02 09:23:12.263] [logger-name] [<font color="#0DBC79">info</font>] hello, world!
/// </pre>
///
/// - If crate feature `source-location` is enabled:
///
/// <pre>
/// [2022-11-02 09:23:12.263] [<font color="#11D116">info</font>] [mod::path, src/main.rs:4] hello, world!
/// [2022-11-02 09:23:12.263] [logger-name] [<font color="#0DBC79">info</font>] [mod::path, src/main.rs:4] hello, world!
/// </pre>
#[derive(Clone)]
pub struct FullFormatter {
Expand Down
58 changes: 48 additions & 10 deletions spdlog/src/formatter/mod.rs
Original file line number Diff line number Diff line change
@@ -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<dyn std::error::Error>> {
//! // 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(
Expand All @@ -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
///
Expand Down Expand Up @@ -55,7 +99,7 @@ impl FmtExtraInfo {
FmtExtraInfo::default()
}

/// Constructs a [`FmtExtraInfoBuilder`].
/// Gets a [`FmtExtraInfoBuilder`].
#[must_use]
pub fn builder() -> FmtExtraInfoBuilder {
FmtExtraInfoBuilder::new()
Expand All @@ -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,
Expand Down