aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Vander Stoep <jeffv@google.com>2024-02-06 12:04:00 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2024-02-06 12:04:00 +0000
commit18416b35d3dda4bf38336f52d1ef30e08398a2f7 (patch)
tree557e2a18ba5917b760198ffc92e40e337d0d7aa0
parent90fa860d7cc113af40466de84be8c0847ace93e2 (diff)
parentab6d4828012cb640dc355f8e8c1cb9d00a8caa8b (diff)
downloadtracing-subscriber-main.tar.gz
Upgrade tracing-subscriber to 0.3.18 am: ab6d482801HEADmastermain
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/tracing-subscriber/+/2950618 Change-Id: I4fcee0e5637751f5bce80ed66266315bdf278b99 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp2
-rw-r--r--CHANGELOG.md32
-rw-r--r--Cargo.toml18
-rw-r--r--Cargo.toml.orig9
-rw-r--r--METADATA25
-rw-r--r--README.md6
-rw-r--r--src/field/mod.rs3
-rw-r--r--src/filter/directive.rs5
-rw-r--r--src/filter/env/builder.rs11
-rw-r--r--src/filter/env/directive.rs23
-rw-r--r--src/filter/layer_filters/mod.rs115
-rw-r--r--src/fmt/fmt_layer.rs110
-rw-r--r--src/fmt/format/mod.rs27
-rw-r--r--src/fmt/mod.rs13
-rw-r--r--src/fmt/time/chrono_crate.rs177
-rw-r--r--src/fmt/time/mod.rs15
-rw-r--r--src/fmt/time/time_crate.rs48
-rw-r--r--src/fmt/writer.rs9
-rw-r--r--src/layer/layered.rs2
-rw-r--r--src/layer/mod.rs22
-rw-r--r--src/lib.rs6
-rw-r--r--src/macros.rs2
-rw-r--r--src/registry/mod.rs6
-rw-r--r--tests/cached_layer_filters_dont_break_other_layers.rs22
-rw-r--r--tests/env_filter/main.rs159
-rw-r--r--tests/env_filter/per_layer.rs76
-rw-r--r--tests/field_filter.rs48
-rw-r--r--tests/filter_log.rs8
-rw-r--r--tests/hinted_layer_filters_dont_break_other_layers.rs26
-rw-r--r--tests/layer_filter_interests_are_cached.rs8
-rw-r--r--tests/layer_filters/boxed.rs2
-rw-r--r--tests/layer_filters/combinators.rs2
-rw-r--r--tests/layer_filters/filter_scopes.rs94
-rw-r--r--tests/layer_filters/main.rs73
-rw-r--r--tests/layer_filters/option.rs143
-rw-r--r--tests/layer_filters/per_event.rs10
-rw-r--r--tests/layer_filters/targets.rs3
-rw-r--r--tests/layer_filters/trees.rs87
-rw-r--r--tests/layer_filters/vec.rs38
-rw-r--r--tests/multiple_layer_filter_interests_cached.rs26
-rw-r--r--tests/option_filter_interest_caching.rs53
-rw-r--r--tests/same_len_filters.rs26
-rw-r--r--tests/unhinted_layer_filters_dont_break_other_layers.rs22
-rw-r--r--tests/utils.rs4
-rw-r--r--tests/vec_subscriber_filter_interests_cached.rs29
46 files changed, 1164 insertions, 483 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index db028ed..4a55346 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "0114ec1cf56e01e79b2e429e77c660457711d263"
+ "sha1": "8b7a1dde69797b33ecfa20da71e72eb5e61f0b25"
},
"path_in_vcs": "tracing-subscriber"
} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index e83f278..de958da 100644
--- a/Android.bp
+++ b/Android.bp
@@ -6,7 +6,7 @@ rust_library {
host_supported: true,
crate_name: "tracing_subscriber",
cargo_env_compat: true,
- cargo_pkg_version: "0.3.17",
+ cargo_pkg_version: "0.3.18",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a33e55..a8894b9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,35 @@
+# 0.3.18 (November 13, 2023)
+
+This release of `tracing-subscriber` adds support for the [`NO_COLOR`] environment
+variable (an informal standard to disable emitting ANSI color escape codes) in
+`fmt::Layer`, reintroduces support for the [`chrono`] crate, and increases the
+minimum supported Rust version (MSRV) to Rust 1.63.0.
+
+It also introduces several minor API improvements.
+
+### Added
+
+- **chrono**: Add [`chrono`] implementations of `FormatTime` ([#2690])
+- **subscriber**: Add support for the [`NO_COLOR`] environment variable in
+`fmt::Layer` ([#2647])
+- **fmt**: make `format::Writer::new()` public ([#2680])
+- **filter**: Implement `layer::Filter` for `Option<Filter>` ([#2407])
+
+### Changed
+
+- **log**: bump version of `tracing-log` to 0.2 ([#2772])
+- Increased minimum supported Rust version (MSRV) to 1.63.0+.
+
+[`chrono`]: https://github.com/chronotope/chrono
+[`NO_COLOR`]: https://no-color.org/
+[#2690]: https://github.com/tokio-rs/tracing/pull/2690
+[#2647]: https://github.com/tokio-rs/tracing/pull/2647
+[#2680]: https://github.com/tokio-rs/tracing/pull/2680
+[#2407]: https://github.com/tokio-rs/tracing/pull/2407
+[#2772]: https://github.com/tokio-rs/tracing/pull/2772
+
+Thanks to @shayne-fletcher, @dmlary, @kaifastromai, and @jsgf for contributing!
+
# 0.3.17 (April 21, 2023)
This release of `tracing-subscriber` fixes a build error when using `env-filter`
diff --git a/Cargo.toml b/Cargo.toml
index 3d62fe7..c20d5ba 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2018"
-rust-version = "1.56.0"
+rust-version = "1.63.0"
name = "tracing-subscriber"
-version = "0.3.17"
+version = "0.3.18"
authors = [
"Eliza Weisman <eliza@buoyant.io>",
"David Barsky <me@davidbarsky.com>",
@@ -37,6 +37,7 @@ categories = [
]
license = "MIT"
repository = "https://github.com/tokio-rs/tracing"
+resolver = "2"
[package.metadata.docs.rs]
all-features = true
@@ -61,6 +62,15 @@ harness = false
name = "enter"
harness = false
+[dependencies.chrono]
+version = "0.4.26"
+features = [
+ "clock",
+ "std",
+]
+optional = true
+default-features = false
+
[dependencies.matchers]
version = "0.1.0"
optional = true
@@ -122,7 +132,7 @@ version = "0.1.30"
default-features = false
[dependencies.tracing-log]
-version = "0.1.3"
+version = "0.2.0"
features = [
"log-tracer",
"std",
@@ -172,7 +182,7 @@ features = [
default-features = false
[dev-dependencies.tracing-log]
-version = "0.1.3"
+version = "0.2.0"
[features]
alloc = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 3fbeb2f..807880b 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "tracing-subscriber"
-version = "0.3.17"
+version = "0.3.18"
authors = [
"Eliza Weisman <eliza@buoyant.io>",
"David Barsky <me@davidbarsky.com>",
@@ -20,7 +20,7 @@ categories = [
"asynchronous",
]
keywords = ["logging", "tracing", "metrics", "subscriber"]
-rust-version = "1.56.0"
+rust-version = "1.63.0"
[features]
@@ -48,7 +48,7 @@ smallvec = { optional = true, version = "1.9.0" }
once_cell = { optional = true, version = "1.13.0" }
# fmt
-tracing-log = { path = "../tracing-log", version = "0.1.3", optional = true, default-features = false, features = ["log-tracer", "std"] }
+tracing-log = { path = "../tracing-log", version = "0.2.0", optional = true, default-features = false, features = ["log-tracer", "std"] }
nu-ansi-term = { version = "0.46.0", optional = true }
time = { version = "0.3.2", features = ["formatting"], optional = true }
@@ -59,6 +59,7 @@ tracing-serde = { path = "../tracing-serde", version = "0.1.3", optional = true
# opt-in deps
parking_lot = { version = "0.12.1", optional = true }
+chrono = { version = "0.4.26", default-features = false, features = ["clock", "std"], optional = true }
# registry
sharded-slab = { version = "0.1.4", optional = true }
@@ -72,7 +73,7 @@ valuable-serde = { version = "0.1.0", optional = true, default-features = false
tracing = { path = "../tracing", version = "0.1.35" }
tracing-mock = { path = "../tracing-mock", features = ["tracing-subscriber"] }
log = "0.4.17"
-tracing-log = { path = "../tracing-log", version = "0.1.3" }
+tracing-log = { path = "../tracing-log", version = "0.2.0" }
criterion = { version = "0.3.6", default-features = false }
regex = { version = "1", default-features = false, features = ["std"] }
tracing-futures = { path = "../tracing-futures", version = "0.2.0", default-features = false, features = ["std-future", "std"] }
diff --git a/METADATA b/METADATA
index 22049a6..bf11a20 100644
--- a/METADATA
+++ b/METADATA
@@ -1,19 +1,20 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update external/rust/crates/tracing-subscriber
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+
name: "tracing-subscriber"
description: "()"
third_party {
- url {
- type: HOMEPAGE
- value: "https://crates.io/crates/tracing-subscriber"
- }
- url {
- type: ARCHIVE
- value: "https://static.crates.io/crates/tracing-subscriber/tracing-subscriber-0.3.17.crate"
- }
- version: "0.3.17"
license_type: NOTICE
last_upgrade_date {
- year: 2023
- month: 7
- day: 28
+ year: 2024
+ month: 2
+ day: 6
+ }
+ homepage: "https://crates.io/crates/tracing-subscriber"
+ identifier {
+ type: "Archive"
+ value: "https://static.crates.io/crates/tracing-subscriber/tracing-subscriber-0.3.18.crate"
+ version: "0.3.18"
}
}
diff --git a/README.md b/README.md
index 7c1212c..cc5426d 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Utilities for implementing and composing [`tracing`][tracing] subscribers.
[crates-badge]: https://img.shields.io/crates/v/tracing-subscriber.svg
[crates-url]: https://crates.io/crates/tracing-subscriber
[docs-badge]: https://docs.rs/tracing-subscriber/badge.svg
-[docs-url]: https://docs.rs/tracing-subscriber/0.3.15
+[docs-url]: https://docs.rs/tracing-subscriber/latest
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
[docs-master-url]: https://tracing-rs.netlify.com/tracing_subscriber
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
@@ -32,14 +32,14 @@ Utilities for implementing and composing [`tracing`][tracing] subscribers.
[discord-url]: https://discord.gg/EeF3cQw
[maint-badge]: https://img.shields.io/badge/maintenance-experimental-blue.svg
-*Compiler support: [requires `rustc` 1.56+][msrv]*
+*Compiler support: [requires `rustc` 1.63+][msrv]*
[msrv]: #supported-rust-versions
## Supported Rust Versions
Tracing is built against the latest stable release. The minimum supported
-version is 1.56. The current Tracing version is not guaranteed to build on Rust
+version is 1.63. The current Tracing version is not guaranteed to build on Rust
versions earlier than the minimum supported version.
Tracing follows the same compiler support policies as the rest of the Tokio
diff --git a/src/field/mod.rs b/src/field/mod.rs
index 5dfddb3..03b9146 100644
--- a/src/field/mod.rs
+++ b/src/field/mod.rs
@@ -55,7 +55,7 @@ pub trait VisitOutput<Out>: Visit {
/// Extension trait implemented by types which can be recorded by a [visitor].
///
/// This allows writing code that is generic over `tracing_core`'s
-/// [`span::Attributes`][attr], [`span::Record`][rec], and [`Event`][event]
+/// [`span::Attributes`][attr], [`span::Record`][rec], and [`Event`]
/// types. These types all provide inherent `record` methods that allow a
/// visitor to record their fields, but there is no common trait representing this.
///
@@ -85,7 +85,6 @@ pub trait VisitOutput<Out>: Visit {
/// [visitor]: tracing_core::field::Visit
/// [attr]: tracing_core::span::Attributes
/// [rec]: tracing_core::span::Record
-/// [event]: tracing_core::event::Event
pub trait RecordFields: crate::sealed::Sealed<RecordFieldsMarker> {
/// Record all the fields in `self` with the provided `visitor`.
fn record(&self, visitor: &mut dyn Visit);
diff --git a/src/filter/directive.rs b/src/filter/directive.rs
index 2ae3f0f..9ee2ce5 100644
--- a/src/filter/directive.rs
+++ b/src/filter/directive.rs
@@ -49,7 +49,8 @@ enum ParseErrorKind {
// === impl DirectiveSet ===
impl<T> DirectiveSet<T> {
- #[cfg(feature = "env-filter")]
+ // this is only used by `env-filter`.
+ #[cfg(all(feature = "std", feature = "env-filter"))]
pub(crate) fn is_empty(&self) -> bool {
self.directives.is_empty()
}
@@ -397,7 +398,7 @@ impl FromStr for StaticDirective {
// === impl ParseError ===
impl ParseError {
- #[cfg(feature = "env-filter")]
+ #[cfg(all(feature = "std", feature = "env-filter"))]
pub(crate) fn new() -> Self {
ParseError {
kind: ParseErrorKind::Other(None),
diff --git a/src/filter/env/builder.rs b/src/filter/env/builder.rs
index c814707..8afe117 100644
--- a/src/filter/env/builder.rs
+++ b/src/filter/env/builder.rs
@@ -170,15 +170,16 @@ impl Builder {
self.parse_lossy(var)
}
- /// Returns a new [`EnvFilter`] from the directives in the in the configured
- /// environment variable, or an error if the environment variable is not set
- /// or contains invalid directives.
+ /// Returns a new [`EnvFilter`] from the directives in the configured
+ /// environment variable. If the environment variable is unset, no directive is added.
+ ///
+ /// An error is returned if the environment contains invalid directives.
pub fn from_env(&self) -> Result<EnvFilter, FromEnvError> {
let var = env::var(self.env_var_name()).unwrap_or_default();
self.parse(var).map_err(Into::into)
}
- /// Returns a new [`EnvFilter`] from the directives in the in the configured
+ /// Returns a new [`EnvFilter`] from the directives in the configured
/// environment variable, or an error if the environment variable is not set
/// or contains invalid directives.
pub fn try_from_env(&self) -> Result<EnvFilter, FromEnvError> {
@@ -212,7 +213,7 @@ impl Builder {
#[cfg(feature = "nu_ansi_term")]
use nu_ansi_term::{Color, Style};
// NOTE: We can't use a configured `MakeWriter` because the EnvFilter
- // has no knowledge of any underlying subscriber or collector, which
+ // has no knowledge of any underlying subscriber or subscriber, which
// may or may not use a `MakeWriter`.
let warn = |msg: &str| {
#[cfg(not(feature = "nu_ansi_term"))]
diff --git a/src/filter/env/directive.rs b/src/filter/env/directive.rs
index f062e6e..d095065 100644
--- a/src/filter/env/directive.rs
+++ b/src/filter/env/directive.rs
@@ -120,8 +120,9 @@ impl Directive {
}
pub(super) fn parse(from: &str, regex: bool) -> Result<Self, ParseError> {
- static DIRECTIVE_RE: Lazy<Regex> = Lazy::new(|| Regex::new(
- r"(?x)
+ static DIRECTIVE_RE: Lazy<Regex> = Lazy::new(|| {
+ Regex::new(
+ r"(?x)
^(?P<global_level>(?i:trace|debug|info|warn|error|off|[0-5]))$ |
# ^^^.
# `note: we match log level names case-insensitively
@@ -135,15 +136,18 @@ impl Directive {
# `note: we match log level names case-insensitively
)?
$
- "
- )
- .unwrap());
+ ",
+ )
+ .unwrap()
+ });
static SPAN_PART_RE: Lazy<Regex> =
- Lazy::new(|| Regex::new(r#"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).unwrap());
+ Lazy::new(|| Regex::new(r"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?").unwrap());
static FIELD_FILTER_RE: Lazy<Regex> =
// TODO(eliza): this doesn't _currently_ handle value matchers that include comma
// characters. We should fix that.
- Lazy::new(|| Regex::new(r#"(?x)
+ Lazy::new(|| {
+ Regex::new(
+ r"(?x)
(
# field name
[[:word:]][[[:word:]]\.]*
@@ -152,7 +156,10 @@ impl Directive {
)
# trailing comma or EOS
(?:,\s?|$)
- "#).unwrap());
+ ",
+ )
+ .unwrap()
+ });
let caps = DIRECTIVE_RE.captures(from).ok_or_else(ParseError::new)?;
diff --git a/src/filter/layer_filters/mod.rs b/src/filter/layer_filters/mod.rs
index e50ee6f..69736fa 100644
--- a/src/filter/layer_filters/mod.rs
+++ b/src/filter/layer_filters/mod.rs
@@ -351,10 +351,10 @@ pub trait FilterExt<S>: layer::Filter<S> {
// globally applied to events where it doesn't today, since we can't know
// what `event_enabled` will say until we have the event to call it with.
///
- /// [`Filter`]: crate::subscribe::Filter
- /// [`enabled`]: crate::subscribe::Filter::enabled
- /// [`event_enabled`]: crate::subscribe::Filter::event_enabled
- /// [`callsite_enabled`]: crate::subscribe::Filter::callsite_enabled
+ /// [`Filter`]: crate::layer::Filter
+ /// [`enabled`]: crate::layer::Filter::enabled
+ /// [`event_enabled`]: crate::layer::Filter::event_enabled
+ /// [`callsite_enabled`]: crate::layer::Filter::callsite_enabled
fn not(self) -> combinator::Not<Self, S>
where
Self: Sized,
@@ -478,6 +478,36 @@ macro_rules! filter_impl_body {
fn max_level_hint(&self) -> Option<LevelFilter> {
self.deref().max_level_hint()
}
+
+ #[inline]
+ fn event_enabled(&self, event: &Event<'_>, cx: &Context<'_, S>) -> bool {
+ self.deref().event_enabled(event, cx)
+ }
+
+ #[inline]
+ fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
+ self.deref().on_new_span(attrs, id, ctx)
+ }
+
+ #[inline]
+ fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
+ self.deref().on_record(id, values, ctx)
+ }
+
+ #[inline]
+ fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+ self.deref().on_enter(id, ctx)
+ }
+
+ #[inline]
+ fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
+ self.deref().on_exit(id, ctx)
+ }
+
+ #[inline]
+ fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
+ self.deref().on_close(id, ctx)
+ }
};
}
@@ -493,6 +523,75 @@ impl<S> layer::Filter<S> for Box<dyn layer::Filter<S> + Send + Sync + 'static> {
filter_impl_body!();
}
+// Implement Filter for Option<Filter> where None => allow
+#[cfg(feature = "registry")]
+#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+impl<F, S> layer::Filter<S> for Option<F>
+where
+ F: layer::Filter<S>,
+{
+ #[inline]
+ fn enabled(&self, meta: &Metadata<'_>, ctx: &Context<'_, S>) -> bool {
+ self.as_ref()
+ .map(|inner| inner.enabled(meta, ctx))
+ .unwrap_or(true)
+ }
+
+ #[inline]
+ fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
+ self.as_ref()
+ .map(|inner| inner.callsite_enabled(meta))
+ .unwrap_or_else(Interest::always)
+ }
+
+ #[inline]
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ self.as_ref().and_then(|inner| inner.max_level_hint())
+ }
+
+ #[inline]
+ fn event_enabled(&self, event: &Event<'_>, ctx: &Context<'_, S>) -> bool {
+ self.as_ref()
+ .map(|inner| inner.event_enabled(event, ctx))
+ .unwrap_or(true)
+ }
+
+ #[inline]
+ fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
+ if let Some(inner) = self {
+ inner.on_new_span(attrs, id, ctx)
+ }
+ }
+
+ #[inline]
+ fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
+ if let Some(inner) = self {
+ inner.on_record(id, values, ctx)
+ }
+ }
+
+ #[inline]
+ fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+ if let Some(inner) = self {
+ inner.on_enter(id, ctx)
+ }
+ }
+
+ #[inline]
+ fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
+ if let Some(inner) = self {
+ inner.on_exit(id, ctx)
+ }
+ }
+
+ #[inline]
+ fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
+ if let Some(inner) = self {
+ inner.on_close(id, ctx)
+ }
+ }
+}
+
// === impl Filtered ===
impl<L, F, S> Filtered<L, F, S> {
@@ -595,7 +694,7 @@ impl<L, F, S> Filtered<L, F, S> {
/// # }
/// ```
///
- /// [subscriber]: Subscribe
+ /// [`Layer`]: crate::layer::Layer
pub fn inner_mut(&mut self) -> &mut L {
&mut self.layer
}
@@ -607,8 +706,8 @@ where
F: layer::Filter<S> + 'static,
L: Layer<S>,
{
- fn on_register_dispatch(&self, collector: &Dispatch) {
- self.layer.on_register_dispatch(collector);
+ fn on_register_dispatch(&self, subscriber: &Dispatch) {
+ self.layer.on_register_dispatch(subscriber);
}
fn on_layer(&mut self, subscriber: &mut S) {
@@ -1091,7 +1190,7 @@ impl FilterState {
}
}
- /// Run a second filtering pass, e.g. for Subscribe::event_enabled.
+ /// Run a second filtering pass, e.g. for Layer::event_enabled.
fn and(&self, filter: FilterId, f: impl FnOnce() -> bool) -> bool {
let map = self.enabled.get();
let enabled = map.is_enabled(filter) && f();
diff --git a/src/fmt/fmt_layer.rs b/src/fmt/fmt_layer.rs
index 1e0923a..d3cb8c1 100644
--- a/src/fmt/fmt_layer.rs
+++ b/src/fmt/fmt_layer.rs
@@ -5,7 +5,9 @@ use crate::{
registry::{self, LookupSpan, SpanRef},
};
use format::{FmtSpan, TimingDisplay};
-use std::{any::TypeId, cell::RefCell, fmt, io, marker::PhantomData, ops::Deref, time::Instant};
+use std::{
+ any::TypeId, cell::RefCell, env, fmt, io, marker::PhantomData, ops::Deref, time::Instant,
+};
use tracing_core::{
field,
span::{Attributes, Current, Id, Record},
@@ -276,6 +278,15 @@ impl<S, N, E, W> Layer<S, N, E, W> {
/// Sets whether or not the formatter emits ANSI terminal escape codes
/// for colors and other text formatting.
///
+ /// When the "ansi" crate feature flag is enabled, ANSI colors are enabled
+ /// by default unless the [`NO_COLOR`] environment variable is set to
+ /// a non-empty value. If the [`NO_COLOR`] environment variable is set to
+ /// any non-empty value, then ANSI colors will be suppressed by default.
+ /// The [`with_ansi`] and [`set_ansi`] methods can be used to forcibly
+ /// enable ANSI colors, overriding any [`NO_COLOR`] environment variable.
+ ///
+ /// [`NO_COLOR`]: https://no-color.org/
+ ///
/// Enabling ANSI escapes (calling `with_ansi(true)`) requires the "ansi"
/// crate feature flag. Calling `with_ansi(true)` without the "ansi"
/// feature flag enabled will panic if debug assertions are enabled, or
@@ -288,6 +299,9 @@ impl<S, N, E, W> Layer<S, N, E, W> {
/// ANSI escape codes can ensure that they are not used, regardless of
/// whether or not other crates in the dependency graph enable the "ansi"
/// feature flag.
+ ///
+ /// [`with_ansi`]: Subscriber::with_ansi
+ /// [`set_ansi`]: Subscriber::set_ansi
pub fn with_ansi(self, ansi: bool) -> Self {
#[cfg(not(feature = "ansi"))]
if ansi {
@@ -311,10 +325,10 @@ impl<S, N, E, W> Layer<S, N, E, W> {
/// By default, `fmt::Layer` will write any `FormatEvent`-internal errors to
/// the writer. These errors are unlikely and will only occur if there is a
/// bug in the `FormatEvent` implementation or its dependencies.
- ///
+ ///
/// If writing to the writer fails, the error message is printed to stderr
/// as a fallback.
- ///
+ ///
/// [`FormatEvent`]: crate::fmt::FormatEvent
pub fn log_internal_errors(self, log_internal_errors: bool) -> Self {
Self {
@@ -677,12 +691,16 @@ impl<S, N, E, W> Layer<S, N, E, W> {
impl<S> Default for Layer<S> {
fn default() -> Self {
+ // only enable ANSI when the feature is enabled, and the NO_COLOR
+ // environment variable is unset or empty.
+ let ansi = cfg!(feature = "ansi") && env::var("NO_COLOR").map_or(true, |v| v.is_empty());
+
Layer {
fmt_fields: format::DefaultFields::default(),
fmt_event: format::Format::default(),
fmt_span: format::FmtSpanConfig::default(),
make_writer: io::stdout,
- is_ansi: cfg!(feature = "ansi"),
+ is_ansi: ansi,
log_internal_errors: false,
_inner: PhantomData,
}
@@ -775,7 +793,7 @@ macro_rules! with_event_from_span {
#[allow(unused)]
let mut iter = fs.iter();
let v = [$(
- (&iter.next().unwrap(), Some(&$value as &dyn field::Value)),
+ (&iter.next().unwrap(), ::core::option::Option::Some(&$value as &dyn field::Value)),
)*];
let vs = fs.value_set(&v);
let $event = Event::new_child_of($id, meta, &vs);
@@ -1288,8 +1306,17 @@ mod test {
let actual = sanitize_timings(make_writer.get_string());
// Only assert the start because the line number and callsite may change.
- let expected = concat!("Unable to format the following event. Name: event ", file!(), ":");
- assert!(actual.as_str().starts_with(expected), "\nactual = {}\nshould start with expected = {}\n", actual, expected);
+ let expected = concat!(
+ "Unable to format the following event. Name: event ",
+ file!(),
+ ":"
+ );
+ assert!(
+ actual.as_str().starts_with(expected),
+ "\nactual = {}\nshould start with expected = {}\n",
+ actual,
+ expected
+ );
}
#[test]
@@ -1491,4 +1518,73 @@ mod test {
actual.as_str()
);
}
+
+ // Because we need to modify an environment variable for these test cases,
+ // we do them all in a single test.
+ #[cfg(feature = "ansi")]
+ #[test]
+ fn layer_no_color() {
+ const NO_COLOR: &str = "NO_COLOR";
+
+ // Restores the previous value of the `NO_COLOR` env variable when
+ // dropped.
+ //
+ // This is done in a `Drop` implementation, rather than just resetting
+ // the value at the end of the test, so that the previous value is
+ // restored even if the test panics.
+ struct RestoreEnvVar(Result<String, env::VarError>);
+ impl Drop for RestoreEnvVar {
+ fn drop(&mut self) {
+ match self.0 {
+ Ok(ref var) => env::set_var(NO_COLOR, var),
+ Err(_) => env::remove_var(NO_COLOR),
+ }
+ }
+ }
+
+ let _saved_no_color = RestoreEnvVar(env::var(NO_COLOR));
+
+ let cases: Vec<(Option<&str>, bool)> = vec![
+ (Some("0"), false), // any non-empty value disables ansi
+ (Some("off"), false), // any non-empty value disables ansi
+ (Some("1"), false),
+ (Some(""), true), // empty value does not disable ansi
+ (None, true),
+ ];
+
+ for (var, ansi) in cases {
+ if let Some(value) = var {
+ env::set_var(NO_COLOR, value);
+ } else {
+ env::remove_var(NO_COLOR);
+ }
+
+ let layer: Layer<()> = fmt::Layer::default();
+ assert_eq!(
+ layer.is_ansi, ansi,
+ "NO_COLOR={:?}; Layer::default().is_ansi should be {}",
+ var, ansi
+ );
+
+ // with_ansi should override any `NO_COLOR` value
+ let layer: Layer<()> = fmt::Layer::default().with_ansi(true);
+ assert!(
+ layer.is_ansi,
+ "NO_COLOR={:?}; Layer::default().with_ansi(true).is_ansi should be true",
+ var
+ );
+
+ // set_ansi should override any `NO_COLOR` value
+ let mut layer: Layer<()> = fmt::Layer::default();
+ layer.set_ansi(true);
+ assert!(
+ layer.is_ansi,
+ "NO_COLOR={:?}; layer.set_ansi(true); layer.is_ansi should be true",
+ var
+ );
+ }
+
+ // dropping `_saved_no_color` will restore the previous value of
+ // `NO_COLOR`.
+ }
}
diff --git a/src/fmt/format/mod.rs b/src/fmt/format/mod.rs
index fa22c78..80612e1 100644
--- a/src/fmt/format/mod.rs
+++ b/src/fmt/format/mod.rs
@@ -326,8 +326,10 @@ pub struct FieldFnVisitor<'a, F> {
/// Marker for [`Format`] that indicates that the compact log format should be used.
///
/// The compact format includes fields from all currently entered spans, after
-/// the event's fields. Span names are listed in order before fields are
-/// displayed.
+/// the event's fields. Span fields are ordered (but not grouped) by
+/// span, and span names are not shown. A more compact representation of the
+/// event's [`Level`] is used, and additional information—such as the event's
+/// target—is disabled by default.
///
/// # Example Output
///
@@ -416,7 +418,19 @@ impl<'writer> Writer<'writer> {
// We may not want to do that if we choose to expose specialized
// constructors instead (e.g. `from_string` that stores whether the string
// is empty...?)
- pub(crate) fn new(writer: &'writer mut impl fmt::Write) -> Self {
+ //(@kaifastromai) I suppose having dedicated constructors may have certain benefits
+ // but I am not privy to the larger direction of tracing/subscriber.
+ /// Create a new [`Writer`] from any type that implements [`fmt::Write`].
+ ///
+ /// The returned `Writer` value may be passed as an argument to methods
+ /// such as [`Format::format_event`]. Since constructing a `Writer`
+ /// mutably borrows the underlying [`fmt::Write`] instance, that value may
+ /// be accessed again once the `Writer` is dropped. For example, if the
+ /// value implementing [`fmt::Write`] is a [`String`], it will contain
+ /// the formatted output of [`Format::format_event`], which may then be
+ /// used for other purposes.
+ #[must_use]
+ pub fn new(writer: &'writer mut impl fmt::Write) -> Self {
Self {
writer: writer as &mut dyn fmt::Write,
is_ansi: false,
@@ -1086,7 +1100,12 @@ where
let mut needs_space = false;
if self.display_target {
- write!(writer, "{}{}", dimmed.paint(meta.target()), dimmed.paint(":"))?;
+ write!(
+ writer,
+ "{}{}",
+ dimmed.paint(meta.target()),
+ dimmed.paint(":")
+ )?;
needs_space = true;
}
diff --git a/src/fmt/mod.rs b/src/fmt/mod.rs
index cfe4704..3762164 100644
--- a/src/fmt/mod.rs
+++ b/src/fmt/mod.rs
@@ -16,7 +16,7 @@
//! tracing-subscriber = "0.3"
//! ```
//!
-//! *Compiler support: [requires `rustc` 1.56+][msrv]*
+//! *Compiler support: [requires `rustc` 1.63+][msrv]*
//!
//! [msrv]: super#supported-rust-versions
//!
@@ -762,7 +762,7 @@ where
/// Sets the subscriber being built to use a JSON formatter.
///
- /// See [`format::Json`][super::fmt::format::Json]
+ /// See [`format::Json`] for details.
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn json(
@@ -783,7 +783,7 @@ where
impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> {
/// Sets the json subscriber being built to flatten event metadata.
///
- /// See [`format::Json`][super::fmt::format::Json]
+ /// See [`format::Json`] for details.
pub fn flatten_event(
self,
flatten_event: bool,
@@ -797,7 +797,7 @@ impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json,
/// Sets whether or not the JSON subscriber being built will include the current span
/// in formatted events.
///
- /// See [`format::Json`][super::fmt::format::Json]
+ /// See [`format::Json`] for details.
pub fn with_current_span(
self,
display_current_span: bool,
@@ -811,7 +811,7 @@ impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json,
/// Sets whether or not the JSON subscriber being built will include a list (from
/// root to leaf) of all currently entered spans in formatted events.
///
- /// See [`format::Json`][super::fmt::format::Json]
+ /// See [`format::Json`] for details.
pub fn with_span_list(
self,
display_span_list: bool,
@@ -1304,6 +1304,9 @@ mod test {
Self { buf }
}
+ // this is currently only used by the JSON formatter tests. if we need
+ // it elsewhere in the future, feel free to remove the `#[cfg]`
+ // attribute!
#[cfg(feature = "json")]
pub(crate) fn buf(&self) -> MutexGuard<'_, Vec<u8>> {
self.buf.lock().unwrap()
diff --git a/src/fmt/time/chrono_crate.rs b/src/fmt/time/chrono_crate.rs
new file mode 100644
index 0000000..1a831ef
--- /dev/null
+++ b/src/fmt/time/chrono_crate.rs
@@ -0,0 +1,177 @@
+use crate::fmt::format::Writer;
+use crate::fmt::time::FormatTime;
+
+use std::sync::Arc;
+
+/// Formats [local time]s and [UTC time]s with `FormatTime` implementations
+/// that use the [`chrono` crate].
+///
+/// [local time]: [`chrono::offset::Local`]
+/// [UTC time]: [`chrono::offset::Utc`]
+/// [`chrono` crate]: [`chrono`]
+
+/// Formats the current [local time] using a [formatter] from the [`chrono`] crate.
+///
+/// [local time]: chrono::Local::now()
+/// [formatter]: chrono::format
+#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
+#[derive(Debug, Clone, Eq, PartialEq, Default)]
+pub struct ChronoLocal {
+ format: Arc<ChronoFmtType>,
+}
+
+impl ChronoLocal {
+ /// Format the time using the [`RFC 3339`] format
+ /// (a subset of [`ISO 8601`]).
+ ///
+ /// [`RFC 3339`]: https://tools.ietf.org/html/rfc3339
+ /// [`ISO 8601`]: https://en.wikipedia.org/wiki/ISO_8601
+ pub fn rfc_3339() -> Self {
+ Self {
+ format: Arc::new(ChronoFmtType::Rfc3339),
+ }
+ }
+
+ /// Format the time using the given format string.
+ ///
+ /// See [`chrono::format::strftime`] for details on the supported syntax.
+ pub fn new(format_string: String) -> Self {
+ Self {
+ format: Arc::new(ChronoFmtType::Custom(format_string)),
+ }
+ }
+}
+
+impl FormatTime for ChronoLocal {
+ fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result {
+ let t = chrono::Local::now();
+ match self.format.as_ref() {
+ ChronoFmtType::Rfc3339 => {
+ use chrono::format::{Fixed, Item};
+ write!(
+ w,
+ "{}",
+ t.format_with_items(core::iter::once(Item::Fixed(Fixed::RFC3339)))
+ )
+ }
+ ChronoFmtType::Custom(fmt) => {
+ write!(w, "{}", t.format(fmt))
+ }
+ }
+ }
+}
+
+/// Formats the current [UTC time] using a [formatter] from the [`chrono`] crate.
+///
+/// [UTC time]: chrono::Utc::now()
+/// [formatter]: chrono::format
+#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
+#[derive(Debug, Clone, Eq, PartialEq, Default)]
+pub struct ChronoUtc {
+ format: Arc<ChronoFmtType>,
+}
+
+impl ChronoUtc {
+ /// Format the time using the [`RFC 3339`] format
+ /// (a subset of [`ISO 8601`]).
+ ///
+ /// [`RFC 3339`]: https://tools.ietf.org/html/rfc3339
+ /// [`ISO 8601`]: https://en.wikipedia.org/wiki/ISO_8601
+ pub fn rfc_3339() -> Self {
+ Self {
+ format: Arc::new(ChronoFmtType::Rfc3339),
+ }
+ }
+
+ /// Format the time using the given format string.
+ ///
+ /// See [`chrono::format::strftime`] for details on the supported syntax.
+ pub fn new(format_string: String) -> Self {
+ Self {
+ format: Arc::new(ChronoFmtType::Custom(format_string)),
+ }
+ }
+}
+
+impl FormatTime for ChronoUtc {
+ fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result {
+ let t = chrono::Utc::now();
+ match self.format.as_ref() {
+ ChronoFmtType::Rfc3339 => w.write_str(&t.to_rfc3339()),
+ ChronoFmtType::Custom(fmt) => w.write_str(&format!("{}", t.format(fmt))),
+ }
+ }
+}
+
+/// The RFC 3339 format is used by default but a custom format string
+/// can be used. See [`chrono::format::strftime`]for details on
+/// the supported syntax.
+///
+/// [`chrono::format::strftime`]: https://docs.rs/chrono/0.4.9/chrono/format/strftime/index.html
+#[derive(Debug, Clone, Eq, PartialEq)]
+enum ChronoFmtType {
+ /// Format according to the RFC 3339 convention.
+ Rfc3339,
+ /// Format according to a custom format string.
+ Custom(String),
+}
+
+impl Default for ChronoFmtType {
+ fn default() -> Self {
+ ChronoFmtType::Rfc3339
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::fmt::format::Writer;
+ use crate::fmt::time::FormatTime;
+
+ use std::sync::Arc;
+
+ use super::ChronoFmtType;
+ use super::ChronoLocal;
+ use super::ChronoUtc;
+
+ #[test]
+ fn test_chrono_format_time_utc_default() {
+ let mut buf = String::new();
+ let mut dst: Writer<'_> = Writer::new(&mut buf);
+ assert!(FormatTime::format_time(&ChronoUtc::default(), &mut dst).is_ok());
+ // e.g. `buf` contains "2023-08-18T19:05:08.662499+00:00"
+ assert!(chrono::DateTime::parse_from_str(&buf, "%FT%H:%M:%S%.6f%z").is_ok());
+ }
+
+ #[test]
+ fn test_chrono_format_time_utc_custom() {
+ let fmt = ChronoUtc {
+ format: Arc::new(ChronoFmtType::Custom("%a %b %e %T %Y".to_owned())),
+ };
+ let mut buf = String::new();
+ let mut dst: Writer<'_> = Writer::new(&mut buf);
+ assert!(FormatTime::format_time(&fmt, &mut dst).is_ok());
+ // e.g. `buf` contains "Wed Aug 23 15:53:23 2023"
+ assert!(chrono::NaiveDateTime::parse_from_str(&buf, "%a %b %e %T %Y").is_ok());
+ }
+
+ #[test]
+ fn test_chrono_format_time_local_default() {
+ let mut buf = String::new();
+ let mut dst: Writer<'_> = Writer::new(&mut buf);
+ assert!(FormatTime::format_time(&ChronoLocal::default(), &mut dst).is_ok());
+ // e.g. `buf` contains "2023-08-18T14:59:08.662499-04:00".
+ assert!(chrono::DateTime::parse_from_str(&buf, "%FT%H:%M:%S%.6f%z").is_ok());
+ }
+
+ #[test]
+ fn test_chrono_format_time_local_custom() {
+ let fmt = ChronoLocal {
+ format: Arc::new(ChronoFmtType::Custom("%a %b %e %T %Y".to_owned())),
+ };
+ let mut buf = String::new();
+ let mut dst: Writer<'_> = Writer::new(&mut buf);
+ assert!(FormatTime::format_time(&fmt, &mut dst).is_ok());
+ // e.g. `buf` contains "Wed Aug 23 15:55:46 2023".
+ assert!(chrono::NaiveDateTime::parse_from_str(&buf, "%a %b %e %T %Y").is_ok());
+ }
+}
diff --git a/src/fmt/time/mod.rs b/src/fmt/time/mod.rs
index 1d1bba2..48f34d1 100644
--- a/src/fmt/time/mod.rs
+++ b/src/fmt/time/mod.rs
@@ -7,6 +7,7 @@ mod datetime;
#[cfg(feature = "time")]
mod time_crate;
+
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
pub use time_crate::UtcTime;
@@ -19,6 +20,18 @@ pub use time_crate::LocalTime;
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
pub use time_crate::OffsetTime;
+/// [`chrono`]-based implementation for [`FormatTime`].
+#[cfg(feature = "chrono")]
+mod chrono_crate;
+
+#[cfg(feature = "chrono")]
+#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
+pub use chrono_crate::ChronoLocal;
+
+#[cfg(feature = "chrono")]
+#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
+pub use chrono_crate::ChronoUtc;
+
/// A type that can measure and format the current time.
///
/// This trait is used by `Format` to include a timestamp with each `Event` when it is logged.
@@ -52,7 +65,7 @@ pub trait FormatTime {
/// # }
/// ```
pub fn time() -> SystemTime {
- SystemTime::default()
+ SystemTime
}
/// Returns a new `Uptime` timestamp provider.
diff --git a/src/fmt/time/time_crate.rs b/src/fmt/time/time_crate.rs
index 60d57fd..4883db4 100644
--- a/src/fmt/time/time_crate.rs
+++ b/src/fmt/time/time_crate.rs
@@ -76,9 +76,9 @@ impl LocalTime<well_known::Rfc3339> {
/// ```
/// use tracing_subscriber::fmt::{self, time};
///
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(time::LocalTime::rfc_3339());
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// [local time]: time::OffsetDateTime::now_local
@@ -130,9 +130,9 @@ impl<F: Formattable> LocalTime<F> {
/// use time::macros::format_description;
///
/// let timer = LocalTime::new(format_description!("[hour]:[minute]:[second]"));
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(timer);
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// Using [`time::format_description::parse`]:
@@ -143,9 +143,9 @@ impl<F: Formattable> LocalTime<F> {
/// let time_format = time::format_description::parse("[hour]:[minute]:[second]")
/// .expect("format string should be valid!");
/// let timer = LocalTime::new(time_format);
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(timer);
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// Using the [`format_description!`] macro requires enabling the `time`
@@ -158,9 +158,9 @@ impl<F: Formattable> LocalTime<F> {
/// use tracing_subscriber::fmt::{self, time::LocalTime};
///
/// let timer = LocalTime::new(time::format_description::well_known::Rfc3339);
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(timer);
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// [local time]: time::OffsetDateTime::now_local()
@@ -207,9 +207,9 @@ impl UtcTime<well_known::Rfc3339> {
/// ```
/// use tracing_subscriber::fmt::{self, time};
///
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(time::UtcTime::rfc_3339());
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// [local time]: time::OffsetDateTime::now_utc
@@ -247,9 +247,9 @@ impl<F: Formattable> UtcTime<F> {
/// use time::macros::format_description;
///
/// let timer = UtcTime::new(format_description!("[hour]:[minute]:[second]"));
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(timer);
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// Using the [`format_description!`] macro requires enabling the `time`
@@ -263,9 +263,9 @@ impl<F: Formattable> UtcTime<F> {
/// let time_format = time::format_description::parse("[hour]:[minute]:[second]")
/// .expect("format string should be valid!");
/// let timer = UtcTime::new(time_format);
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(timer);
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// Using a [well-known format][well-known formats] (this is equivalent to
@@ -275,9 +275,9 @@ impl<F: Formattable> UtcTime<F> {
/// use tracing_subscriber::fmt::{self, time::UtcTime};
///
/// let timer = UtcTime::new(time::format_description::well_known::Rfc3339);
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(timer);
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// [UTC time]: time::OffsetDateTime::now_utc()
@@ -326,9 +326,9 @@ impl OffsetTime<well_known::Rfc3339> {
/// ```
/// use tracing_subscriber::fmt::{self, time};
///
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(time::OffsetTime::local_rfc_3339().expect("could not get local offset!"));
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// Using `OffsetTime` with Tokio:
@@ -398,9 +398,9 @@ impl<F: time::formatting::Formattable> OffsetTime<F> {
///
/// let offset = UtcOffset::current_local_offset().expect("should get local offset!");
/// let timer = OffsetTime::new(offset, format_description!("[hour]:[minute]:[second]"));
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(timer);
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// Using [`time::format_description::parse`]:
@@ -413,9 +413,9 @@ impl<F: time::formatting::Formattable> OffsetTime<F> {
/// let time_format = time::format_description::parse("[hour]:[minute]:[second]")
/// .expect("format string should be valid!");
/// let timer = OffsetTime::new(offset, time_format);
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(timer);
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// Using the [`format_description!`] macro requires enabling the `time`
@@ -430,9 +430,9 @@ impl<F: time::formatting::Formattable> OffsetTime<F> {
///
/// let offset = UtcOffset::current_local_offset().expect("should get local offset!");
/// let timer = OffsetTime::new(offset, time::format_description::well_known::Rfc3339);
- /// let collector = tracing_subscriber::fmt()
+ /// let subscriber = tracing_subscriber::fmt()
/// .with_timer(timer);
- /// # drop(collector);
+ /// # drop(subscriber);
/// ```
///
/// [`time` crate]: time
diff --git a/src/fmt/writer.rs b/src/fmt/writer.rs
index 2b9f9e9..bbc1c4a 100644
--- a/src/fmt/writer.rs
+++ b/src/fmt/writer.rs
@@ -16,7 +16,7 @@ use tracing_core::Metadata;
/// This trait is already implemented for function pointers and
/// immutably-borrowing closures that return an instance of [`io::Write`], such
/// as [`io::stdout`] and [`io::stderr`]. Additionally, it is implemented for
-/// [`std::sync::Mutex`][mutex] when the type inside the mutex implements
+/// [`std::sync::Mutex`] when the type inside the mutex implements
/// [`io::Write`].
///
/// # Examples
@@ -66,7 +66,7 @@ use tracing_core::Metadata;
/// ```
///
/// A single instance of a type implementing [`io::Write`] may be used as a
-/// `MakeWriter` by wrapping it in a [`Mutex`][mutex]. For example, we could
+/// `MakeWriter` by wrapping it in a [`Mutex`]. For example, we could
/// write to a file like so:
///
/// ```
@@ -88,7 +88,6 @@ use tracing_core::Metadata;
/// [`Event`]: tracing_core::event::Event
/// [`io::stdout`]: std::io::stdout()
/// [`io::stderr`]: std::io::stderr()
-/// [mutex]: std::sync::Mutex
/// [`MakeWriter::make_writer_for`]: MakeWriter::make_writer_for
/// [`Metadata`]: tracing_core::Metadata
/// [levels]: tracing_core::Level
@@ -325,7 +324,7 @@ pub trait MakeWriterExt<'a>: MakeWriter<'a> {
/// Wraps `self` with a predicate that takes a span or event's [`Metadata`]
/// and returns a `bool`. The returned [`MakeWriter`]'s
- /// [`MakeWriter::make_writer_for`][mwf] method will check the predicate to
+ /// [`MakeWriter::make_writer_for`] method will check the predicate to
/// determine if a writer should be produced for a given span or event.
///
/// If the predicate returns `false`, the wrapped [`MakeWriter`]'s
@@ -544,7 +543,7 @@ pub struct BoxMakeWriter {
name: &'static str,
}
-/// A [writer] that is one of two types implementing [`io::Write`][writer].
+/// A [writer] that is one of two types implementing [`io::Write`].
///
/// This may be used by [`MakeWriter`] implementations that may conditionally
/// return one of two writers.
diff --git a/src/layer/layered.rs b/src/layer/layered.rs
index f09c58c..e276514 100644
--- a/src/layer/layered.rs
+++ b/src/layer/layered.rs
@@ -470,7 +470,7 @@ where
return Interest::sometimes();
}
- // otherwise, allow the inner subscriber or collector to weigh in.
+ // otherwise, allow the inner subscriber or subscriber to weigh in.
inner
}
diff --git a/src/layer/mod.rs b/src/layer/mod.rs
index bdc1543..296de5e 100644
--- a/src/layer/mod.rs
+++ b/src/layer/mod.rs
@@ -468,6 +468,24 @@
//! function pointer. In addition, when more control is required, the [`Filter`]
//! trait may also be implemented for user-defined types.
//!
+//! //! [`Option<Filter>`] also implements [`Filter`], which allows for an optional
+//! filter. [`None`](Option::None) filters out _nothing_ (that is, allows
+//! everything through). For example:
+//!
+//! ```rust
+//! # use tracing_subscriber::{filter::filter_fn, Layer};
+//! # use tracing_core::{Metadata, subscriber::Subscriber};
+//! # struct MyLayer<S>(std::marker::PhantomData<S>);
+//! # impl<S> MyLayer<S> { fn new() -> Self { Self(std::marker::PhantomData)} }
+//! # impl<S: Subscriber> Layer<S> for MyLayer<S> {}
+//! # fn my_filter(_: &str) -> impl Fn(&Metadata) -> bool { |_| true }
+//! fn setup_tracing<S: Subscriber>(filter_config: Option<&str>) {
+//! let layer = MyLayer::<S>::new()
+//! .with_filter(filter_config.map(|config| filter_fn(my_filter(config))));
+//! //...
+//! }
+//! ```
+//!
//! <pre class="compile_fail" style="white-space:normal;font:inherit;">
//! <strong>Warning</strong>: Currently, the <a href="../struct.Registry.html">
//! <code>Registry</code></a> type defined in this crate is the only root
@@ -732,8 +750,8 @@ where
/// [`WeakDispatch`]: tracing_core::dispatcher::WeakDispatch
/// [upgraded]: tracing_core::dispatcher::WeakDispatch::upgrade
/// [`Subscriber`]: tracing_core::Subscriber
- fn on_register_dispatch(&self, collector: &Dispatch) {
- let _ = collector;
+ fn on_register_dispatch(&self, subscriber: &Dispatch) {
+ let _ = subscriber;
}
/// Performs late initialization when attaching a `Layer` to a
diff --git a/src/lib.rs b/src/lib.rs
index 761e239..21cfe70 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,7 +10,7 @@
//! `tracing-subscriber` is intended for use by both `Subscriber` authors and
//! application authors using `tracing` to instrument their applications.
//!
-//! *Compiler support: [requires `rustc` 1.56+][msrv]*
+//! *Compiler support: [requires `rustc` 1.63+][msrv]*
//!
//! [msrv]: #supported-rust-versions
//!
@@ -53,7 +53,7 @@
//! similar to the [`env_logger` crate]. **Requires "std"**.
//! - `fmt`: Enables the [`fmt`] module, which provides a subscriber
//! implementation for printing formatted representations of trace events.
-//! Enabled by default. **Requires "std"**.
+//! Enabled by default. **Requires "registry" and "std"**.
//! - `ansi`: Enables `fmt` support for ANSI terminal colors. Enabled by
//! default.
//! - `registry`: enables the [`registry`] module. Enabled by default.
@@ -138,7 +138,7 @@
//! ## Supported Rust Versions
//!
//! Tracing is built against the latest stable release. The minimum supported
-//! version is 1.56. The current Tracing version is not guaranteed to build on
+//! version is 1.63. The current Tracing version is not guaranteed to build on
//! Rust versions earlier than the minimum supported version.
//!
//! Tracing follows the same compiler support policies as the rest of the Tokio
diff --git a/src/macros.rs b/src/macros.rs
index 8135113..5b461d0 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -4,7 +4,7 @@ macro_rules! try_lock {
try_lock!($lock, else return)
};
($lock:expr, else $els:expr) => {
- if let Ok(l) = $lock {
+ if let ::core::result::Result::Ok(l) = $lock {
l
} else if std::thread::panicking() {
$els
diff --git a/src/registry/mod.rs b/src/registry/mod.rs
index 38af53e..1617f5c 100644
--- a/src/registry/mod.rs
+++ b/src/registry/mod.rs
@@ -200,11 +200,9 @@ pub trait SpanData<'a> {
/// A reference to [span data] and the associated [registry].
///
-/// This type implements all the same methods as [`SpanData`][span data], and
-/// provides additional methods for querying the registry based on values from
-/// the span.
+/// This type implements all the same methods as [`SpanData`], and provides
+/// additional methods for querying the registry based on values from the span.
///
-/// [span data]: SpanData
/// [registry]: LookupSpan
#[derive(Debug)]
pub struct SpanRef<'a, R: LookupSpan<'a>> {
diff --git a/tests/cached_layer_filters_dont_break_other_layers.rs b/tests/cached_layer_filters_dont_break_other_layers.rs
index 5b40b60..b6d7677 100644
--- a/tests/cached_layer_filters_dont_break_other_layers.rs
+++ b/tests/cached_layer_filters_dont_break_other_layers.rs
@@ -1,7 +1,7 @@
#![cfg(feature = "registry")]
use tracing::Level;
use tracing_mock::{
- event,
+ expect,
layer::{self, MockLayer},
subscriber,
};
@@ -107,20 +107,20 @@ fn filter() -> LevelFilter {
fn unfiltered(name: &str) -> (MockLayer, subscriber::MockHandle) {
layer::named(name)
- .event(event::mock().at_level(Level::TRACE))
- .event(event::mock().at_level(Level::DEBUG))
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::TRACE))
+ .event(expect::event().at_level(Level::DEBUG))
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle()
}
fn filtered(name: &str) -> (MockLayer, subscriber::MockHandle) {
layer::named(name)
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle()
}
diff --git a/tests/env_filter/main.rs b/tests/env_filter/main.rs
index ef984a6..1692181 100644
--- a/tests/env_filter/main.rs
+++ b/tests/env_filter/main.rs
@@ -3,20 +3,21 @@
mod per_layer;
use tracing::{self, subscriber::with_default, Level};
-use tracing_mock::{event, field, layer, span, subscriber};
+use tracing_mock::{expect, layer, span, subscriber};
use tracing_subscriber::{
filter::{EnvFilter, LevelFilter},
prelude::*,
+ Registry,
};
#[test]
fn level_filter_event() {
let filter: EnvFilter = "info".parse().expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -38,18 +39,18 @@ fn same_name_spans() {
.expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
.new_span(
- span::mock()
+ expect::span()
.named("foo")
.at_level(Level::TRACE)
- .with_field(field::mock("bar")),
+ .with_field(expect::field("bar")),
)
.new_span(
- span::mock()
+ expect::span()
.named("foo")
.at_level(Level::TRACE)
- .with_field(field::mock("baz")),
+ .with_field(expect::field("baz")),
)
- .done()
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
with_default(subscriber, || {
@@ -64,12 +65,12 @@ fn same_name_spans() {
fn level_filter_event_with_target() {
let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
- .event(event::mock().at_level(Level::WARN).with_target("stuff"))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::DEBUG).with_target("stuff"))
+ .event(expect::event().at_level(Level::WARN).with_target("stuff"))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR).with_target("stuff"))
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -95,20 +96,20 @@ fn level_filter_event_with_target_and_span_global() {
let cool_span = span::named("cool_span");
let uncool_span = span::named("uncool_span");
- let (subscriber, handle) = subscriber::mock()
+ let (layer, handle) = layer::mock()
.enter(cool_span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
.in_scope(vec![cool_span.clone()]),
)
.exit(cool_span)
.enter(uncool_span.clone())
.exit(uncool_span)
- .done()
+ .only()
.run_with_handle();
- let subscriber = subscriber.with(filter);
+ let subscriber = Registry::default().with(filter).with(layer);
with_default(subscriber, || {
{
@@ -133,12 +134,12 @@ fn not_order_dependent() {
let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
- .event(event::mock().at_level(Level::WARN).with_target("stuff"))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::DEBUG).with_target("stuff"))
+ .event(expect::event().at_level(Level::WARN).with_target("stuff"))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR).with_target("stuff"))
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -167,9 +168,9 @@ fn add_directive_enables_event() {
filter = filter.add_directive("hello=trace".parse().expect("directive should parse"));
let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO).with_target("hello"))
- .event(event::mock().at_level(Level::TRACE).with_target("hello"))
- .done()
+ .event(expect::event().at_level(Level::INFO).with_target("hello"))
+ .event(expect::event().at_level(Level::TRACE).with_target("hello"))
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -187,19 +188,19 @@ fn span_name_filter_is_dynamic() {
.parse()
.expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO))
- .enter(span::named("cool_span"))
- .event(event::mock().at_level(Level::DEBUG))
- .enter(span::named("uncool_span"))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::DEBUG))
- .exit(span::named("uncool_span"))
- .exit(span::named("cool_span"))
- .enter(span::named("uncool_span"))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .exit(span::named("uncool_span"))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .enter(expect::span().named("cool_span"))
+ .event(expect::event().at_level(Level::DEBUG))
+ .enter(expect::span().named("uncool_span"))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::DEBUG))
+ .exit(expect::span().named("uncool_span"))
+ .exit(expect::span().named("cool_span"))
+ .enter(expect::span().named("uncool_span"))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .exit(expect::span().named("uncool_span"))
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -245,10 +246,10 @@ mod per_layer_filter {
fn level_filter_event() {
let filter: EnvFilter = "info".parse().expect("filter should parse");
let (layer, handle) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -271,18 +272,18 @@ mod per_layer_filter {
.expect("filter should parse");
let (layer, handle) = layer::mock()
.new_span(
- span::mock()
+ expect::span()
.named("foo")
.at_level(Level::TRACE)
- .with_field(field::mock("bar")),
+ .with_field(expect::field("bar")),
)
.new_span(
- span::mock()
+ expect::span()
.named("foo")
.at_level(Level::TRACE)
- .with_field(field::mock("baz")),
+ .with_field(expect::field("baz")),
)
- .done()
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -299,12 +300,12 @@ mod per_layer_filter {
fn level_filter_event_with_target() {
let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse");
let (layer, handle) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
- .event(event::mock().at_level(Level::WARN).with_target("stuff"))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::DEBUG).with_target("stuff"))
+ .event(expect::event().at_level(Level::WARN).with_target("stuff"))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR).with_target("stuff"))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -333,12 +334,12 @@ mod per_layer_filter {
let (layer, handle) = layer::mock()
.enter(cool_span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
.in_scope(vec![cool_span.clone()]),
)
.exit(cool_span)
- .done()
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -366,12 +367,12 @@ mod per_layer_filter {
let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse");
let (layer, finished) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
- .event(event::mock().at_level(Level::WARN).with_target("stuff"))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::DEBUG).with_target("stuff"))
+ .event(expect::event().at_level(Level::WARN).with_target("stuff"))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR).with_target("stuff"))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -401,9 +402,9 @@ mod per_layer_filter {
filter = filter.add_directive("hello=trace".parse().expect("directive should parse"));
let (layer, finished) = layer::mock()
- .event(event::mock().at_level(Level::INFO).with_target("hello"))
- .event(event::mock().at_level(Level::TRACE).with_target("hello"))
- .done()
+ .event(expect::event().at_level(Level::INFO).with_target("hello"))
+ .event(expect::event().at_level(Level::TRACE).with_target("hello"))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -424,21 +425,21 @@ mod per_layer_filter {
let cool_span = span::named("cool_span");
let uncool_span = span::named("uncool_span");
let (layer, finished) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::INFO))
.enter(cool_span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
.in_scope(vec![cool_span.clone()]),
)
.enter(uncool_span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::WARN)
.in_scope(vec![uncool_span.clone()]),
)
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
.in_scope(vec![uncool_span.clone()]),
)
@@ -446,17 +447,17 @@ mod per_layer_filter {
.exit(cool_span)
.enter(uncool_span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::WARN)
.in_scope(vec![uncool_span.clone()]),
)
.event(
- event::mock()
+ expect::event()
.at_level(Level::ERROR)
.in_scope(vec![uncool_span.clone()]),
)
.exit(uncool_span)
- .done()
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -497,12 +498,12 @@ mod per_layer_filter {
let (layer, handle) = layer::named("layer1")
.enter(span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
.in_scope(vec![span.clone()]),
)
.exit(span)
- .done()
+ .only()
.run_with_handle();
(layer.with_filter(filter), handle)
};
@@ -513,12 +514,12 @@ mod per_layer_filter {
let (layer, handle) = layer::named("layer2")
.enter(span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::INFO)
.in_scope(vec![span.clone()]),
)
.exit(span)
- .done()
+ .only()
.run_with_handle();
(layer.with_filter(filter), handle)
};
diff --git a/tests/env_filter/per_layer.rs b/tests/env_filter/per_layer.rs
index 4b143b8..229b9ff 100644
--- a/tests/env_filter/per_layer.rs
+++ b/tests/env_filter/per_layer.rs
@@ -2,16 +2,16 @@
//! `Layer` filter).
#![cfg(feature = "registry")]
use super::*;
-use tracing_mock::{event, field, layer, span};
+use tracing_mock::{layer, span};
#[test]
fn level_filter_event() {
let filter: EnvFilter = "info".parse().expect("filter should parse");
let (layer, handle) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -34,18 +34,18 @@ fn same_name_spans() {
.expect("filter should parse");
let (layer, handle) = layer::mock()
.new_span(
- span::mock()
+ expect::span()
.named("foo")
.at_level(Level::TRACE)
- .with_field(field::mock("bar")),
+ .with_field(expect::field("bar")),
)
.new_span(
- span::mock()
+ expect::span()
.named("foo")
.at_level(Level::TRACE)
- .with_field(field::mock("baz")),
+ .with_field(expect::field("baz")),
)
- .done()
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -62,12 +62,12 @@ fn same_name_spans() {
fn level_filter_event_with_target() {
let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse");
let (layer, handle) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
- .event(event::mock().at_level(Level::WARN).with_target("stuff"))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::DEBUG).with_target("stuff"))
+ .event(expect::event().at_level(Level::WARN).with_target("stuff"))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR).with_target("stuff"))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -96,12 +96,12 @@ fn level_filter_event_with_target_and_span() {
let (layer, handle) = layer::mock()
.enter(cool_span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
.in_scope(vec![cool_span.clone()]),
)
.exit(cool_span)
- .done()
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -129,12 +129,12 @@ fn not_order_dependent() {
let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse");
let (layer, finished) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
- .event(event::mock().at_level(Level::WARN).with_target("stuff"))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::DEBUG).with_target("stuff"))
+ .event(expect::event().at_level(Level::WARN).with_target("stuff"))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR).with_target("stuff"))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -164,9 +164,9 @@ fn add_directive_enables_event() {
filter = filter.add_directive("hello=trace".parse().expect("directive should parse"));
let (layer, finished) = layer::mock()
- .event(event::mock().at_level(Level::INFO).with_target("hello"))
- .event(event::mock().at_level(Level::TRACE).with_target("hello"))
- .done()
+ .event(expect::event().at_level(Level::INFO).with_target("hello"))
+ .event(expect::event().at_level(Level::TRACE).with_target("hello"))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -187,21 +187,21 @@ fn span_name_filter_is_dynamic() {
let cool_span = span::named("cool_span");
let uncool_span = span::named("uncool_span");
let (layer, finished) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::INFO))
.enter(cool_span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
.in_scope(vec![cool_span.clone()]),
)
.enter(uncool_span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::WARN)
.in_scope(vec![uncool_span.clone()]),
)
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
.in_scope(vec![uncool_span.clone()]),
)
@@ -209,17 +209,17 @@ fn span_name_filter_is_dynamic() {
.exit(cool_span)
.enter(uncool_span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::WARN)
.in_scope(vec![uncool_span.clone()]),
)
.event(
- event::mock()
+ expect::event()
.at_level(Level::ERROR)
.in_scope(vec![uncool_span.clone()]),
)
.exit(uncool_span)
- .done()
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -260,12 +260,12 @@ fn multiple_dynamic_filters() {
let (layer, handle) = layer::named("layer1")
.enter(span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
.in_scope(vec![span.clone()]),
)
.exit(span)
- .done()
+ .only()
.run_with_handle();
(layer.with_filter(filter), handle)
};
@@ -276,12 +276,12 @@ fn multiple_dynamic_filters() {
let (layer, handle) = layer::named("layer2")
.enter(span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::INFO)
.in_scope(vec![span.clone()]),
)
.exit(span)
- .done()
+ .only()
.run_with_handle();
(layer.with_filter(filter), handle)
};
diff --git a/tests/field_filter.rs b/tests/field_filter.rs
index 385d024..b14aebc 100644
--- a/tests/field_filter.rs
+++ b/tests/field_filter.rs
@@ -10,16 +10,16 @@ fn field_filter_events() {
let filter: EnvFilter = "[{thing}]=debug".parse().expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
.event(
- event::mock()
+ expect::event()
.at_level(Level::INFO)
- .with_fields(field::mock("thing")),
+ .with_fields(expect::field("thing")),
)
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
- .with_fields(field::mock("thing")),
+ .with_fields(expect::field("thing")),
)
- .done()
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -41,23 +41,23 @@ fn field_filter_spans() {
.parse()
.expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
- .enter(span::mock().named("span1"))
+ .enter(expect::span().named("span1"))
.event(
- event::mock()
+ expect::event()
.at_level(Level::INFO)
- .with_fields(field::mock("something")),
+ .with_fields(expect::field("something")),
)
- .exit(span::mock().named("span1"))
- .enter(span::mock().named("span2"))
- .exit(span::mock().named("span2"))
- .enter(span::mock().named("span3"))
+ .exit(expect::span().named("span1"))
+ .enter(expect::span().named("span2"))
+ .exit(expect::span().named("span2"))
+ .enter(expect::span().named("span3"))
.event(
- event::mock()
+ expect::event()
.at_level(Level::DEBUG)
- .with_fields(field::mock("something")),
+ .with_fields(expect::field("something")),
)
- .exit(span::mock().named("span3"))
- .done()
+ .exit(expect::span().named("span3"))
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -84,16 +84,16 @@ fn record_after_created() {
.parse()
.expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
- .enter(span::mock().named("span"))
- .exit(span::mock().named("span"))
+ .enter(expect::span().named("span"))
+ .exit(expect::span().named("span"))
.record(
- span::mock().named("span"),
- field::mock("enabled").with_value(&true),
+ expect::span().named("span"),
+ expect::field("enabled").with_value(&true),
)
- .enter(span::mock().named("span"))
- .event(event::mock().at_level(Level::DEBUG))
- .exit(span::mock().named("span"))
- .done()
+ .enter(expect::span().named("span"))
+ .event(expect::event().at_level(Level::DEBUG))
+ .exit(expect::span().named("span"))
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
diff --git a/tests/filter_log.rs b/tests/filter_log.rs
index 8d57ed6..9cda434 100644
--- a/tests/filter_log.rs
+++ b/tests/filter_log.rs
@@ -36,10 +36,10 @@ fn log_is_enabled() {
.parse()
.expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
// Note: we have to set the global default in order to set the `log` max
diff --git a/tests/hinted_layer_filters_dont_break_other_layers.rs b/tests/hinted_layer_filters_dont_break_other_layers.rs
index 4e5ee4e..a3ad351 100644
--- a/tests/hinted_layer_filters_dont_break_other_layers.rs
+++ b/tests/hinted_layer_filters_dont_break_other_layers.rs
@@ -1,9 +1,9 @@
#![cfg(feature = "registry")]
use tracing::{Level, Metadata, Subscriber};
use tracing_mock::{
- event,
- layer::{self, MockLayer},
- subscriber,
+ expect, layer,
+ layer::MockLayer,
+ subscriber::{self},
};
use tracing_subscriber::{filter::DynFilterFn, layer::Context, prelude::*};
@@ -115,20 +115,20 @@ fn filter<S>() -> DynFilterFn<S> {
fn unfiltered(name: &str) -> (MockLayer, subscriber::MockHandle) {
layer::named(name)
- .event(event::mock().at_level(Level::TRACE))
- .event(event::mock().at_level(Level::DEBUG))
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::TRACE))
+ .event(expect::event().at_level(Level::DEBUG))
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle()
}
fn filtered(name: &str) -> (MockLayer, subscriber::MockHandle) {
layer::named(name)
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle()
}
diff --git a/tests/layer_filter_interests_are_cached.rs b/tests/layer_filter_interests_are_cached.rs
index 67e8ba7..867fdd0 100644
--- a/tests/layer_filter_interests_are_cached.rs
+++ b/tests/layer_filter_interests_are_cached.rs
@@ -4,7 +4,7 @@ use std::{
sync::{Arc, Mutex},
};
use tracing::{Level, Subscriber};
-use tracing_mock::{event, layer};
+use tracing_mock::{expect, layer};
use tracing_subscriber::{filter, prelude::*};
#[test]
@@ -21,9 +21,9 @@ fn layer_filter_interests_are_cached() {
});
let (expect, handle) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let subscriber = tracing_subscriber::registry().with(expect.with_filter(filter));
diff --git a/tests/layer_filters/boxed.rs b/tests/layer_filters/boxed.rs
index b02331a..96566a5 100644
--- a/tests/layer_filters/boxed.rs
+++ b/tests/layer_filters/boxed.rs
@@ -3,7 +3,7 @@ use tracing_mock::layer::MockLayer;
use tracing_subscriber::{filter, prelude::*, Layer};
fn layer() -> (MockLayer, subscriber::MockHandle) {
- layer::mock().done().run_with_handle()
+ layer::mock().only().run_with_handle()
}
fn filter<S>() -> filter::DynFilterFn<S> {
diff --git a/tests/layer_filters/combinators.rs b/tests/layer_filters/combinators.rs
index 6052a2d..c5ea3b5 100644
--- a/tests/layer_filters/combinators.rs
+++ b/tests/layer_filters/combinators.rs
@@ -12,7 +12,7 @@ fn and() {
.at_level(tracing::Level::INFO)
.with_target("interesting_target"),
)
- .done()
+ .only()
.run_with_handle();
// Enables spans and events with targets starting with `interesting_target`:
diff --git a/tests/layer_filters/filter_scopes.rs b/tests/layer_filters/filter_scopes.rs
index d5608a8..02d0007 100644
--- a/tests/layer_filters/filter_scopes.rs
+++ b/tests/layer_filters/filter_scopes.rs
@@ -1,49 +1,49 @@
use super::*;
-use tracing_mock::layer::MockLayer;
+use tracing_mock::{event, expect, layer::MockLayer};
#[test]
fn filters_span_scopes() {
let (debug_layer, debug_handle) = layer::named("debug")
- .enter(span::mock().at_level(Level::DEBUG))
- .enter(span::mock().at_level(Level::INFO))
- .enter(span::mock().at_level(Level::WARN))
- .enter(span::mock().at_level(Level::ERROR))
+ .enter(expect::span().at_level(Level::DEBUG))
+ .enter(expect::span().at_level(Level::INFO))
+ .enter(expect::span().at_level(Level::WARN))
+ .enter(expect::span().at_level(Level::ERROR))
.event(event::msg("hello world").in_scope(vec![
- span::mock().at_level(Level::ERROR),
- span::mock().at_level(Level::WARN),
- span::mock().at_level(Level::INFO),
- span::mock().at_level(Level::DEBUG),
+ expect::span().at_level(Level::ERROR),
+ expect::span().at_level(Level::WARN),
+ expect::span().at_level(Level::INFO),
+ expect::span().at_level(Level::DEBUG),
]))
- .exit(span::mock().at_level(Level::ERROR))
- .exit(span::mock().at_level(Level::WARN))
- .exit(span::mock().at_level(Level::INFO))
- .exit(span::mock().at_level(Level::DEBUG))
- .done()
+ .exit(expect::span().at_level(Level::ERROR))
+ .exit(expect::span().at_level(Level::WARN))
+ .exit(expect::span().at_level(Level::INFO))
+ .exit(expect::span().at_level(Level::DEBUG))
+ .only()
.run_with_handle();
let (info_layer, info_handle) = layer::named("info")
- .enter(span::mock().at_level(Level::INFO))
- .enter(span::mock().at_level(Level::WARN))
- .enter(span::mock().at_level(Level::ERROR))
+ .enter(expect::span().at_level(Level::INFO))
+ .enter(expect::span().at_level(Level::WARN))
+ .enter(expect::span().at_level(Level::ERROR))
.event(event::msg("hello world").in_scope(vec![
- span::mock().at_level(Level::ERROR),
- span::mock().at_level(Level::WARN),
- span::mock().at_level(Level::INFO),
+ expect::span().at_level(Level::ERROR),
+ expect::span().at_level(Level::WARN),
+ expect::span().at_level(Level::INFO),
]))
- .exit(span::mock().at_level(Level::ERROR))
- .exit(span::mock().at_level(Level::WARN))
- .exit(span::mock().at_level(Level::INFO))
- .done()
+ .exit(expect::span().at_level(Level::ERROR))
+ .exit(expect::span().at_level(Level::WARN))
+ .exit(expect::span().at_level(Level::INFO))
+ .only()
.run_with_handle();
let (warn_layer, warn_handle) = layer::named("warn")
- .enter(span::mock().at_level(Level::WARN))
- .enter(span::mock().at_level(Level::ERROR))
+ .enter(expect::span().at_level(Level::WARN))
+ .enter(expect::span().at_level(Level::ERROR))
.event(event::msg("hello world").in_scope(vec![
- span::mock().at_level(Level::ERROR),
- span::mock().at_level(Level::WARN),
+ expect::span().at_level(Level::ERROR),
+ expect::span().at_level(Level::WARN),
]))
- .exit(span::mock().at_level(Level::ERROR))
- .exit(span::mock().at_level(Level::WARN))
- .done()
+ .exit(expect::span().at_level(Level::ERROR))
+ .exit(expect::span().at_level(Level::WARN))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -70,38 +70,38 @@ fn filters_span_scopes() {
fn filters_interleaved_span_scopes() {
fn target_layer(target: &'static str) -> (MockLayer, subscriber::MockHandle) {
layer::named(format!("target_{}", target))
- .enter(span::mock().with_target(target))
- .enter(span::mock().with_target(target))
+ .enter(expect::span().with_target(target))
+ .enter(expect::span().with_target(target))
.event(event::msg("hello world").in_scope(vec![
- span::mock().with_target(target),
- span::mock().with_target(target),
+ expect::span().with_target(target),
+ expect::span().with_target(target),
]))
.event(
event::msg("hello to my target")
.in_scope(vec![
- span::mock().with_target(target),
- span::mock().with_target(target),
+ expect::span().with_target(target),
+ expect::span().with_target(target),
])
.with_target(target),
)
- .exit(span::mock().with_target(target))
- .exit(span::mock().with_target(target))
- .done()
+ .exit(expect::span().with_target(target))
+ .exit(expect::span().with_target(target))
+ .only()
.run_with_handle()
}
let (a_layer, a_handle) = target_layer("a");
let (b_layer, b_handle) = target_layer("b");
let (all_layer, all_handle) = layer::named("all")
- .enter(span::mock().with_target("b"))
- .enter(span::mock().with_target("a"))
+ .enter(expect::span().with_target("b"))
+ .enter(expect::span().with_target("a"))
.event(event::msg("hello world").in_scope(vec![
- span::mock().with_target("a"),
- span::mock().with_target("b"),
+ expect::span().with_target("a"),
+ expect::span().with_target("b"),
]))
- .exit(span::mock().with_target("a"))
- .exit(span::mock().with_target("b"))
- .done()
+ .exit(expect::span().with_target("a"))
+ .exit(expect::span().with_target("b"))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
diff --git a/tests/layer_filters/main.rs b/tests/layer_filters/main.rs
index fed7403..80b929c 100644
--- a/tests/layer_filters/main.rs
+++ b/tests/layer_filters/main.rs
@@ -2,33 +2,34 @@
mod boxed;
mod downcast_raw;
mod filter_scopes;
+mod option;
mod per_event;
mod targets;
mod trees;
mod vec;
use tracing::{level_filters::LevelFilter, Level};
-use tracing_mock::{event, layer, span, subscriber};
+use tracing_mock::{event, expect, layer, subscriber};
use tracing_subscriber::{filter, prelude::*, Layer};
#[test]
fn basic_layer_filters() {
let (trace_layer, trace_handle) = layer::named("trace")
- .event(event::mock().at_level(Level::TRACE))
- .event(event::mock().at_level(Level::DEBUG))
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::TRACE))
+ .event(expect::event().at_level(Level::DEBUG))
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let (debug_layer, debug_handle) = layer::named("debug")
- .event(event::mock().at_level(Level::DEBUG))
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::DEBUG))
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let (info_layer, info_handle) = layer::named("info")
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -47,23 +48,23 @@ fn basic_layer_filters() {
}
#[test]
-fn basic_layer_filters_spans() {
+fn basic_layer_filter_spans() {
let (trace_layer, trace_handle) = layer::named("trace")
- .new_span(span::mock().at_level(Level::TRACE))
- .new_span(span::mock().at_level(Level::DEBUG))
- .new_span(span::mock().at_level(Level::INFO))
- .done()
+ .new_span(expect::span().at_level(Level::TRACE))
+ .new_span(expect::span().at_level(Level::DEBUG))
+ .new_span(expect::span().at_level(Level::INFO))
+ .only()
.run_with_handle();
let (debug_layer, debug_handle) = layer::named("debug")
- .new_span(span::mock().at_level(Level::DEBUG))
- .new_span(span::mock().at_level(Level::INFO))
- .done()
+ .new_span(expect::span().at_level(Level::DEBUG))
+ .new_span(expect::span().at_level(Level::INFO))
+ .only()
.run_with_handle();
let (info_layer, info_handle) = layer::named("info")
- .new_span(span::mock().at_level(Level::INFO))
- .done()
+ .new_span(expect::span().at_level(Level::INFO))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -82,12 +83,12 @@ fn basic_layer_filters_spans() {
}
#[test]
-fn global_filters_layers_still_work() {
+fn global_filters_subscribers_still_work() {
let (expect, handle) = layer::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -107,9 +108,9 @@ fn global_filters_layers_still_work() {
#[test]
fn global_filter_interests_are_cached() {
let (expect, handle) = layer::mock()
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -133,12 +134,12 @@ fn global_filter_interests_are_cached() {
}
#[test]
-fn global_filters_affect_layer_filters() {
+fn global_filters_affect_subscriber_filters() {
let (expect, handle) = layer::named("debug")
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
@@ -160,17 +161,17 @@ fn filter_fn() {
let (all, all_handle) = layer::named("all_targets")
.event(event::msg("hello foo"))
.event(event::msg("hello bar"))
- .done()
+ .only()
.run_with_handle();
let (foo, foo_handle) = layer::named("foo_target")
.event(event::msg("hello foo"))
- .done()
+ .only()
.run_with_handle();
let (bar, bar_handle) = layer::named("bar_target")
.event(event::msg("hello bar"))
- .done()
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
diff --git a/tests/layer_filters/option.rs b/tests/layer_filters/option.rs
new file mode 100644
index 0000000..6eb4c40
--- /dev/null
+++ b/tests/layer_filters/option.rs
@@ -0,0 +1,143 @@
+use super::*;
+use tracing::Subscriber;
+use tracing_subscriber::{
+ filter::{self, LevelFilter},
+ prelude::*,
+ Layer,
+};
+
+fn filter_out_everything<S>() -> filter::DynFilterFn<S> {
+ // Use dynamic filter fn to disable interest caching and max-level hints,
+ // allowing us to put all of these tests in the same file.
+ filter::dynamic_filter_fn(|_, _| false)
+}
+
+#[test]
+fn option_some() {
+ let (layer, handle) = layer::mock().only().run_with_handle();
+ let layer = layer.with_filter(Some(filter_out_everything()));
+
+ let _guard = tracing_subscriber::registry().with(layer).set_default();
+
+ for i in 0..2 {
+ tracing::info!(i);
+ }
+
+ handle.assert_finished();
+}
+
+#[test]
+fn option_none() {
+ let (layer, handle) = layer::mock()
+ .event(expect::event())
+ .event(expect::event())
+ .only()
+ .run_with_handle();
+ let layer = layer.with_filter(None::<filter::DynFilterFn<_>>);
+
+ let _guard = tracing_subscriber::registry().with(layer).set_default();
+
+ for i in 0..2 {
+ tracing::info!(i);
+ }
+
+ handle.assert_finished();
+}
+
+#[test]
+fn option_mixed() {
+ let (layer, handle) = layer::mock()
+ .event(expect::event())
+ .only()
+ .run_with_handle();
+ let layer = layer
+ .with_filter(filter::dynamic_filter_fn(|meta, _ctx| {
+ meta.target() == "interesting"
+ }))
+ .with_filter(None::<filter::DynFilterFn<_>>);
+
+ let _guard = tracing_subscriber::registry().with(layer).set_default();
+
+ tracing::info!(target: "interesting", x="foo");
+ tracing::info!(target: "boring", x="bar");
+
+ handle.assert_finished();
+}
+
+/// The lack of a max level hint from a `None` filter should result in no max
+/// level hint when combined with other filters/layer.
+#[test]
+fn none_max_level_hint() {
+ let (layer_some, handle_none) = layer::mock()
+ .event(expect::event())
+ .event(expect::event())
+ .only()
+ .run_with_handle();
+ let subscribe_none = layer_some.with_filter(None::<filter::DynFilterFn<_>>);
+ assert!(subscribe_none.max_level_hint().is_none());
+
+ let (layer_filter_fn, handle_filter_fn) = layer::mock()
+ .event(expect::event())
+ .only()
+ .run_with_handle();
+ let max_level = Level::INFO;
+ let layer_filter_fn = layer_filter_fn.with_filter(
+ filter::dynamic_filter_fn(move |meta, _| return meta.level() <= &max_level)
+ .with_max_level_hint(max_level),
+ );
+ assert_eq!(layer_filter_fn.max_level_hint(), Some(LevelFilter::INFO));
+
+ let subscriber = tracing_subscriber::registry()
+ .with(subscribe_none)
+ .with(layer_filter_fn);
+ // The absence of a hint from the `None` filter upgrades the `INFO` hint
+ // from the filter fn layer.
+ assert!(subscriber.max_level_hint().is_none());
+
+ let _guard = subscriber.set_default();
+ tracing::info!(target: "interesting", x="foo");
+ tracing::debug!(target: "sometimes_interesting", x="bar");
+
+ handle_none.assert_finished();
+ handle_filter_fn.assert_finished();
+}
+
+/// The max level hint from inside a `Some(filter)` filter should be propagated
+/// and combined with other filters/layers.
+#[test]
+fn some_max_level_hint() {
+ let (layer_some, handle_some) = layer::mock()
+ .event(expect::event())
+ .event(expect::event())
+ .only()
+ .run_with_handle();
+ let layer_some = layer_some.with_filter(Some(
+ filter::dynamic_filter_fn(move |meta, _| return meta.level() <= &Level::DEBUG)
+ .with_max_level_hint(Level::DEBUG),
+ ));
+ assert_eq!(layer_some.max_level_hint(), Some(LevelFilter::DEBUG));
+
+ let (layer_filter_fn, handle_filter_fn) = layer::mock()
+ .event(expect::event())
+ .only()
+ .run_with_handle();
+ let layer_filter_fn = layer_filter_fn.with_filter(
+ filter::dynamic_filter_fn(move |meta, _| return meta.level() <= &Level::INFO)
+ .with_max_level_hint(Level::INFO),
+ );
+ assert_eq!(layer_filter_fn.max_level_hint(), Some(LevelFilter::INFO));
+
+ let subscriber = tracing_subscriber::registry()
+ .with(layer_some)
+ .with(layer_filter_fn);
+ // The `DEBUG` hint from the `Some` filter upgrades the `INFO` hint from the
+ // filter fn layer.
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));
+
+ let _guard = subscriber.set_default();
+ tracing::info!(target: "interesting", x="foo");
+ tracing::debug!(target: "sometimes_interesting", x="bar");
+
+ handle_some.assert_finished();
+ handle_filter_fn.assert_finished();
+}
diff --git a/tests/layer_filters/per_event.rs b/tests/layer_filters/per_event.rs
index 3a28d94..897c9f2 100644
--- a/tests/layer_filters/per_event.rs
+++ b/tests/layer_filters/per_event.rs
@@ -1,5 +1,5 @@
use tracing::Level;
-use tracing_mock::{event, layer};
+use tracing_mock::{expect, layer};
use tracing_subscriber::{field::Visit, layer::Filter, prelude::*};
struct FilterEvent;
@@ -40,11 +40,11 @@ impl<S> Filter<S> for FilterEvent {
}
#[test]
-fn per_subscriber_event_field_filtering() {
+fn per_layer_event_field_filtering() {
let (expect, handle) = layer::mock()
- .event(event::mock().at_level(Level::TRACE))
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::TRACE))
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let _subscriber = tracing_subscriber::registry()
diff --git a/tests/layer_filters/targets.rs b/tests/layer_filters/targets.rs
index c813304..19bcff1 100644
--- a/tests/layer_filters/targets.rs
+++ b/tests/layer_filters/targets.rs
@@ -1,4 +1,5 @@
use super::*;
+use tracing_mock::event;
use tracing_subscriber::{
filter::{filter_fn, Targets},
prelude::*,
@@ -39,7 +40,7 @@ fn inner_layer_short_circuits() {
let (layer, handle) = layer::mock()
.event(event::msg("hello world"))
- .done()
+ .only()
.run_with_handle();
let filter = Targets::new().with_target("magic_target", LevelFilter::DEBUG);
diff --git a/tests/layer_filters/trees.rs b/tests/layer_filters/trees.rs
index 0283012..a0dbbbe 100644
--- a/tests/layer_filters/trees.rs
+++ b/tests/layer_filters/trees.rs
@@ -1,37 +1,49 @@
use super::*;
-use tracing_mock::layer::MockLayer;
+use tracing_mock::{event, expect, layer::MockLayer};
#[test]
fn basic_trees() {
let (with_target, with_target_handle) = layer::named("info_with_target")
- .event(event::mock().at_level(Level::INFO).with_target("my_target"))
- .done()
+ .event(
+ expect::event()
+ .at_level(Level::INFO)
+ .with_target("my_target"),
+ )
+ .only()
.run_with_handle();
let (info, info_handle) = layer::named("info")
.event(
- event::mock()
+ expect::event()
.at_level(Level::INFO)
.with_target(module_path!()),
)
- .event(event::mock().at_level(Level::INFO).with_target("my_target"))
- .done()
+ .event(
+ expect::event()
+ .at_level(Level::INFO)
+ .with_target("my_target"),
+ )
+ .only()
.run_with_handle();
let (all, all_handle) = layer::named("all")
.event(
- event::mock()
+ expect::event()
.at_level(Level::INFO)
.with_target(module_path!()),
)
- .event(event::mock().at_level(Level::TRACE))
- .event(event::mock().at_level(Level::INFO).with_target("my_target"))
+ .event(expect::event().at_level(Level::TRACE))
+ .event(
+ expect::event()
+ .at_level(Level::INFO)
+ .with_target("my_target"),
+ )
.event(
- event::mock()
+ expect::event()
.at_level(Level::TRACE)
.with_target("my_target"),
)
- .done()
+ .only()
.run_with_handle();
let info_tree = info
@@ -57,41 +69,40 @@ fn basic_trees() {
fn filter_span_scopes() {
fn target_layer(target: &'static str) -> (MockLayer, subscriber::MockHandle) {
layer::named(format!("target_{}", target))
- .enter(span::mock().with_target(target).at_level(Level::INFO))
- .event(
- event::msg("hello world")
- .in_scope(vec![span::mock().with_target(target).at_level(Level::INFO)]),
- )
- .exit(span::mock().with_target(target).at_level(Level::INFO))
- .done()
+ .enter(expect::span().with_target(target).at_level(Level::INFO))
+ .event(event::msg("hello world").in_scope(vec![
+ expect::span().with_target(target).at_level(Level::INFO),
+ ]))
+ .exit(expect::span().with_target(target).at_level(Level::INFO))
+ .only()
.run_with_handle()
}
let (a_layer, a_handle) = target_layer("a");
let (b_layer, b_handle) = target_layer("b");
let (info_layer, info_handle) = layer::named("info")
- .enter(span::mock().with_target("b").at_level(Level::INFO))
- .enter(span::mock().with_target("a").at_level(Level::INFO))
+ .enter(expect::span().with_target("b").at_level(Level::INFO))
+ .enter(expect::span().with_target("a").at_level(Level::INFO))
.event(event::msg("hello world").in_scope(vec![
- span::mock().with_target("a").at_level(Level::INFO),
- span::mock().with_target("b").at_level(Level::INFO),
+ expect::span().with_target("a").at_level(Level::INFO),
+ expect::span().with_target("b").at_level(Level::INFO),
]))
- .exit(span::mock().with_target("a").at_level(Level::INFO))
- .exit(span::mock().with_target("b").at_level(Level::INFO))
- .done()
+ .exit(expect::span().with_target("a").at_level(Level::INFO))
+ .exit(expect::span().with_target("b").at_level(Level::INFO))
+ .only()
.run_with_handle();
let full_scope = vec![
- span::mock().with_target("b").at_level(Level::TRACE),
- span::mock().with_target("a").at_level(Level::INFO),
- span::mock().with_target("b").at_level(Level::INFO),
- span::mock().with_target("a").at_level(Level::TRACE),
+ expect::span().with_target("b").at_level(Level::TRACE),
+ expect::span().with_target("a").at_level(Level::INFO),
+ expect::span().with_target("b").at_level(Level::INFO),
+ expect::span().with_target("a").at_level(Level::TRACE),
];
let (all_layer, all_handle) = layer::named("all")
- .enter(span::mock().with_target("a").at_level(Level::TRACE))
- .enter(span::mock().with_target("b").at_level(Level::INFO))
- .enter(span::mock().with_target("a").at_level(Level::INFO))
- .enter(span::mock().with_target("b").at_level(Level::TRACE))
+ .enter(expect::span().with_target("a").at_level(Level::TRACE))
+ .enter(expect::span().with_target("b").at_level(Level::INFO))
+ .enter(expect::span().with_target("a").at_level(Level::INFO))
+ .enter(expect::span().with_target("b").at_level(Level::TRACE))
.event(event::msg("hello world").in_scope(full_scope.clone()))
.event(
event::msg("hello to my target")
@@ -103,11 +114,11 @@ fn filter_span_scopes() {
.with_target("b")
.in_scope(full_scope),
)
- .exit(span::mock().with_target("b").at_level(Level::TRACE))
- .exit(span::mock().with_target("a").at_level(Level::INFO))
- .exit(span::mock().with_target("b").at_level(Level::INFO))
- .exit(span::mock().with_target("a").at_level(Level::TRACE))
- .done()
+ .exit(expect::span().with_target("b").at_level(Level::TRACE))
+ .exit(expect::span().with_target("a").at_level(Level::INFO))
+ .exit(expect::span().with_target("b").at_level(Level::INFO))
+ .exit(expect::span().with_target("a").at_level(Level::TRACE))
+ .only()
.run_with_handle();
let a_layer = a_layer.with_filter(filter::filter_fn(|meta| {
diff --git a/tests/layer_filters/vec.rs b/tests/layer_filters/vec.rs
index dbe3674..42aa308 100644
--- a/tests/layer_filters/vec.rs
+++ b/tests/layer_filters/vec.rs
@@ -1,27 +1,27 @@
use super::*;
use tracing::Subscriber;
-use tracing_mock::layer::{self, MockLayer};
+use tracing_mock::{expect, layer::MockLayer};
#[test]
fn with_filters_unboxed() {
let (trace_layer, trace_handle) = layer::named("trace")
- .event(event::mock().at_level(Level::TRACE))
- .event(event::mock().at_level(Level::DEBUG))
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::TRACE))
+ .event(expect::event().at_level(Level::DEBUG))
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let trace_layer = trace_layer.with_filter(LevelFilter::TRACE);
let (debug_layer, debug_handle) = layer::named("debug")
- .event(event::mock().at_level(Level::DEBUG))
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::DEBUG))
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let debug_layer = debug_layer.with_filter(LevelFilter::DEBUG);
let (info_layer, info_handle) = layer::named("info")
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let info_layer = info_layer.with_filter(LevelFilter::INFO);
@@ -41,23 +41,23 @@ fn with_filters_unboxed() {
#[test]
fn with_filters_boxed() {
let (unfiltered_layer, unfiltered_handle) = layer::named("unfiltered")
- .event(event::mock().at_level(Level::TRACE))
- .event(event::mock().at_level(Level::DEBUG))
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::TRACE))
+ .event(expect::event().at_level(Level::DEBUG))
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let unfiltered_layer = unfiltered_layer.boxed();
let (debug_layer, debug_handle) = layer::named("debug")
- .event(event::mock().at_level(Level::DEBUG))
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::DEBUG))
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let debug_layer = debug_layer.with_filter(LevelFilter::DEBUG).boxed();
let (target_layer, target_handle) = layer::named("target")
- .event(event::mock().at_level(Level::INFO))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .only()
.run_with_handle();
let target_layer = target_layer
.with_filter(filter::filter_fn(|meta| meta.target() == "my_target"))
diff --git a/tests/multiple_layer_filter_interests_cached.rs b/tests/multiple_layer_filter_interests_cached.rs
index 13e1a94..553c537 100644
--- a/tests/multiple_layer_filter_interests_cached.rs
+++ b/tests/multiple_layer_filter_interests_cached.rs
@@ -4,7 +4,7 @@ use std::{
sync::{Arc, Mutex},
};
use tracing::{Level, Subscriber};
-use tracing_mock::{event, layer};
+use tracing_mock::{expect, layer};
use tracing_subscriber::{filter, prelude::*};
#[test]
@@ -23,13 +23,13 @@ fn multiple_layer_filter_interests_are_cached() {
let seen_info = seen_info2;
let (info_layer, info_handle) = layer::named("info")
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let info_layer = info_layer.with_filter(filter);
@@ -47,11 +47,11 @@ fn multiple_layer_filter_interests_are_cached() {
let seen_warn = seen_warn2;
let (warn_layer, warn_handle) = layer::named("warn")
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let warn_layer = warn_layer.with_filter(filter);
diff --git a/tests/option_filter_interest_caching.rs b/tests/option_filter_interest_caching.rs
new file mode 100644
index 0000000..609007c
--- /dev/null
+++ b/tests/option_filter_interest_caching.rs
@@ -0,0 +1,53 @@
+// A separate test crate for `Option<Filter>` for isolation from other tests
+// that may influence the interest cache.
+
+use std::sync::{
+ atomic::{AtomicUsize, Ordering},
+ Arc,
+};
+use tracing_mock::{expect, layer};
+use tracing_subscriber::{filter, prelude::*, Layer};
+
+/// A `None` filter should always be interested in events, and it should not
+/// needlessly degrade the caching of other filters.
+#[test]
+fn none_interest_cache() {
+ let (layer_none, handle_none) = layer::mock()
+ .event(expect::event())
+ .event(expect::event())
+ .only()
+ .run_with_handle();
+ let layer_none = layer_none.with_filter(None::<filter::DynFilterFn<_>>);
+
+ let times_filtered = Arc::new(AtomicUsize::new(0));
+ let (layer_filter_fn, handle_filter_fn) = layer::mock()
+ .event(expect::event())
+ .event(expect::event())
+ .only()
+ .run_with_handle();
+ let layer_filter_fn = layer_filter_fn.with_filter(filter::filter_fn({
+ let times_filtered = Arc::clone(&times_filtered);
+ move |_| {
+ times_filtered.fetch_add(1, Ordering::Relaxed);
+ true
+ }
+ }));
+
+ let subscriber = tracing_subscriber::registry()
+ .with(layer_none)
+ .with(layer_filter_fn);
+
+ let _guard = subscriber.set_default();
+ for _ in 0..2 {
+ tracing::debug!(target: "always_interesting", x="bar");
+ }
+
+ // The `None` filter is unchanging and performs no filtering, so it should
+ // be cacheable and always be interested in events. The filter fn is a
+ // non-dynamic filter fn, which means the result can be cached per callsite.
+ // The filter fn should only need to be called once, and the `Option` filter
+ // should not interfere in the caching of that result.
+ assert_eq!(times_filtered.load(Ordering::Relaxed), 1);
+ handle_none.assert_finished();
+ handle_filter_fn.assert_finished();
+}
diff --git a/tests/same_len_filters.rs b/tests/same_len_filters.rs
index 879e578..ac0b908 100644
--- a/tests/same_len_filters.rs
+++ b/tests/same_len_filters.rs
@@ -10,9 +10,9 @@ use tracing_subscriber::{filter::EnvFilter, prelude::*};
fn same_length_targets() {
let filter: EnvFilter = "foo=trace,bar=trace".parse().expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::TRACE))
- .event(event::mock().at_level(Level::TRACE))
- .done()
+ .event(expect::event().at_level(Level::TRACE))
+ .event(expect::event().at_level(Level::TRACE))
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -31,16 +31,16 @@ fn same_num_fields_event() {
.expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
.event(
- event::mock()
+ expect::event()
.at_level(Level::TRACE)
- .with_fields(field::mock("foo")),
+ .with_fields(expect::field("foo")),
)
.event(
- event::mock()
+ expect::event()
.at_level(Level::TRACE)
- .with_fields(field::mock("bar")),
+ .with_fields(expect::field("bar")),
)
- .done()
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
with_default(subscriber, || {
@@ -58,18 +58,18 @@ fn same_num_fields_and_name_len() {
.expect("filter should parse");
let (subscriber, finished) = subscriber::mock()
.new_span(
- span::mock()
+ expect::span()
.named("foo")
.at_level(Level::TRACE)
- .with_field(field::mock("bar")),
+ .with_field(expect::field("bar")),
)
.new_span(
- span::mock()
+ expect::span()
.named("baz")
.at_level(Level::TRACE)
- .with_field(field::mock("boz")),
+ .with_field(expect::field("boz")),
)
- .done()
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
with_default(subscriber, || {
diff --git a/tests/unhinted_layer_filters_dont_break_other_layers.rs b/tests/unhinted_layer_filters_dont_break_other_layers.rs
index d8b3834..a0f3b51 100644
--- a/tests/unhinted_layer_filters_dont_break_other_layers.rs
+++ b/tests/unhinted_layer_filters_dont_break_other_layers.rs
@@ -1,7 +1,7 @@
#![cfg(feature = "registry")]
use tracing::Level;
use tracing_mock::{
- event,
+ expect,
layer::{self, MockLayer},
subscriber,
};
@@ -107,20 +107,20 @@ fn filter<S>() -> DynFilterFn<S> {
fn unfiltered(name: &str) -> (MockLayer, subscriber::MockHandle) {
layer::named(name)
- .event(event::mock().at_level(Level::TRACE))
- .event(event::mock().at_level(Level::DEBUG))
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::TRACE))
+ .event(expect::event().at_level(Level::DEBUG))
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle()
}
fn filtered(name: &str) -> (MockLayer, subscriber::MockHandle) {
layer::named(name)
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle()
}
diff --git a/tests/utils.rs b/tests/utils.rs
index e95868d..9a8eb30 100644
--- a/tests/utils.rs
+++ b/tests/utils.rs
@@ -7,11 +7,11 @@ use tracing_subscriber::prelude::*;
fn init_ext_works() {
let (subscriber, finished) = subscriber::mock()
.event(
- event::mock()
+ expect::event()
.at_level(tracing::Level::INFO)
.with_target("init_works"),
)
- .done()
+ .only()
.run_with_handle();
let _guard = subscriber.set_default();
diff --git a/tests/vec_subscriber_filter_interests_cached.rs b/tests/vec_subscriber_filter_interests_cached.rs
index 1bfb4a0..e80cfa0 100644
--- a/tests/vec_subscriber_filter_interests_cached.rs
+++ b/tests/vec_subscriber_filter_interests_cached.rs
@@ -4,10 +4,7 @@ use std::{
sync::{Arc, Mutex},
};
use tracing::{Level, Subscriber};
-use tracing_mock::{
- event,
- layer::{self, MockLayer},
-};
+use tracing_mock::{layer::MockLayer, *};
use tracing_subscriber::{filter, prelude::*};
#[test]
@@ -26,23 +23,23 @@ fn vec_layer_filter_interests_are_cached() {
// This layer will return Interest::always for INFO and lower.
let (info_layer, info_handle) = layer::named("info")
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::INFO))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let (info_layer, seen_info) = mk_filtered(Level::INFO, info_layer);
// This layer will return Interest::always for WARN and lower.
let (warn_layer, warn_handle) = layer::named("warn")
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::WARN))
+ .event(expect::event().at_level(Level::ERROR))
+ .only()
.run_with_handle();
let (warn_layer, seen_warn) = mk_filtered(Level::WARN, warn_layer);