Skip to content

Commit

Permalink
sth like envfilter® :D
Browse files Browse the repository at this point in the history
Signed-off-by: tison <wander4096@gmail.com>
  • Loading branch information
tisonkun committed Oct 25, 2024
1 parent 5dfd339 commit 4f7cf99
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 55 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
run: |
cargo run --example simple_stdio
cargo run --example fn_layout_filter
cargo run --example directive_filter
cargo run --example env_filter
cargo run --features="no-color" --example simple_stdio
cargo run --features="json" --example json_stdio
cargo run --features="json,rolling_file" --example rolling_file
Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ rolling_file = ["dep:crossbeam-channel", "dep:parking_lot"]
anyhow = { version = "1.0" }
colored = { version = "2.1" }
env_filter = { version = "0.1" }
jiff = { version = "0.1.10" }
jiff = { version = "0.1.13" }
log = { version = "0.4", features = ["std", "kv_unstable"] }
paste = { version = "1.0" }

[dev-dependencies]
rand = "0.8"
tempfile = "3.12"
tempfile = "3.13"

## Serde dependencies
[dependencies.serde]
Expand Down Expand Up @@ -114,5 +114,5 @@ name = "fn_layout_filter"
path = "examples/fn_layout_filter.rs"

[[example]]
name = "directive_filter"
path = "examples/directive_filter.rs"
name = "env_filter"
path = "examples/env_filter.rs"
4 changes: 2 additions & 2 deletions examples/directive_filter.rs → examples/env_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
// limitations under the License.

use logforth::append;
use logforth::filter::DirectiveFilter;
use logforth::filter::EnvFilter;
use logforth::Dispatch;
use logforth::Logger;

fn main() {
Logger::new()
.dispatch(
Dispatch::new()
.filter(DirectiveFilter::from_default_env())
.filter(EnvFilter::from_default_env())
.append(append::Stdout::default()),
)
.apply()
Expand Down
85 changes: 45 additions & 40 deletions src/filter/directive.rs → src/filter/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,23 @@ use crate::Filter;
/// The default name for the environment variable to read filters from.
pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG";

/// A filter that follows the `RUST_LOG` environment variable pattern.
/// A filter consists of one or more comma-separated directives which match on [`log::Record`].
///
/// Read more from [the `env_logger` documentation](https://docs.rs/env_logger/#enabling-logging).
/// Each directive may have a corresponding maximum verbosity [`level`][log::Level] which enables
/// records that match.
///
/// Less exclusive levels (like `trace` or `info`) are considered to be more verbose than more
/// exclusive levels (like `error` or `warn`).
///
/// The directive syntax is similar to that of [`env_logger`](https://crates.io/crates/env_logger)'s.
/// Read more from [the `env_logger` documentation](https://docs.rs/env_logger/#enabling-logging)
#[derive(Debug)]
pub struct DirectiveFilter(env_filter::Filter);
pub struct EnvFilter(env_filter::Filter);

impl DirectiveFilter {
/// Initializes the filter builder from the [DirectiveFilterBuilder].
pub fn new(mut builder: DirectiveFilterBuilder) -> Self {
DirectiveFilter(builder.0.build())
impl EnvFilter {
/// Initializes the filter builder from the [EnvFilterBuilder].
pub fn new(mut builder: EnvFilterBuilder) -> Self {
EnvFilter(builder.0.build())
}

/// Initializes the filter builder from the environment using default variable name `RUST_LOG`.
Expand All @@ -43,11 +50,11 @@ impl DirectiveFilter {
/// Initialize a filter using the default environment variables:
///
/// ```
/// use logforth::filter::DirectiveFilter;
/// let filter = DirectiveFilter::from_default_env();
/// use logforth::filter::EnvFilter;
/// let filter = EnvFilter::from_default_env();
/// ```
pub fn from_default_env() -> Self {
DirectiveFilter::from_env(DEFAULT_FILTER_ENV)
EnvFilter::from_env(DEFAULT_FILTER_ENV)
}

/// Initializes the filter builder from the environment using default variable name `RUST_LOG`.
Expand All @@ -59,14 +66,14 @@ impl DirectiveFilter {
/// value:
///
/// ```
/// use logforth::filter::DirectiveFilter;
/// let filter = DirectiveFilter::from_default_env_or("info");
/// use logforth::filter::EnvFilter;
/// let filter = EnvFilter::from_default_env_or("info");
/// ```
pub fn from_default_env_or<'a, V>(default: V) -> Self
where
V: Into<Cow<'a, str>>,
{
DirectiveFilter::from_env_or(DEFAULT_FILTER_ENV, default)
EnvFilter::from_env_or(DEFAULT_FILTER_ENV, default)
}

/// Initializes the filter builder from the environment using specific variable name.
Expand All @@ -76,20 +83,20 @@ impl DirectiveFilter {
/// Initialize a filter using the using specific variable name:
///
/// ```
/// use logforth::filter::DirectiveFilter;
/// let filter = DirectiveFilter::from_env("MY_LOG");
/// use logforth::filter::EnvFilter;
/// let filter = EnvFilter::from_env("MY_LOG");
/// ```
pub fn from_env<'a, E>(name: E) -> Self
where
E: Into<Cow<'a, str>>,
{
let name = name.into();

let builder = DirectiveFilterBuilder::new();
let builder = EnvFilterBuilder::new();
if let Ok(s) = std::env::var(&*name) {
DirectiveFilter::new(builder.parse(&s))
EnvFilter::new(builder.parse(&s))
} else {
DirectiveFilter::new(builder)
EnvFilter::new(builder)
}
}

Expand All @@ -102,8 +109,8 @@ impl DirectiveFilter {
/// value:
///
/// ```
/// use logforth::filter::DirectiveFilter;
/// let filter = DirectiveFilter::from_env_or("MY_LOG", "info");
/// use logforth::filter::EnvFilter;
/// let filter = EnvFilter::from_env_or("MY_LOG", "info");
/// ```
pub fn from_env_or<'a, 'b, E, V>(name: E, default: V) -> Self
where
Expand All @@ -113,11 +120,11 @@ impl DirectiveFilter {
let name = name.into();
let default = default.into();

let builder = DirectiveFilterBuilder::new();
let builder = EnvFilterBuilder::new();
if let Ok(s) = std::env::var(&*name) {
DirectiveFilter::new(builder.parse(&s))
EnvFilter::new(builder.parse(&s))
} else {
DirectiveFilter::new(builder.parse(&default))
EnvFilter::new(builder.parse(&default))
}
}

Expand All @@ -138,45 +145,43 @@ impl DirectiveFilter {
}
}

impl From<DirectiveFilter> for Filter {
fn from(filter: DirectiveFilter) -> Self {
Filter::Directive(filter)
impl From<EnvFilter> for Filter {
fn from(filter: EnvFilter) -> Self {
Filter::Env(filter)
}
}

impl From<LevelFilter> for DirectiveFilter {
impl From<LevelFilter> for EnvFilter {
fn from(filter: LevelFilter) -> Self {
DirectiveFilter::new(DirectiveFilterBuilder::new().filter_level(filter))
EnvFilter::new(EnvFilterBuilder::new().filter_level(filter))
}
}

impl<'a> From<&'a str> for DirectiveFilter {
impl<'a> From<&'a str> for EnvFilter {
fn from(filter: &'a str) -> Self {
DirectiveFilter::new(DirectiveFilterBuilder::new().parse(filter))
EnvFilter::new(EnvFilterBuilder::new().parse(filter))
}
}

impl FromStr for DirectiveFilter {
impl FromStr for EnvFilter {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
DirectiveFilterBuilder::new()
.try_parse(s)
.map(DirectiveFilter::new)
EnvFilterBuilder::new().try_parse(s).map(EnvFilter::new)
}
}

/// A builder for the directive log filter.
/// A builder for the env log filter.
///
/// It can be used to parse a set of directives from a string before building a [DirectiveFilter]
/// It can be used to parse a set of directives from a string before building a [EnvFilter]
/// instance.
#[derive(Default, Debug)]
pub struct DirectiveFilterBuilder(env_filter::Builder);
pub struct EnvFilterBuilder(env_filter::Builder);

impl DirectiveFilterBuilder {
impl EnvFilterBuilder {
/// Initializes the filter builder with defaults.
pub fn new() -> Self {
DirectiveFilterBuilder(env_filter::Builder::new())
EnvFilterBuilder(env_filter::Builder::new())
}

/// Try to initialize the filter builder from an environment; return `None` if the environment
Expand All @@ -185,7 +190,7 @@ impl DirectiveFilterBuilder {
let mut builder = env_filter::Builder::new();
let config = std::env::var(env).ok()?;
builder.try_parse(&config).ok()?;
Some(DirectiveFilterBuilder(builder))
Some(EnvFilterBuilder(builder))
}

/// Adds a directive to the filter for a specific module.
Expand Down
16 changes: 8 additions & 8 deletions src/filter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ use std::str::FromStr;
use log::LevelFilter;

pub use self::custom::CustomFilter;
pub use self::directive::DirectiveFilter;
pub use self::env::EnvFilter;

mod custom;
pub mod directive;
pub mod env;

/// The result of a filter may return.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand All @@ -37,42 +37,42 @@ pub enum FilterResult {

#[derive(Debug)]
pub enum Filter {
Directive(DirectiveFilter),
Env(EnvFilter),
Custom(CustomFilter),
}

impl Filter {
pub(crate) fn enabled(&self, metadata: &log::Metadata) -> FilterResult {
match self {
Filter::Directive(filter) => filter.enabled(metadata),
Filter::Env(filter) => filter.enabled(metadata),
Filter::Custom(filter) => filter.enabled(metadata),
}
}

pub(crate) fn matches(&self, record: &log::Record) -> FilterResult {
match self {
Filter::Directive(filter) => filter.matches(record),
Filter::Env(filter) => filter.matches(record),
Filter::Custom(filter) => filter.enabled(record.metadata()),
}
}
}

impl From<LevelFilter> for Filter {
fn from(filter: LevelFilter) -> Self {
DirectiveFilter::from(filter).into()
EnvFilter::from(filter).into()
}
}

impl<'a> From<&'a str> for Filter {
fn from(filter: &'a str) -> Self {
DirectiveFilter::from(filter).into()
EnvFilter::from(filter).into()
}
}

impl FromStr for Filter {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
DirectiveFilter::from_str(s).map(Into::into)
EnvFilter::from_str(s).map(Into::into)
}
}

0 comments on commit 4f7cf99

Please sign in to comment.