Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
subscriber: add
Targets::targets
method to iterate directives (toki…
…o-rs#1574) There's currently no way to get the registered directives from a `Targets` instance, which is a barrier to some use-cases such as combining user-supplied directives with application-supplied defaults. This commit adds a `Targets::targets` method, which returns an iterator of `(&str, LevelFilter)` pairs, one for each directive (excluding the default level, whose `target` is `None`). Items are yielded as per the underlying `DirectiveSet::directives`, which would yield itms in specifity order (as constructed by `DirectiveSet::add`). However, the order has been left explicitly undefined in the documentation for `Targets::targets` on the basis that this is an implementation detail that may change. ## Motivation As hinted in the commit message, my use-case is to have an application-supplied 'base' `Targets` filter, which can then be extended/overridden by a user-supplied filter parsed from `RUST_LOG` (e.g.). Sadly, there's currently no way of getting the directives out of a `Targets` instance, nor to re-serialize to the string representation. Thus, the only way to implement the above would be to manually parse the user-supplied filters in the application, which is shame since it duplicates the implementation here and would be prone to drift/subtle incompatibilities. ## Solution The proposed solution is to add methods to `Targets` to retrieve the underlying directives. ```rust // application-defined defaults, for a useful level of information let mut filter = Targets::new() .with_target("my_crate", LevelFilter::INFO) .with_target("important_dependency", LevelFilter::INFO); if let Ok(overrides) = std::env::var("RUST_LOG") { let overrides: Targets = overrides.parse().unwrap(); // merge user-supplied overrides, which can enable additional tracing // or disable default tracing filter.extend(overrides.iter()); // ^^^^^^^^^ this is new } ``` For this PR, I've gone for `fn iter(&self) -> Iter`, e.g. a method `targets` that returns an iterator over the pairs of `(&str, LevelFilter)` in the underlying directives. The iterator excludes any default level(s) where `target` would be `None`. This matches nicely with the `FromIterator` and `Extend` impls, which use `(impl Into<String>, impl Into<LevelFilter>)`. In addition, I've added `IntoIterator` implementations for `&Targets` and for `Targets`. The by-value `IntoIterator` implementation returns an `IntoIter` type that moves the targets as `String`s, rather than as borrowed `&str`s. This makes `extend` more efficient when moving a second `Targets` by value.
- Loading branch information