From 4f9fe856a25ab29345b90e7725509e9ee38a37be Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:41 +0200 Subject: Adding upstream version 1.69.0+dfsg1. Signed-off-by: Daniel Baumann --- .../src/filter/directive.rs | 424 ----------- .../src/filter/env/directive.rs | 846 --------------------- .../src/filter/env/field.rs | 416 ---------- .../tracing-subscriber-0.3.3/src/filter/env/mod.rs | 738 ------------------ .../src/filter/filter_fn.rs | 749 ------------------ .../src/filter/layer_filters.rs | 830 -------------------- .../tracing-subscriber-0.3.3/src/filter/level.rs | 27 - vendor/tracing-subscriber-0.3.3/src/filter/mod.rs | 66 -- .../tracing-subscriber-0.3.3/src/filter/targets.rs | 681 ----------------- 9 files changed, 4777 deletions(-) delete mode 100644 vendor/tracing-subscriber-0.3.3/src/filter/directive.rs delete mode 100644 vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs delete mode 100644 vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs delete mode 100644 vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs delete mode 100644 vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs delete mode 100644 vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs delete mode 100644 vendor/tracing-subscriber-0.3.3/src/filter/level.rs delete mode 100644 vendor/tracing-subscriber-0.3.3/src/filter/mod.rs delete mode 100644 vendor/tracing-subscriber-0.3.3/src/filter/targets.rs (limited to 'vendor/tracing-subscriber-0.3.3/src/filter') diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs b/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs deleted file mode 100644 index dd6b063c4..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs +++ /dev/null @@ -1,424 +0,0 @@ -use crate::filter::level::{self, LevelFilter}; -#[cfg(not(feature = "smallvec"))] -use alloc::vec; -#[cfg(not(feature = "std"))] -use alloc::{string::String, vec::Vec}; - -use core::{cmp::Ordering, fmt, iter::FromIterator, slice, str::FromStr}; -use tracing_core::Metadata; -/// Indicates that a string could not be parsed as a filtering directive. -#[derive(Debug)] -pub struct ParseError { - kind: ParseErrorKind, -} - -/// A directive which will statically enable or disable a given callsite. -/// -/// Unlike a dynamic directive, this can be cached by the callsite. -#[derive(Debug, PartialEq, Eq, Clone)] -pub(crate) struct StaticDirective { - pub(in crate::filter) target: Option, - pub(in crate::filter) field_names: Vec, - pub(in crate::filter) level: LevelFilter, -} - -#[cfg(feature = "smallvec")] -pub(crate) type FilterVec = smallvec::SmallVec<[T; 8]>; -#[cfg(not(feature = "smallvec"))] -pub(crate) type FilterVec = Vec; - -#[derive(Debug, PartialEq, Clone)] -pub(in crate::filter) struct DirectiveSet { - directives: FilterVec, - pub(in crate::filter) max_level: LevelFilter, -} - -pub(in crate::filter) trait Match { - fn cares_about(&self, meta: &Metadata<'_>) -> bool; - fn level(&self) -> &LevelFilter; -} - -#[derive(Debug)] -enum ParseErrorKind { - #[cfg(feature = "std")] - Field(Box), - Level(level::ParseError), - Other(Option<&'static str>), -} - -// === impl DirectiveSet === - -impl DirectiveSet { - #[cfg(feature = "env-filter")] - pub(crate) fn is_empty(&self) -> bool { - self.directives.is_empty() - } - - pub(crate) fn iter(&self) -> slice::Iter<'_, T> { - self.directives.iter() - } -} - -impl Default for DirectiveSet { - fn default() -> Self { - Self { - directives: FilterVec::new(), - max_level: LevelFilter::OFF, - } - } -} - -impl DirectiveSet { - pub(crate) fn directives(&self) -> impl Iterator { - self.directives.iter() - } - - pub(crate) fn directives_for<'a>( - &'a self, - metadata: &'a Metadata<'a>, - ) -> impl Iterator + 'a { - self.directives().filter(move |d| d.cares_about(metadata)) - } - - pub(crate) fn add(&mut self, directive: T) { - // does this directive enable a more verbose level than the current - // max? if so, update the max level. - let level = *directive.level(); - if level > self.max_level { - self.max_level = level; - } - // insert the directive into the vec of directives, ordered by - // specificity (length of target + number of field filters). this - // ensures that, when finding a directive to match a span or event, we - // search the directive set in most specific first order. - match self.directives.binary_search(&directive) { - Ok(i) => self.directives[i] = directive, - Err(i) => self.directives.insert(i, directive), - } - } - - #[cfg(test)] - pub(in crate::filter) fn into_vec(self) -> FilterVec { - self.directives - } -} - -impl FromIterator for DirectiveSet { - fn from_iter>(iter: I) -> Self { - let mut this = Self::default(); - this.extend(iter); - this - } -} - -impl Extend for DirectiveSet { - fn extend>(&mut self, iter: I) { - for directive in iter.into_iter() { - self.add(directive); - } - } -} - -impl IntoIterator for DirectiveSet { - type Item = T; - - #[cfg(feature = "smallvec")] - type IntoIter = smallvec::IntoIter<[T; 8]>; - #[cfg(not(feature = "smallvec"))] - type IntoIter = vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.directives.into_iter() - } -} - -// === impl Statics === - -impl DirectiveSet { - pub(crate) fn enabled(&self, meta: &Metadata<'_>) -> bool { - let level = meta.level(); - match self.directives_for(meta).next() { - Some(d) => d.level >= *level, - None => false, - } - } -} - -// === impl StaticDirective === - -impl StaticDirective { - pub(in crate::filter) fn new( - target: Option, - field_names: Vec, - level: LevelFilter, - ) -> Self { - Self { - target, - field_names, - level, - } - } -} - -impl Ord for StaticDirective { - fn cmp(&self, other: &StaticDirective) -> Ordering { - // We attempt to order directives by how "specific" they are. This - // ensures that we try the most specific directives first when - // attempting to match a piece of metadata. - - // First, we compare based on whether a target is specified, and the - // lengths of those targets if both have targets. - let ordering = self - .target - .as_ref() - .map(String::len) - .cmp(&other.target.as_ref().map(String::len)) - // Then we compare how many field names are matched by each directive. - .then_with(|| self.field_names.len().cmp(&other.field_names.len())) - // Finally, we fall back to lexicographical ordering if the directives are - // equally specific. Although this is no longer semantically important, - // we need to define a total ordering to determine the directive's place - // in the BTreeMap. - .then_with(|| { - self.target - .cmp(&other.target) - .then_with(|| self.field_names[..].cmp(&other.field_names[..])) - }) - .reverse(); - - #[cfg(debug_assertions)] - { - if ordering == Ordering::Equal { - debug_assert_eq!( - self.target, other.target, - "invariant violated: Ordering::Equal must imply a.target == b.target" - ); - debug_assert_eq!( - self.field_names, other.field_names, - "invariant violated: Ordering::Equal must imply a.field_names == b.field_names" - ); - } - } - - ordering - } -} - -impl PartialOrd for StaticDirective { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Match for StaticDirective { - fn cares_about(&self, meta: &Metadata<'_>) -> bool { - // Does this directive have a target filter, and does it match the - // metadata's target? - if let Some(ref target) = self.target { - if !meta.target().starts_with(&target[..]) { - return false; - } - } - - if meta.is_event() && !self.field_names.is_empty() { - let fields = meta.fields(); - for name in &self.field_names { - if fields.field(name).is_none() { - return false; - } - } - } - - true - } - - fn level(&self) -> &LevelFilter { - &self.level - } -} - -impl Default for StaticDirective { - fn default() -> Self { - StaticDirective { - target: None, - field_names: Vec::new(), - level: LevelFilter::ERROR, - } - } -} - -impl fmt::Display for StaticDirective { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut wrote_any = false; - if let Some(ref target) = self.target { - fmt::Display::fmt(target, f)?; - wrote_any = true; - } - - if !self.field_names.is_empty() { - f.write_str("[")?; - - let mut fields = self.field_names.iter(); - if let Some(field) = fields.next() { - write!(f, "{{{}", field)?; - for field in fields { - write!(f, ",{}", field)?; - } - f.write_str("}")?; - } - - f.write_str("]")?; - wrote_any = true; - } - - if wrote_any { - f.write_str("=")?; - } - - fmt::Display::fmt(&self.level, f) - } -} - -impl FromStr for StaticDirective { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - // This method parses a filtering directive in one of the following - // forms: - // - // * `foo=trace` (TARGET=LEVEL) - // * `foo[{bar,baz}]=info` (TARGET[{FIELD,+}]=LEVEL) - // * `trace` (bare LEVEL) - // * `foo` (bare TARGET) - let mut split = s.split('='); - let part0 = split - .next() - .ok_or_else(|| ParseError::msg("string must not be empty"))?; - - // Directive includes an `=`: - // * `foo=trace` - // * `foo[{bar}]=trace` - // * `foo[{bar,baz}]=trace` - if let Some(part1) = split.next() { - if split.next().is_some() { - return Err(ParseError::msg( - "too many '=' in filter directive, expected 0 or 1", - )); - } - - let mut split = part0.split("[{"); - let target = split.next().map(String::from); - let mut field_names = Vec::new(); - // Directive includes fields: - // * `foo[{bar}]=trace` - // * `foo[{bar,baz}]=trace` - if let Some(maybe_fields) = split.next() { - if split.next().is_some() { - return Err(ParseError::msg( - "too many '[{' in filter directive, expected 0 or 1", - )); - } - - if !maybe_fields.ends_with("}]") { - return Err(ParseError::msg("expected fields list to end with '}]'")); - } - - let fields = maybe_fields - .trim_end_matches("}]") - .split(',') - .filter_map(|s| { - if s.is_empty() { - None - } else { - Some(String::from(s)) - } - }); - field_names.extend(fields); - }; - let level = part1.parse()?; - return Ok(Self { - level, - field_names, - target, - }); - } - - // Okay, the part after the `=` was empty, the directive is either a - // bare level or a bare target. - // * `foo` - // * `info` - Ok(match part0.parse::() { - Ok(level) => Self { - level, - target: None, - field_names: Vec::new(), - }, - Err(_) => Self { - target: Some(String::from(part0)), - level: LevelFilter::TRACE, - field_names: Vec::new(), - }, - }) - } -} - -// === impl ParseError === - -impl ParseError { - #[cfg(feature = "env-filter")] - pub(crate) fn new() -> Self { - ParseError { - kind: ParseErrorKind::Other(None), - } - } - - pub(crate) fn msg(s: &'static str) -> Self { - ParseError { - kind: ParseErrorKind::Other(Some(s)), - } - } -} - -impl fmt::Display for ParseError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - ParseErrorKind::Other(None) => f.pad("invalid filter directive"), - ParseErrorKind::Other(Some(msg)) => write!(f, "invalid filter directive: {}", msg), - ParseErrorKind::Level(ref l) => l.fmt(f), - #[cfg(feature = "std")] - ParseErrorKind::Field(ref e) => write!(f, "invalid field filter: {}", e), - } - } -} - -#[cfg(feature = "std")] -impl std::error::Error for ParseError { - fn description(&self) -> &str { - "invalid filter directive" - } - - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self.kind { - ParseErrorKind::Other(_) => None, - ParseErrorKind::Level(ref l) => Some(l), - ParseErrorKind::Field(ref n) => Some(n.as_ref()), - } - } -} - -#[cfg(feature = "std")] -impl From> for ParseError { - fn from(e: Box) -> Self { - Self { - kind: ParseErrorKind::Field(e), - } - } -} - -impl From for ParseError { - fn from(l: level::ParseError) -> Self { - Self { - kind: ParseErrorKind::Level(l), - } - } -} diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs b/vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs deleted file mode 100644 index 66ca23dc4..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs +++ /dev/null @@ -1,846 +0,0 @@ -pub(crate) use crate::filter::directive::{FilterVec, ParseError, StaticDirective}; -use crate::filter::{ - directive::{DirectiveSet, Match}, - env::{field, FieldMap}, - level::LevelFilter, -}; -use lazy_static::lazy_static; -use regex::Regex; -use std::{cmp::Ordering, fmt, iter::FromIterator, str::FromStr}; -use tracing_core::{span, Level, Metadata}; - -/// A single filtering directive. -// TODO(eliza): add a builder for programmatically constructing directives? -#[derive(Debug, Eq, PartialEq)] -#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))] -pub struct Directive { - in_span: Option, - fields: Vec, - pub(crate) target: Option, - pub(crate) level: LevelFilter, -} - -/// A set of dynamic filtering directives. -pub(super) type Dynamics = DirectiveSet; - -/// A set of static filtering directives. -pub(super) type Statics = DirectiveSet; - -pub(crate) type CallsiteMatcher = MatchSet; -pub(crate) type SpanMatcher = MatchSet; - -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct MatchSet { - field_matches: FilterVec, - base_level: LevelFilter, -} - -impl Directive { - pub(super) fn has_name(&self) -> bool { - self.in_span.is_some() - } - - pub(super) fn has_fields(&self) -> bool { - !self.fields.is_empty() - } - - pub(super) fn to_static(&self) -> Option { - if !self.is_static() { - return None; - } - - // TODO(eliza): these strings are all immutable; we should consider - // `Arc`ing them to make this more efficient... - let field_names = self.fields.iter().map(field::Match::name).collect(); - - Some(StaticDirective::new( - self.target.clone(), - field_names, - self.level, - )) - } - - fn is_static(&self) -> bool { - !self.has_name() && !self.fields.iter().any(field::Match::has_value) - } - - pub(super) fn is_dynamic(&self) -> bool { - self.has_name() || self.has_fields() - } - - pub(crate) fn field_matcher(&self, meta: &Metadata<'_>) -> Option { - let fieldset = meta.fields(); - let fields = self - .fields - .iter() - .filter_map( - |field::Match { - ref name, - ref value, - }| { - if let Some(field) = fieldset.field(name) { - let value = value.as_ref().cloned()?; - Some(Ok((field, value))) - } else { - Some(Err(())) - } - }, - ) - .collect::, ()>>() - .ok()?; - Some(field::CallsiteMatch { - fields, - level: self.level, - }) - } - - pub(super) fn make_tables( - directives: impl IntoIterator, - ) -> (Dynamics, Statics) { - // TODO(eliza): this could be made more efficient... - let (dyns, stats): (Vec, Vec) = - directives.into_iter().partition(Directive::is_dynamic); - let statics = stats - .into_iter() - .filter_map(|d| d.to_static()) - .chain(dyns.iter().filter_map(Directive::to_static)) - .collect(); - (Dynamics::from_iter(dyns), statics) - } -} - -impl Match for Directive { - fn cares_about(&self, meta: &Metadata<'_>) -> bool { - // Does this directive have a target filter, and does it match the - // metadata's target? - if let Some(ref target) = self.target { - if !meta.target().starts_with(&target[..]) { - return false; - } - } - - // Do we have a name filter, and does it match the metadata's name? - // TODO(eliza): put name globbing here? - if let Some(ref name) = self.in_span { - if name != meta.name() { - return false; - } - } - - // Does the metadata define all the fields that this directive cares about? - let fields = meta.fields(); - for field in &self.fields { - if fields.field(&field.name).is_none() { - return false; - } - } - - true - } - - fn level(&self) -> &LevelFilter { - &self.level - } -} - -impl FromStr for Directive { - type Err = ParseError; - fn from_str(from: &str) -> Result { - lazy_static! { - static ref DIRECTIVE_RE: Regex = Regex::new( - r"(?x) - ^(?P(?i:trace|debug|info|warn|error|off|[0-5]))$ | - # ^^^. - # `note: we match log level names case-insensitively - ^ - (?: # target name or span name - (?P[\w:-]+)|(?P\[[^\]]*\]) - ){1,2} - (?: # level or nothing - =(?P(?i:trace|debug|info|warn|error|off|[0-5]))? - # ^^^. - # `note: we match log level names case-insensitively - )? - $ - " - ) - .unwrap(); - static ref SPAN_PART_RE: Regex = - Regex::new(r#"(?P[^\]\{]+)?(?:\{(?P[^\}]*)\})?"#).unwrap(); - static ref FIELD_FILTER_RE: Regex = - // TODO(eliza): this doesn't _currently_ handle value matchers that include comma - // characters. We should fix that. - Regex::new(r#"(?x) - ( - # field name - [[:word:]][[[:word:]]\.]* - # value part (optional) - (?:=[^,]+)? - ) - # trailing comma or EOS - (?:,\s?|$) - "#).unwrap(); - } - - let caps = DIRECTIVE_RE.captures(from).ok_or_else(ParseError::new)?; - - if let Some(level) = caps - .name("global_level") - .and_then(|s| s.as_str().parse().ok()) - { - return Ok(Directive { - level, - ..Default::default() - }); - } - - let target = caps.name("target").and_then(|c| { - let s = c.as_str(); - if s.parse::().is_ok() { - None - } else { - Some(s.to_owned()) - } - }); - - let (in_span, fields) = caps - .name("span") - .and_then(|cap| { - let cap = cap.as_str().trim_matches(|c| c == '[' || c == ']'); - let caps = SPAN_PART_RE.captures(cap)?; - let span = caps.name("name").map(|c| c.as_str().to_owned()); - let fields = caps - .name("fields") - .map(|c| { - FIELD_FILTER_RE - .find_iter(c.as_str()) - .map(|c| c.as_str().parse()) - .collect::, _>>() - }) - .unwrap_or_else(|| Ok(Vec::new())); - Some((span, fields)) - }) - .unwrap_or_else(|| (None, Ok(Vec::new()))); - - let level = caps - .name("level") - .and_then(|l| l.as_str().parse().ok()) - // Setting the target without the level enables every level for that target - .unwrap_or(LevelFilter::TRACE); - - Ok(Directive { - level, - target, - in_span, - fields: fields?, - }) - } -} - -impl Default for Directive { - fn default() -> Self { - Directive { - level: LevelFilter::OFF, - target: None, - in_span: None, - fields: Vec::new(), - } - } -} - -impl PartialOrd for Directive { - fn partial_cmp(&self, other: &Directive) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Directive { - fn cmp(&self, other: &Directive) -> Ordering { - // We attempt to order directives by how "specific" they are. This - // ensures that we try the most specific directives first when - // attempting to match a piece of metadata. - - // First, we compare based on whether a target is specified, and the - // lengths of those targets if both have targets. - let ordering = self - .target - .as_ref() - .map(String::len) - .cmp(&other.target.as_ref().map(String::len)) - // Next compare based on the presence of span names. - .then_with(|| self.in_span.is_some().cmp(&other.in_span.is_some())) - // Then we compare how many fields are defined by each - // directive. - .then_with(|| self.fields.len().cmp(&other.fields.len())) - // Finally, we fall back to lexicographical ordering if the directives are - // equally specific. Although this is no longer semantically important, - // we need to define a total ordering to determine the directive's place - // in the BTreeMap. - .then_with(|| { - self.target - .cmp(&other.target) - .then_with(|| self.in_span.cmp(&other.in_span)) - .then_with(|| self.fields[..].cmp(&other.fields[..])) - }) - .reverse(); - - #[cfg(debug_assertions)] - { - if ordering == Ordering::Equal { - debug_assert_eq!( - self.target, other.target, - "invariant violated: Ordering::Equal must imply a.target == b.target" - ); - debug_assert_eq!( - self.in_span, other.in_span, - "invariant violated: Ordering::Equal must imply a.in_span == b.in_span" - ); - debug_assert_eq!( - self.fields, other.fields, - "invariant violated: Ordering::Equal must imply a.fields == b.fields" - ); - } - } - - ordering - } -} - -impl fmt::Display for Directive { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut wrote_any = false; - if let Some(ref target) = self.target { - fmt::Display::fmt(target, f)?; - wrote_any = true; - } - - if self.in_span.is_some() || !self.fields.is_empty() { - f.write_str("[")?; - - if let Some(ref span) = self.in_span { - fmt::Display::fmt(span, f)?; - } - - let mut fields = self.fields.iter(); - if let Some(field) = fields.next() { - write!(f, "{{{}", field)?; - for field in fields { - write!(f, ",{}", field)?; - } - f.write_str("}")?; - } - - f.write_str("]")?; - wrote_any = true; - } - - if wrote_any { - f.write_str("=")?; - } - - fmt::Display::fmt(&self.level, f) - } -} - -impl From for Directive { - fn from(level: LevelFilter) -> Self { - Self { - level, - ..Self::default() - } - } -} - -impl From for Directive { - fn from(level: Level) -> Self { - LevelFilter::from_level(level).into() - } -} - -// === impl Dynamics === - -impl Dynamics { - pub(crate) fn matcher(&self, metadata: &Metadata<'_>) -> Option { - let mut base_level = None; - let field_matches = self - .directives_for(metadata) - .filter_map(|d| { - if let Some(f) = d.field_matcher(metadata) { - return Some(f); - } - match base_level { - Some(ref b) if d.level > *b => base_level = Some(d.level), - None => base_level = Some(d.level), - _ => {} - } - None - }) - .collect(); - - if let Some(base_level) = base_level { - Some(CallsiteMatcher { - field_matches, - base_level, - }) - } else if !field_matches.is_empty() { - Some(CallsiteMatcher { - field_matches, - base_level: base_level.unwrap_or(LevelFilter::OFF), - }) - } else { - None - } - } - - pub(crate) fn has_value_filters(&self) -> bool { - self.directives() - .any(|d| d.fields.iter().any(|f| f.value.is_some())) - } -} - -// ===== impl DynamicMatch ===== - -impl CallsiteMatcher { - /// Create a new `SpanMatch` for a given instance of the matched callsite. - pub(crate) fn to_span_match(&self, attrs: &span::Attributes<'_>) -> SpanMatcher { - let field_matches = self - .field_matches - .iter() - .map(|m| { - let m = m.to_span_match(); - attrs.record(&mut m.visitor()); - m - }) - .collect(); - SpanMatcher { - field_matches, - base_level: self.base_level, - } - } -} - -impl SpanMatcher { - /// Returns the level currently enabled for this callsite. - pub(crate) fn level(&self) -> LevelFilter { - self.field_matches - .iter() - .filter_map(field::SpanMatch::filter) - .max() - .unwrap_or(self.base_level) - } - - pub(crate) fn record_update(&self, record: &span::Record<'_>) { - for m in &self.field_matches { - record.record(&mut m.visitor()) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - fn parse_directives(dirs: impl AsRef) -> Vec { - dirs.as_ref() - .split(',') - .filter_map(|s| s.parse().ok()) - .collect() - } - - fn expect_parse(dirs: impl AsRef) -> Vec { - dirs.as_ref() - .split(',') - .map(|s| { - s.parse() - .unwrap_or_else(|err| panic!("directive '{:?}' should parse: {}", s, err)) - }) - .collect() - } - - #[test] - fn directive_ordering_by_target_len() { - // TODO(eliza): it would be nice to have a property-based test for this - // instead. - let mut dirs = expect_parse( - "foo::bar=debug,foo::bar::baz=trace,foo=info,a_really_long_name_with_no_colons=warn", - ); - dirs.sort_unstable(); - - let expected = vec![ - "a_really_long_name_with_no_colons", - "foo::bar::baz", - "foo::bar", - "foo", - ]; - let sorted = dirs - .iter() - .map(|d| d.target.as_ref().unwrap()) - .collect::>(); - - assert_eq!(expected, sorted); - } - #[test] - fn directive_ordering_by_span() { - // TODO(eliza): it would be nice to have a property-based test for this - // instead. - let mut dirs = expect_parse("bar[span]=trace,foo=debug,baz::quux=info,a[span]=warn"); - dirs.sort_unstable(); - - let expected = vec!["baz::quux", "bar", "foo", "a"]; - let sorted = dirs - .iter() - .map(|d| d.target.as_ref().unwrap()) - .collect::>(); - - assert_eq!(expected, sorted); - } - - #[test] - fn directive_ordering_uses_lexicographic_when_equal() { - // TODO(eliza): it would be nice to have a property-based test for this - // instead. - let mut dirs = expect_parse("span[b]=debug,b=debug,a=trace,c=info,span[a]=info"); - dirs.sort_unstable(); - - let expected = vec![ - ("span", Some("b")), - ("span", Some("a")), - ("c", None), - ("b", None), - ("a", None), - ]; - let sorted = dirs - .iter() - .map(|d| { - ( - d.target.as_ref().unwrap().as_ref(), - d.in_span.as_ref().map(String::as_ref), - ) - }) - .collect::>(); - - assert_eq!(expected, sorted); - } - - // TODO: this test requires the parser to support directives with multiple - // fields, which it currently can't handle. We should enable this test when - // that's implemented. - #[test] - #[ignore] - fn directive_ordering_by_field_num() { - // TODO(eliza): it would be nice to have a property-based test for this - // instead. - let mut dirs = expect_parse( - "b[{foo,bar}]=info,c[{baz,quuux,quuux}]=debug,a[{foo}]=warn,bar[{field}]=trace,foo=debug,baz::quux=info" - ); - dirs.sort_unstable(); - - let expected = vec!["baz::quux", "bar", "foo", "c", "b", "a"]; - let sorted = dirs - .iter() - .map(|d| d.target.as_ref().unwrap()) - .collect::>(); - - assert_eq!(expected, sorted); - } - - #[test] - fn parse_directives_ralith() { - let dirs = parse_directives("common=trace,server=trace"); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("common".to_string())); - assert_eq!(dirs[0].level, LevelFilter::TRACE); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("server".to_string())); - assert_eq!(dirs[1].level, LevelFilter::TRACE); - assert_eq!(dirs[1].in_span, None); - } - - #[test] - fn parse_directives_ralith_uc() { - let dirs = parse_directives("common=INFO,server=DEBUG"); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("common".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("server".to_string())); - assert_eq!(dirs[1].level, LevelFilter::DEBUG); - assert_eq!(dirs[1].in_span, None); - } - - #[test] - fn parse_directives_ralith_mixed() { - let dirs = parse_directives("common=iNfo,server=dEbUg"); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("common".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("server".to_string())); - assert_eq!(dirs[1].level, LevelFilter::DEBUG); - assert_eq!(dirs[1].in_span, None); - } - - #[test] - fn parse_directives_valid() { - let dirs = parse_directives("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off"); - assert_eq!(dirs.len(), 4, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::TRACE); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[2].target, Some("crate2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::DEBUG); - assert_eq!(dirs[2].in_span, None); - - assert_eq!(dirs[3].target, Some("crate3".to_string())); - assert_eq!(dirs[3].level, LevelFilter::OFF); - assert_eq!(dirs[3].in_span, None); - } - - #[test] - - fn parse_level_directives() { - let dirs = parse_directives( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off", - ); - assert_eq!(dirs.len(), 6, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::WARN); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[2].target, Some("crate1::mod2::mod3".to_string())); - assert_eq!(dirs[2].level, LevelFilter::INFO); - assert_eq!(dirs[2].in_span, None); - - assert_eq!(dirs[3].target, Some("crate2".to_string())); - assert_eq!(dirs[3].level, LevelFilter::DEBUG); - assert_eq!(dirs[3].in_span, None); - - assert_eq!(dirs[4].target, Some("crate3".to_string())); - assert_eq!(dirs[4].level, LevelFilter::TRACE); - assert_eq!(dirs[4].in_span, None); - - assert_eq!(dirs[5].target, Some("crate3::mod2::mod1".to_string())); - assert_eq!(dirs[5].level, LevelFilter::OFF); - assert_eq!(dirs[5].in_span, None); - } - - #[test] - fn parse_uppercase_level_directives() { - let dirs = parse_directives( - "crate1::mod1=ERROR,crate1::mod2=WARN,crate1::mod2::mod3=INFO,\ - crate2=DEBUG,crate3=TRACE,crate3::mod2::mod1=OFF", - ); - assert_eq!(dirs.len(), 6, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::WARN); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[2].target, Some("crate1::mod2::mod3".to_string())); - assert_eq!(dirs[2].level, LevelFilter::INFO); - assert_eq!(dirs[2].in_span, None); - - assert_eq!(dirs[3].target, Some("crate2".to_string())); - assert_eq!(dirs[3].level, LevelFilter::DEBUG); - assert_eq!(dirs[3].in_span, None); - - assert_eq!(dirs[4].target, Some("crate3".to_string())); - assert_eq!(dirs[4].level, LevelFilter::TRACE); - assert_eq!(dirs[4].in_span, None); - - assert_eq!(dirs[5].target, Some("crate3::mod2::mod1".to_string())); - assert_eq!(dirs[5].level, LevelFilter::OFF); - assert_eq!(dirs[5].in_span, None); - } - - #[test] - fn parse_numeric_level_directives() { - let dirs = parse_directives( - "crate1::mod1=1,crate1::mod2=2,crate1::mod2::mod3=3,crate2=4,\ - crate3=5,crate3::mod2::mod1=0", - ); - assert_eq!(dirs.len(), 6, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::WARN); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[2].target, Some("crate1::mod2::mod3".to_string())); - assert_eq!(dirs[2].level, LevelFilter::INFO); - assert_eq!(dirs[2].in_span, None); - - assert_eq!(dirs[3].target, Some("crate2".to_string())); - assert_eq!(dirs[3].level, LevelFilter::DEBUG); - assert_eq!(dirs[3].in_span, None); - - assert_eq!(dirs[4].target, Some("crate3".to_string())); - assert_eq!(dirs[4].level, LevelFilter::TRACE); - assert_eq!(dirs[4].in_span, None); - - assert_eq!(dirs[5].target, Some("crate3::mod2::mod1".to_string())); - assert_eq!(dirs[5].level, LevelFilter::OFF); - assert_eq!(dirs[5].in_span, None); - } - - #[test] - fn parse_directives_invalid_crate() { - // test parse_directives with multiple = in specification - let dirs = parse_directives("crate1::mod1=warn=info,crate2=debug"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::DEBUG); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_invalid_level() { - // test parse_directives with 'noNumber' as log level - let dirs = parse_directives("crate1::mod1=noNumber,crate2=debug"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::DEBUG); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_string_level() { - // test parse_directives with 'warn' as log level - let dirs = parse_directives("crate1::mod1=wrong,crate2=warn"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::WARN); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_empty_level() { - // test parse_directives with '' as log level - let dirs = parse_directives("crate1::mod1=wrong,crate2="); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::TRACE); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_global() { - // test parse_directives with no crate - let dirs = parse_directives("warn,crate2=debug"); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, None); - assert_eq!(dirs[0].level, LevelFilter::WARN); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[1].target, Some("crate2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::DEBUG); - assert_eq!(dirs[1].in_span, None); - } - - // helper function for tests below - fn test_parse_bare_level(directive_to_test: &str, level_expected: LevelFilter) { - let dirs = parse_directives(directive_to_test); - assert_eq!( - dirs.len(), - 1, - "\ninput: \"{}\"; parsed: {:#?}", - directive_to_test, - dirs - ); - assert_eq!(dirs[0].target, None); - assert_eq!(dirs[0].level, level_expected); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_global_bare_warn_lc() { - // test parse_directives with no crate, in isolation, all lowercase - test_parse_bare_level("warn", LevelFilter::WARN); - } - - #[test] - fn parse_directives_global_bare_warn_uc() { - // test parse_directives with no crate, in isolation, all uppercase - test_parse_bare_level("WARN", LevelFilter::WARN); - } - - #[test] - fn parse_directives_global_bare_warn_mixed() { - // test parse_directives with no crate, in isolation, mixed case - test_parse_bare_level("wArN", LevelFilter::WARN); - } - - #[test] - fn parse_directives_valid_with_spans() { - let dirs = parse_directives("crate1::mod1[foo]=error,crate1::mod2[bar],crate2[baz]=debug"); - assert_eq!(dirs.len(), 3, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, Some("foo".to_string())); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::TRACE); - assert_eq!(dirs[1].in_span, Some("bar".to_string())); - - assert_eq!(dirs[2].target, Some("crate2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::DEBUG); - assert_eq!(dirs[2].in_span, Some("baz".to_string())); - } - - #[test] - fn parse_directives_with_dash_in_target_name() { - let dirs = parse_directives("target-name=info"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("target-name".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_with_dash_in_span_name() { - // Reproduces https://github.com/tokio-rs/tracing/issues/1367 - - let dirs = parse_directives("target[span-name]=info"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("target".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, Some("span-name".to_string())); - } - - #[test] - fn parse_directives_with_special_characters_in_span_name() { - let span_name = "!\"#$%&'()*+-./:;<=>?@^_`|~[}"; - - let dirs = parse_directives(format!("target[{}]=info", span_name)); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("target".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, Some(span_name.to_string())); - } - - #[test] - fn parse_directives_with_invalid_span_chars() { - let invalid_span_name = "]{"; - - let dirs = parse_directives(format!("target[{}]=info", invalid_span_name)); - assert_eq!(dirs.len(), 0, "\nparsed: {:#?}", dirs); - } -} diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs b/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs deleted file mode 100644 index 970850f92..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs +++ /dev/null @@ -1,416 +0,0 @@ -use matchers::Pattern; -use std::{ - cmp::Ordering, - error::Error, - fmt, - str::FromStr, - sync::{ - atomic::{AtomicBool, Ordering::*}, - Arc, - }, -}; - -use super::{FieldMap, LevelFilter}; -use tracing_core::field::{Field, Visit}; - -#[derive(Debug, Eq, PartialEq)] -pub(crate) struct Match { - pub(crate) name: String, // TODO: allow match patterns for names? - pub(crate) value: Option, -} - -#[derive(Debug, Eq, PartialEq)] -pub(crate) struct CallsiteMatch { - pub(crate) fields: FieldMap, - pub(crate) level: LevelFilter, -} - -#[derive(Debug)] -pub(crate) struct SpanMatch { - fields: FieldMap<(ValueMatch, AtomicBool)>, - level: LevelFilter, - has_matched: AtomicBool, -} - -pub(crate) struct MatchVisitor<'a> { - inner: &'a SpanMatch, -} - -#[derive(Debug, Clone)] -pub(crate) enum ValueMatch { - Bool(bool), - F64(f64), - U64(u64), - I64(i64), - NaN, - Pat(Box), -} - -impl Eq for ValueMatch {} - -impl PartialEq for ValueMatch { - fn eq(&self, other: &Self) -> bool { - use ValueMatch::*; - match (self, other) { - (Bool(a), Bool(b)) => a.eq(b), - (F64(a), F64(b)) => { - debug_assert!(!a.is_nan()); - debug_assert!(!b.is_nan()); - - a.eq(b) - } - (U64(a), U64(b)) => a.eq(b), - (I64(a), I64(b)) => a.eq(b), - (NaN, NaN) => true, - (Pat(a), Pat(b)) => a.eq(b), - _ => false, - } - } -} - -impl Ord for ValueMatch { - fn cmp(&self, other: &Self) -> Ordering { - use ValueMatch::*; - match (self, other) { - (Bool(this), Bool(that)) => this.cmp(that), - (Bool(_), _) => Ordering::Less, - - (F64(this), F64(that)) => this - .partial_cmp(that) - .expect("`ValueMatch::F64` may not contain `NaN` values"), - (F64(_), Bool(_)) => Ordering::Greater, - (F64(_), _) => Ordering::Less, - - (NaN, NaN) => Ordering::Equal, - (NaN, Bool(_)) | (NaN, F64(_)) => Ordering::Greater, - (NaN, _) => Ordering::Less, - - (U64(this), U64(that)) => this.cmp(that), - (U64(_), Bool(_)) | (U64(_), F64(_)) | (U64(_), NaN) => Ordering::Greater, - (U64(_), _) => Ordering::Less, - - (I64(this), I64(that)) => this.cmp(that), - (I64(_), Bool(_)) | (I64(_), F64(_)) | (I64(_), NaN) | (I64(_), U64(_)) => { - Ordering::Greater - } - (I64(_), _) => Ordering::Less, - - (Pat(this), Pat(that)) => this.cmp(that), - (Pat(_), _) => Ordering::Greater, - } - } -} - -impl PartialOrd for ValueMatch { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -#[derive(Debug, Clone)] -pub(crate) struct MatchPattern { - pub(crate) matcher: Pattern, - pattern: Arc, -} - -/// Indicates that a field name specified in a filter directive was invalid. -#[derive(Clone, Debug)] -#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))] -pub struct BadName { - name: String, -} - -// === impl Match === - -impl FromStr for Match { - type Err = Box; - fn from_str(s: &str) -> Result { - let mut parts = s.split('='); - let name = parts - .next() - .ok_or_else(|| BadName { - name: "".to_string(), - })? - // TODO: validate field name - .to_string(); - let value = parts.next().map(ValueMatch::from_str).transpose()?; - Ok(Match { name, value }) - } -} - -impl Match { - pub(crate) fn has_value(&self) -> bool { - self.value.is_some() - } - - // TODO: reference count these strings? - pub(crate) fn name(&self) -> String { - self.name.clone() - } -} - -impl fmt::Display for Match { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.name, f)?; - if let Some(ref value) = self.value { - write!(f, "={}", value)?; - } - Ok(()) - } -} - -impl Ord for Match { - fn cmp(&self, other: &Self) -> Ordering { - // Ordering for `Match` directives is based first on _whether_ a value - // is matched or not. This is semantically meaningful --- we would - // prefer to check directives that match values first as they are more - // specific. - let has_value = match (self.value.as_ref(), other.value.as_ref()) { - (Some(_), None) => Ordering::Greater, - (None, Some(_)) => Ordering::Less, - _ => Ordering::Equal, - }; - // If both directives match a value, we fall back to the field names in - // length + lexicographic ordering, and if these are equal as well, we - // compare the match directives. - // - // This ordering is no longer semantically meaningful but is necessary - // so that the directives can be stored in the `BTreeMap` in a defined - // order. - has_value - .then_with(|| self.name.cmp(&other.name)) - .then_with(|| self.value.cmp(&other.value)) - } -} - -impl PartialOrd for Match { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -// === impl ValueMatch === - -fn value_match_f64(v: f64) -> ValueMatch { - if v.is_nan() { - ValueMatch::NaN - } else { - ValueMatch::F64(v) - } -} - -impl FromStr for ValueMatch { - type Err = matchers::Error; - fn from_str(s: &str) -> Result { - s.parse::() - .map(ValueMatch::Bool) - .or_else(|_| s.parse::().map(ValueMatch::U64)) - .or_else(|_| s.parse::().map(ValueMatch::I64)) - .or_else(|_| s.parse::().map(value_match_f64)) - .or_else(|_| { - s.parse::() - .map(|p| ValueMatch::Pat(Box::new(p))) - }) - } -} - -impl fmt::Display for ValueMatch { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ValueMatch::Bool(ref inner) => fmt::Display::fmt(inner, f), - ValueMatch::F64(ref inner) => fmt::Display::fmt(inner, f), - ValueMatch::NaN => fmt::Display::fmt(&std::f64::NAN, f), - ValueMatch::I64(ref inner) => fmt::Display::fmt(inner, f), - ValueMatch::U64(ref inner) => fmt::Display::fmt(inner, f), - ValueMatch::Pat(ref inner) => fmt::Display::fmt(inner, f), - } - } -} - -// === impl MatchPattern === - -impl FromStr for MatchPattern { - type Err = matchers::Error; - fn from_str(s: &str) -> Result { - let matcher = s.parse::()?; - Ok(Self { - matcher, - pattern: s.to_owned().into(), - }) - } -} - -impl fmt::Display for MatchPattern { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&*self.pattern, f) - } -} - -impl AsRef for MatchPattern { - #[inline] - fn as_ref(&self) -> &str { - self.pattern.as_ref() - } -} - -impl MatchPattern { - #[inline] - fn str_matches(&self, s: &impl AsRef) -> bool { - self.matcher.matches(s) - } - - #[inline] - fn debug_matches(&self, d: &impl fmt::Debug) -> bool { - self.matcher.debug_matches(d) - } -} - -impl PartialEq for MatchPattern { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.pattern == other.pattern - } -} - -impl Eq for MatchPattern {} - -impl PartialOrd for MatchPattern { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.pattern.cmp(&other.pattern)) - } -} - -impl Ord for MatchPattern { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - self.pattern.cmp(&other.pattern) - } -} - -// === impl BadName === - -impl Error for BadName {} - -impl fmt::Display for BadName { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "invalid field name `{}`", self.name) - } -} - -impl CallsiteMatch { - pub(crate) fn to_span_match(&self) -> SpanMatch { - let fields = self - .fields - .iter() - .map(|(k, v)| (k.clone(), (v.clone(), AtomicBool::new(false)))) - .collect(); - SpanMatch { - fields, - level: self.level, - has_matched: AtomicBool::new(false), - } - } -} - -impl SpanMatch { - pub(crate) fn visitor(&self) -> MatchVisitor<'_> { - MatchVisitor { inner: self } - } - - #[inline] - pub(crate) fn is_matched(&self) -> bool { - if self.has_matched.load(Acquire) { - return true; - } - self.is_matched_slow() - } - - #[inline(never)] - fn is_matched_slow(&self) -> bool { - let matched = self - .fields - .values() - .all(|(_, matched)| matched.load(Acquire)); - if matched { - self.has_matched.store(true, Release); - } - matched - } - - #[inline] - pub(crate) fn filter(&self) -> Option { - if self.is_matched() { - Some(self.level) - } else { - None - } - } -} - -impl<'a> Visit for MatchVisitor<'a> { - fn record_f64(&mut self, field: &Field, value: f64) { - match self.inner.fields.get(field) { - Some((ValueMatch::NaN, ref matched)) if value.is_nan() => { - matched.store(true, Release); - } - Some((ValueMatch::F64(ref e), ref matched)) - if (value - *e).abs() < std::f64::EPSILON => - { - matched.store(true, Release); - } - _ => {} - } - } - - fn record_i64(&mut self, field: &Field, value: i64) { - use std::convert::TryInto; - - match self.inner.fields.get(field) { - Some((ValueMatch::I64(ref e), ref matched)) if value == *e => { - matched.store(true, Release); - } - Some((ValueMatch::U64(ref e), ref matched)) if Ok(value) == (*e).try_into() => { - matched.store(true, Release); - } - _ => {} - } - } - - fn record_u64(&mut self, field: &Field, value: u64) { - match self.inner.fields.get(field) { - Some((ValueMatch::U64(ref e), ref matched)) if value == *e => { - matched.store(true, Release); - } - _ => {} - } - } - - fn record_bool(&mut self, field: &Field, value: bool) { - match self.inner.fields.get(field) { - Some((ValueMatch::Bool(ref e), ref matched)) if value == *e => { - matched.store(true, Release); - } - _ => {} - } - } - - fn record_str(&mut self, field: &Field, value: &str) { - match self.inner.fields.get(field) { - Some((ValueMatch::Pat(ref e), ref matched)) if e.str_matches(&value) => { - matched.store(true, Release); - } - _ => {} - } - } - - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - match self.inner.fields.get(field) { - Some((ValueMatch::Pat(ref e), ref matched)) if e.debug_matches(&value) => { - matched.store(true, Release); - } - _ => {} - } - } -} diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs b/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs deleted file mode 100644 index 81fe0e62d..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs +++ /dev/null @@ -1,738 +0,0 @@ -//! A `Layer` that enables or disables spans and events based on a set of -//! filtering directives. - -// these are publicly re-exported, but the compiler doesn't realize -// that for some reason. -#[allow(unreachable_pub)] -pub use self::{directive::Directive, field::BadName as BadFieldName}; -mod directive; -mod field; - -use crate::{ - filter::LevelFilter, - layer::{Context, Layer}, - sync::RwLock, -}; -use directive::ParseError; -use std::{cell::RefCell, collections::HashMap, env, error::Error, fmt, str::FromStr}; -use tracing_core::{ - callsite, - field::Field, - span, - subscriber::{Interest, Subscriber}, - Metadata, -}; - -/// A [`Layer`] which filters spans and events based on a set of filter -/// directives. -/// -/// # Directives -/// -/// A filter consists of one or more comma-separated directives which match on [`Span`]s and [`Event`]s. -/// Each directive may have a corresponding maximum verbosity [`level`] which -/// enables (e.g., _selects for_) spans and events that match. Like `log`, -/// `tracing` considers less exclusive levels (like `trace` or `info`) to be more -/// verbose than more exclusive levels (like `error` or `warn`). -/// -/// The directive syntax is similar to that of [`env_logger`]'s. At a high level, the syntax for directives -/// consists of several parts: -/// -/// ```text -/// target[span{field=value}]=level -/// ``` -/// -/// Each component (`target`, `span`, `field`, `value`, and `level`) will be covered in turn. -/// -/// - `target` matches the event or span's target. In general, this is the module path and/or crate name. -/// Examples of targets `h2`, `tokio::net`, or `tide::server`. For more information on targets, -/// please refer to [`Metadata`]'s documentation. -/// - `span` matches on the span's name. If a `span` directive is provided alongside a `target`, -/// the `span` directive will match on spans _within_ the `target`. -/// - `field` matches on [fields] within spans. Field names can also be supplied without a `value` -/// and will match on any [`Span`] or [`Event`] that has a field with that name. -/// For example: `[span{field=\"value\"}]=debug`, `[{field}]=trace`. -/// - `value` matches on the value of a span's field. If a value is a numeric literal or a bool, -/// it will match _only_ on that value. Otherwise, this filter acts as a regex on -/// the `std::fmt::Debug` output from the value. -/// - `level` sets a maximum verbosity level accepted by this directive. -/// -/// ## Usage Notes -/// -/// - The portion of the directive which is included within the square brackets is `tracing`-specific. -/// - Any portion of the directive can be omitted. -/// - The sole exception are the `field` and `value` directives. If a `value` is provided, -/// a `field` must _also_ be provided. However, the converse does not hold, as fields can -/// be matched without a value. -/// - If only a level is provided, it will set the maximum level for all `Span`s and `Event`s -/// that are not enabled by other filters. -/// - A directive without a level will enable anything that it matches. This is equivalent to `=trace`. -/// - When a crate has a dash in its name, the default target for events will be the -/// crate's module path as it appears in Rust. This means every dash will be replaced -/// with an underscore. -/// - A dash in a target will only appear when being specified explicitly: -/// `tracing::info!(target: "target-name", ...);` -/// -/// ## Examples -/// -/// - `tokio::net=info` will enable all spans or events that: -/// - have the `tokio::net` target, -/// - at the level `info` or above. -/// - `warn,tokio::net=info` will enable all spans and events that: -/// - are at the level `warn` or above, *or* -/// - have the `tokio::net` target at the level `info` or above. -/// - `my_crate[span_a]=trace` will enable all spans and events that: -/// - are within the `span_a` span or named `span_a` _if_ `span_a` has the target `my_crate`, -/// - at the level `trace` or above. -/// - `[span_b{name=\"bob\"}]` will enable all spans or event that: -/// - have _any_ target, -/// - are inside a span named `span_b`, -/// - which has a field named `name` with value `bob`, -/// - at _any_ level. -/// -/// The [`Targets`] type implements a similar form of filtering, but without the -/// ability to dynamically enable events based on the current span context, and -/// without filtering on field values. When these features are not required, -/// [`Targets`] provides a lighter-weight alternative to [`EnvFilter`]. -/// -/// [`Span`]: tracing_core::span -/// [fields]: tracing_core::Field -/// [`Event`]: tracing_core::Event -/// [`level`]: tracing_core::Level -/// [`Metadata`]: tracing_core::Metadata -/// [`Targets`]: crate::filter::Targets -#[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))] -#[derive(Debug)] -pub struct EnvFilter { - statics: directive::Statics, - dynamics: directive::Dynamics, - has_dynamics: bool, - by_id: RwLock>, - by_cs: RwLock>, -} - -thread_local! { - static SCOPE: RefCell> = RefCell::new(Vec::new()); -} - -type FieldMap = HashMap; - -/// Indicates that an error occurred while parsing a `EnvFilter` from an -/// environment variable. -#[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))] -#[derive(Debug)] -pub struct FromEnvError { - kind: ErrorKind, -} - -#[derive(Debug)] -enum ErrorKind { - Parse(ParseError), - Env(env::VarError), -} - -impl EnvFilter { - /// `RUST_LOG` is the default environment variable used by - /// [`EnvFilter::from_default_env`] and [`EnvFilter::try_from_default_env`]. - /// - /// [`EnvFilter::from_default_env`]: #method.from_default_env - /// [`EnvFilter::try_from_default_env`]: #method.try_from_default_env - pub const DEFAULT_ENV: &'static str = "RUST_LOG"; - - /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment - /// variable, ignoring any invalid filter directives. - pub fn from_default_env() -> Self { - Self::from_env(Self::DEFAULT_ENV) - } - - /// Returns a new `EnvFilter` from the value of the given environment - /// variable, ignoring any invalid filter directives. - pub fn from_env>(env: A) -> Self { - env::var(env.as_ref()).map(Self::new).unwrap_or_default() - } - - /// Returns a new `EnvFilter` from the directives in the given string, - /// ignoring any that are invalid. - pub fn new>(dirs: S) -> Self { - let directives = dirs.as_ref().split(',').filter_map(|s| match s.parse() { - Ok(d) => Some(d), - Err(err) => { - eprintln!("ignoring `{}`: {}", s, err); - None - } - }); - Self::from_directives(directives) - } - - /// Returns a new `EnvFilter` from the directives in the given string, - /// or an error if any are invalid. - pub fn try_new>(dirs: S) -> Result { - let directives = dirs - .as_ref() - .split(',') - .map(|s| s.parse()) - .collect::, _>>()?; - Ok(Self::from_directives(directives)) - } - - /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment - /// variable, or an error if the environment variable contains any invalid - /// filter directives. - pub fn try_from_default_env() -> Result { - Self::try_from_env(Self::DEFAULT_ENV) - } - - /// Returns a new `EnvFilter` from the value of the given environment - /// variable, or an error if the environment variable is unset or contains - /// any invalid filter directives. - pub fn try_from_env>(env: A) -> Result { - env::var(env.as_ref())?.parse().map_err(Into::into) - } - - /// Add a filtering directive to this `EnvFilter`. - /// - /// The added directive will be used in addition to any previously set - /// directives, either added using this method or provided when the filter - /// is constructed. - /// - /// Filters may be created from [`LevelFilter`] or [`Level`], which will - /// enable all traces at or below a certain verbosity level, or - /// parsed from a string specifying a directive. - /// - /// If a filter directive is inserted that matches exactly the same spans - /// and events as a previous filter, but sets a different level for those - /// spans and events, the previous directive is overwritten. - /// - /// [`LevelFilter`]: ../filter/struct.LevelFilter.html - /// [`Level`]: https://docs.rs/tracing-core/latest/tracing_core/struct.Level.html - /// - /// # Examples - /// - /// From [`LevelFilter`]: - //// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// let mut filter = EnvFilter::from_default_env() - /// .add_directive(LevelFilter::INFO.into()); - /// ``` - /// - /// Or from [`Level`]: - /// - /// ```rust - /// # use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// # use tracing::Level; - /// let mut filter = EnvFilter::from_default_env() - /// .add_directive(Level::INFO.into()); - /// ``` - //// - /// Parsed from a string: - //// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, Directive}; - /// - /// # fn try_mk_filter() -> Result<(), Box> { - /// let mut filter = EnvFilter::try_from_default_env()? - /// .add_directive("my_crate::module=trace".parse()?) - /// .add_directive("my_crate::my_other_module::something=info".parse()?); - /// # Ok(()) - /// # } - /// ``` - pub fn add_directive(mut self, directive: Directive) -> Self { - if let Some(stat) = directive.to_static() { - self.statics.add(stat) - } else { - self.has_dynamics = true; - self.dynamics.add(directive); - } - self - } - - fn from_directives(directives: impl IntoIterator) -> Self { - use tracing::level_filters::STATIC_MAX_LEVEL; - use tracing::Level; - - let directives: Vec<_> = directives.into_iter().collect(); - - let disabled: Vec<_> = directives - .iter() - .filter(|directive| directive.level > STATIC_MAX_LEVEL) - .collect(); - - if !disabled.is_empty() { - #[cfg(feature = "ansi_term")] - use ansi_term::{Color, Style}; - // NOTE: We can't use a configured `MakeWriter` because the EnvFilter - // has no knowledge of any underlying subscriber or subscriber, which - // may or may not use a `MakeWriter`. - let warn = |msg: &str| { - #[cfg(not(feature = "ansi_term"))] - let msg = format!("warning: {}", msg); - #[cfg(feature = "ansi_term")] - let msg = { - let bold = Style::new().bold(); - let mut warning = Color::Yellow.paint("warning"); - warning.style_ref_mut().is_bold = true; - format!("{}{} {}", warning, bold.paint(":"), bold.paint(msg)) - }; - eprintln!("{}", msg); - }; - let ctx_prefixed = |prefix: &str, msg: &str| { - #[cfg(not(feature = "ansi_term"))] - let msg = format!("note: {}", msg); - #[cfg(feature = "ansi_term")] - let msg = { - let mut equal = Color::Fixed(21).paint("="); // dark blue - equal.style_ref_mut().is_bold = true; - format!(" {} {} {}", equal, Style::new().bold().paint(prefix), msg) - }; - eprintln!("{}", msg); - }; - let ctx_help = |msg| ctx_prefixed("help:", msg); - let ctx_note = |msg| ctx_prefixed("note:", msg); - let ctx = |msg: &str| { - #[cfg(not(feature = "ansi_term"))] - let msg = format!("note: {}", msg); - #[cfg(feature = "ansi_term")] - let msg = { - let mut pipe = Color::Fixed(21).paint("|"); - pipe.style_ref_mut().is_bold = true; - format!(" {} {}", pipe, msg) - }; - eprintln!("{}", msg); - }; - warn("some trace filter directives would enable traces that are disabled statically"); - for directive in disabled { - let target = if let Some(target) = &directive.target { - format!("the `{}` target", target) - } else { - "all targets".into() - }; - let level = directive - .level - .into_level() - .expect("=off would not have enabled any filters"); - ctx(&format!( - "`{}` would enable the {} level for {}", - directive, level, target - )); - } - ctx_note(&format!("the static max level is `{}`", STATIC_MAX_LEVEL)); - let help_msg = || { - let (feature, filter) = match STATIC_MAX_LEVEL.into_level() { - Some(Level::TRACE) => unreachable!( - "if the max level is trace, no static filtering features are enabled" - ), - Some(Level::DEBUG) => ("max_level_debug", Level::TRACE), - Some(Level::INFO) => ("max_level_info", Level::DEBUG), - Some(Level::WARN) => ("max_level_warn", Level::INFO), - Some(Level::ERROR) => ("max_level_error", Level::WARN), - None => return ("max_level_off", String::new()), - }; - (feature, format!("{} ", filter)) - }; - let (feature, earlier_level) = help_msg(); - ctx_help(&format!( - "to enable {}logging, remove the `{}` feature", - earlier_level, feature - )); - } - - let (dynamics, mut statics) = Directive::make_tables(directives); - let has_dynamics = !dynamics.is_empty(); - - if statics.is_empty() && !has_dynamics { - statics.add(directive::StaticDirective::default()); - } - - Self { - statics, - dynamics, - has_dynamics, - by_id: RwLock::new(HashMap::new()), - by_cs: RwLock::new(HashMap::new()), - } - } - - fn cares_about_span(&self, span: &span::Id) -> bool { - let spans = try_lock!(self.by_id.read(), else return false); - spans.contains_key(span) - } - - fn base_interest(&self) -> Interest { - if self.has_dynamics { - Interest::sometimes() - } else { - Interest::never() - } - } -} - -impl Layer for EnvFilter { - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - if self.has_dynamics && metadata.is_span() { - // If this metadata describes a span, first, check if there is a - // dynamic filter that should be constructed for it. If so, it - // should always be enabled, since it influences filtering. - if let Some(matcher) = self.dynamics.matcher(metadata) { - let mut by_cs = try_lock!(self.by_cs.write(), else return self.base_interest()); - by_cs.insert(metadata.callsite(), matcher); - return Interest::always(); - } - } - - // Otherwise, check if any of our static filters enable this metadata. - if self.statics.enabled(metadata) { - Interest::always() - } else { - self.base_interest() - } - } - - fn max_level_hint(&self) -> Option { - if self.dynamics.has_value_filters() { - // If we perform any filtering on span field *values*, we will - // enable *all* spans, because their field values are not known - // until recording. - return Some(LevelFilter::TRACE); - } - std::cmp::max( - self.statics.max_level.into(), - self.dynamics.max_level.into(), - ) - } - - fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { - let level = metadata.level(); - - // is it possible for a dynamic filter directive to enable this event? - // if not, we can avoid the thread local access + iterating over the - // spans in the current scope. - if self.has_dynamics && self.dynamics.max_level >= *level { - if metadata.is_span() { - // If the metadata is a span, see if we care about its callsite. - let enabled_by_cs = self - .by_cs - .read() - .ok() - .map(|by_cs| by_cs.contains_key(&metadata.callsite())) - .unwrap_or(false); - if enabled_by_cs { - return true; - } - } - - let enabled_by_scope = SCOPE.with(|scope| { - for filter in scope.borrow().iter() { - if filter >= level { - return true; - } - } - false - }); - if enabled_by_scope { - return true; - } - } - - // is it possible for a static filter directive to enable this event? - if self.statics.max_level >= *level { - // Otherwise, fall back to checking if the callsite is - // statically enabled. - return self.statics.enabled(metadata); - } - - false - } - - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) { - let by_cs = try_lock!(self.by_cs.read()); - if let Some(cs) = by_cs.get(&attrs.metadata().callsite()) { - let span = cs.to_span_match(attrs); - try_lock!(self.by_id.write()).insert(id.clone(), span); - } - } - - fn on_record(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>) { - if let Some(span) = try_lock!(self.by_id.read()).get(id) { - span.record_update(values); - } - } - - fn on_enter(&self, id: &span::Id, _: Context<'_, S>) { - // XXX: This is where _we_ could push IDs to the stack instead, and use - // that to allow changing the filter while a span is already entered. - // But that might be much less efficient... - if let Some(span) = try_lock!(self.by_id.read()).get(id) { - SCOPE.with(|scope| scope.borrow_mut().push(span.level())); - } - } - - fn on_exit(&self, id: &span::Id, _: Context<'_, S>) { - if self.cares_about_span(id) { - SCOPE.with(|scope| scope.borrow_mut().pop()); - } - } - - fn on_close(&self, id: span::Id, _: Context<'_, S>) { - // If we don't need to acquire a write lock, avoid doing so. - if !self.cares_about_span(&id) { - return; - } - - let mut spans = try_lock!(self.by_id.write()); - spans.remove(&id); - } -} - -impl FromStr for EnvFilter { - type Err = directive::ParseError; - - fn from_str(spec: &str) -> Result { - Self::try_new(spec) - } -} - -impl From for EnvFilter -where - S: AsRef, -{ - fn from(s: S) -> Self { - Self::new(s) - } -} - -impl Default for EnvFilter { - fn default() -> Self { - Self::from_directives(std::iter::empty()) - } -} - -impl fmt::Display for EnvFilter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut statics = self.statics.iter(); - let wrote_statics = if let Some(next) = statics.next() { - fmt::Display::fmt(next, f)?; - for directive in statics { - write!(f, ",{}", directive)?; - } - true - } else { - false - }; - - let mut dynamics = self.dynamics.iter(); - if let Some(next) = dynamics.next() { - if wrote_statics { - f.write_str(",")?; - } - fmt::Display::fmt(next, f)?; - for directive in dynamics { - write!(f, ",{}", directive)?; - } - } - Ok(()) - } -} - -// ===== impl FromEnvError ===== - -impl From for FromEnvError { - fn from(p: directive::ParseError) -> Self { - Self { - kind: ErrorKind::Parse(p), - } - } -} - -impl From for FromEnvError { - fn from(v: env::VarError) -> Self { - Self { - kind: ErrorKind::Env(v), - } - } -} - -impl fmt::Display for FromEnvError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - ErrorKind::Parse(ref p) => p.fmt(f), - ErrorKind::Env(ref e) => e.fmt(f), - } - } -} - -impl Error for FromEnvError { - fn source(&self) -> Option<&(dyn Error + 'static)> { - match self.kind { - ErrorKind::Parse(ref p) => Some(p), - ErrorKind::Env(ref e) => Some(e), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use tracing_core::field::FieldSet; - use tracing_core::*; - - struct NoSubscriber; - impl Subscriber for NoSubscriber { - #[inline] - fn register_callsite(&self, _: &'static Metadata<'static>) -> subscriber::Interest { - subscriber::Interest::always() - } - fn new_span(&self, _: &span::Attributes<'_>) -> span::Id { - span::Id::from_u64(0xDEAD) - } - fn event(&self, _event: &Event<'_>) {} - fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {} - fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {} - - #[inline] - fn enabled(&self, _metadata: &Metadata<'_>) -> bool { - true - } - fn enter(&self, _span: &span::Id) {} - fn exit(&self, _span: &span::Id) {} - } - - struct Cs; - impl Callsite for Cs { - fn set_interest(&self, _interest: Interest) {} - fn metadata(&self) -> &Metadata<'_> { - unimplemented!() - } - } - - #[test] - fn callsite_enabled_no_span_directive() { - let filter = EnvFilter::new("app=debug").with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::TRACE, - None, - None, - None, - FieldSet::new(&[], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_never()); - } - - #[test] - fn callsite_off() { - let filter = EnvFilter::new("app=off").with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::ERROR, - None, - None, - None, - FieldSet::new(&[], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_never()); - } - - #[test] - fn callsite_enabled_includes_span_directive() { - let filter = EnvFilter::new("app[mySpan]=debug").with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::TRACE, - None, - None, - None, - FieldSet::new(&[], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_always()); - } - - #[test] - fn callsite_enabled_includes_span_directive_field() { - let filter = - EnvFilter::new("app[mySpan{field=\"value\"}]=debug").with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::TRACE, - None, - None, - None, - FieldSet::new(&["field"], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_always()); - } - - #[test] - fn callsite_enabled_includes_span_directive_multiple_fields() { - let filter = EnvFilter::new("app[mySpan{field=\"value\",field2=2}]=debug") - .with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::TRACE, - None, - None, - None, - FieldSet::new(&["field"], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_never()); - } - - #[test] - fn roundtrip() { - let f1: EnvFilter = - "[span1{foo=1}]=error,[span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug" - .parse() - .unwrap(); - let f2: EnvFilter = format!("{}", f1).parse().unwrap(); - assert_eq!(f1.statics, f2.statics); - assert_eq!(f1.dynamics, f2.dynamics); - } - - #[test] - fn size_of_filters() { - fn print_sz(s: &str) { - let filter = s.parse::().expect("filter should parse"); - println!( - "size_of_val({:?})\n -> {}B", - s, - std::mem::size_of_val(&filter) - ); - } - - print_sz("info"); - - print_sz("foo=debug"); - - print_sz( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off", - ); - - print_sz("[span1{foo=1}]=error,[span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug"); - - print_sz( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off,[span1{foo=1}]=error,\ - [span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug", - ); - } -} diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs b/vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs deleted file mode 100644 index 332bf860a..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs +++ /dev/null @@ -1,749 +0,0 @@ -use crate::{ - filter::LevelFilter, - layer::{Context, Layer}, -}; -use core::{any::type_name, fmt, marker::PhantomData}; -use tracing_core::{Interest, Metadata, Subscriber}; - -/// A filter implemented by a closure or function pointer that -/// determines whether a given span or event is enabled, based on its -/// [`Metadata`]. -/// -/// This type can be used for both [per-layer filtering][plf] (using its -/// [`Filter`] implementation) and [global filtering][global] (using its -/// [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// [`Metadata`]: tracing_core::Metadata -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -#[derive(Clone)] -pub struct FilterFn) -> bool> { - enabled: F, - max_level_hint: Option, -} - -/// A filter implemented by a closure or function pointer that -/// determines whether a given span or event is enabled _dynamically_, -/// potentially based on the current [span context]. -/// -/// This type can be used for both [per-layer filtering][plf] (using its -/// [`Filter`] implementation) and [global filtering][global] (using its -/// [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// [span context]: crate::layer::Context -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -pub struct DynFilterFn< - S, - // TODO(eliza): should these just be boxed functions? - F = fn(&Metadata<'_>, &Context<'_, S>) -> bool, - R = fn(&'static Metadata<'static>) -> Interest, -> { - enabled: F, - register_callsite: Option, - max_level_hint: Option, - _s: PhantomData, -} - -// === impl FilterFn === - -/// Constructs a [`FilterFn`], from a function or closure that returns `true` if -/// a span or event should be enabled, based on its [`Metadata`]. -/// -/// The returned [`FilterFn`] can be used for both [per-layer filtering][plf] -/// (using its [`Filter`] implementation) and [global filtering][global] (using -/// its [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// This is equivalent to calling [`FilterFn::new`]. -/// -/// [`Metadata`]: tracing_core::Metadata -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -/// -/// # Examples -/// -/// ``` -/// use tracing_subscriber::{ -/// layer::{Layer, SubscriberExt}, -/// filter, -/// util::SubscriberInitExt, -/// }; -/// -/// let my_filter = filter::filter_fn(|metadata| { -/// // Only enable spans or events with the target "interesting_things" -/// metadata.target() == "interesting_things" -/// }); -/// -/// let my_layer = tracing_subscriber::fmt::layer(); -/// -/// tracing_subscriber::registry() -/// .with(my_layer.with_filter(my_filter)) -/// .init(); -/// -/// // This event will not be enabled. -/// tracing::warn!("something important but uninteresting happened!"); -/// -/// // This event will be enabled. -/// tracing::debug!(target: "interesting_things", "an interesting minor detail..."); -/// ``` -pub fn filter_fn(f: F) -> FilterFn -where - F: Fn(&Metadata<'_>) -> bool, -{ - FilterFn::new(f) -} - -/// Constructs a [`DynFilterFn`] from a function or closure that returns `true` -/// if a span or event should be enabled within a particular [span context][`Context`]. -/// -/// This is equivalent to calling [`DynFilterFn::new`]. -/// -/// Unlike [`filter_fn`], this function takes a closure or function pointer -/// taking the [`Metadata`] for a span or event *and* the current [`Context`]. -/// This means that a [`DynFilterFn`] can choose whether to enable spans or -/// events based on information about the _current_ span (or its parents). -/// -/// If this is *not* necessary, use [`filter_fn`] instead. -/// -/// The returned [`DynFilterFn`] can be used for both [per-layer filtering][plf] -/// (using its [`Filter`] implementation) and [global filtering][global] (using -/// its [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// # Examples -/// -/// ``` -/// use tracing_subscriber::{ -/// layer::{Layer, SubscriberExt}, -/// filter, -/// util::SubscriberInitExt, -/// }; -/// -/// // Only enable spans or events within a span named "interesting_span". -/// let my_filter = filter::dynamic_filter_fn(|metadata, cx| { -/// // If this *is* "interesting_span", make sure to enable it. -/// if metadata.is_span() && metadata.name() == "interesting_span" { -/// return true; -/// } -/// -/// // Otherwise, are we in an interesting span? -/// if let Some(current_span) = cx.lookup_current() { -/// return current_span.name() == "interesting_span"; -/// } -/// -/// false -/// }); -/// -/// let my_layer = tracing_subscriber::fmt::layer(); -/// -/// tracing_subscriber::registry() -/// .with(my_layer.with_filter(my_filter)) -/// .init(); -/// -/// // This event will not be enabled. -/// tracing::info!("something happened"); -/// -/// tracing::info_span!("interesting_span").in_scope(|| { -/// // This event will be enabled. -/// tracing::debug!("something else happened"); -/// }); -/// ``` -/// -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -/// [`Context`]: crate::layer::Context -/// [`Metadata`]: tracing_core::Metadata -pub fn dynamic_filter_fn(f: F) -> DynFilterFn -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, -{ - DynFilterFn::new(f) -} - -impl FilterFn -where - F: Fn(&Metadata<'_>) -> bool, -{ - /// Constructs a [`FilterFn`] from a function or closure that returns `true` - /// if a span or event should be enabled, based on its [`Metadata`]. - /// - /// If determining whether a span or event should be enabled also requires - /// information about the current span context, use [`DynFilterFn`] instead. - /// - /// See the [documentation on per-layer filtering][plf] for details on using - /// [`Filter`]s. - /// - /// [`Filter`]: crate::layer::Filter - /// [plf]: crate::layer#per-layer-filtering - /// [`Metadata`]: tracing_core::Metadata - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::FilterFn, - /// util::SubscriberInitExt, - /// }; - /// - /// let my_filter = FilterFn::new(|metadata| { - /// // Only enable spans or events with the target "interesting_things" - /// metadata.target() == "interesting_things" - /// }); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// - /// // This event will not be enabled. - /// tracing::warn!("something important but uninteresting happened!"); - /// - /// // This event will be enabled. - /// tracing::debug!(target: "interesting_things", "an interesting minor detail..."); - /// ``` - pub fn new(enabled: F) -> Self { - Self { - enabled, - max_level_hint: None, - } - } - - /// Sets the highest verbosity [`Level`] the filter function will enable. - /// - /// The value passed to this method will be returned by this `FilterFn`'s - /// [`Filter::max_level_hint`] method. - /// - /// If the provided function will not enable all levels, it is recommended - /// to call this method to configure it with the most verbose level it will - /// enable. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::{filter_fn, LevelFilter}, - /// util::SubscriberInitExt, - /// }; - /// use tracing_core::Level; - /// - /// let my_filter = filter_fn(|metadata| { - /// // Only enable spans or events with targets starting with `my_crate` - /// // and levels at or below `INFO`. - /// metadata.level() <= &Level::INFO && metadata.target().starts_with("my_crate") - /// }) - /// // Since the filter closure will only enable the `INFO` level and - /// // below, set the max level hint - /// .with_max_level_hint(LevelFilter::INFO); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// ``` - /// - /// [`Level`]: tracing_core::Level - /// [`Filter::max_level_hint`]: crate::layer::Filter::max_level_hint - pub fn with_max_level_hint(self, max_level_hint: impl Into) -> Self { - Self { - max_level_hint: Some(max_level_hint.into()), - ..self - } - } - - #[inline] - pub(in crate::filter) fn is_enabled(&self, metadata: &Metadata<'_>) -> bool { - let enabled = (self.enabled)(metadata); - debug_assert!( - !enabled || self.is_below_max_level(metadata), - "FilterFn<{}> claimed it would only enable {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - - enabled - } - - #[inline] - pub(in crate::filter) fn is_callsite_enabled( - &self, - metadata: &'static Metadata<'static>, - ) -> Interest { - // Because `self.enabled` takes a `Metadata` only (and no `Context` - // parameter), we can reasonably assume its results are cachable, and - // just return `Interest::always`/`Interest::never`. - if (self.enabled)(metadata) { - debug_assert!( - self.is_below_max_level(metadata), - "FilterFn<{}> claimed it was only interested in {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - return Interest::always(); - } - - Interest::never() - } - - fn is_below_max_level(&self, metadata: &Metadata<'_>) -> bool { - self.max_level_hint - .as_ref() - .map(|hint| metadata.level() <= hint) - .unwrap_or(true) - } -} - -impl Layer for FilterFn -where - F: Fn(&Metadata<'_>) -> bool + 'static, - S: Subscriber, -{ - fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { - self.is_enabled(metadata) - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - self.is_callsite_enabled(metadata) - } - - fn max_level_hint(&self) -> Option { - self.max_level_hint - } -} - -impl From for FilterFn -where - F: Fn(&Metadata<'_>) -> bool, -{ - fn from(enabled: F) -> Self { - Self::new(enabled) - } -} - -impl fmt::Debug for FilterFn { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FilterFn") - .field("enabled", &format_args!("{}", type_name::())) - .field("max_level_hint", &self.max_level_hint) - .finish() - } -} - -// === impl DynFilterFn == - -impl DynFilterFn -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, -{ - /// Constructs a [`Filter`] from a function or closure that returns `true` - /// if a span or event should be enabled in the current [span - /// context][`Context`]. - /// - /// Unlike [`FilterFn`], a `DynFilterFn` is constructed from a closure or - /// function pointer that takes both the [`Metadata`] for a span or event - /// *and* the current [`Context`]. This means that a [`DynFilterFn`] can - /// choose whether to enable spans or events based on information about the - /// _current_ span (or its parents). - /// - /// If this is *not* necessary, use [`FilterFn`] instead. - /// - /// See the [documentation on per-layer filtering][plf] for details on using - /// [`Filter`]s. - /// - /// [`Filter`]: crate::layer::Filter - /// [plf]: crate::layer#per-layer-filtering - /// [`Context`]: crate::layer::Context - /// [`Metadata`]: tracing_core::Metadata - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::DynFilterFn, - /// util::SubscriberInitExt, - /// }; - /// - /// // Only enable spans or events within a span named "interesting_span". - /// let my_filter = DynFilterFn::new(|metadata, cx| { - /// // If this *is* "interesting_span", make sure to enable it. - /// if metadata.is_span() && metadata.name() == "interesting_span" { - /// return true; - /// } - /// - /// // Otherwise, are we in an interesting span? - /// if let Some(current_span) = cx.lookup_current() { - /// return current_span.name() == "interesting_span"; - /// } - /// - /// false - /// }); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// - /// // This event will not be enabled. - /// tracing::info!("something happened"); - /// - /// tracing::info_span!("interesting_span").in_scope(|| { - /// // This event will be enabled. - /// tracing::debug!("something else happened"); - /// }); - /// ``` - pub fn new(enabled: F) -> Self { - Self { - enabled, - register_callsite: None, - max_level_hint: None, - _s: PhantomData, - } - } -} - -impl DynFilterFn -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, -{ - /// Sets the highest verbosity [`Level`] the filter function will enable. - /// - /// The value passed to this method will be returned by this `DynFilterFn`'s - /// [`Filter::max_level_hint`] method. - /// - /// If the provided function will not enable all levels, it is recommended - /// to call this method to configure it with the most verbose level it will - /// enable. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::{DynFilterFn, LevelFilter}, - /// util::SubscriberInitExt, - /// }; - /// use tracing_core::Level; - /// - /// // Only enable spans or events with levels at or below `INFO`, if - /// // we are inside a span called "interesting_span". - /// let my_filter = DynFilterFn::new(|metadata, cx| { - /// // If the level is greater than INFO, disable it. - /// if metadata.level() > &Level::INFO { - /// return false; - /// } - /// - /// // If any span in the current scope is named "interesting_span", - /// // enable this span or event. - /// for span in cx.lookup_current().iter().flat_map(|span| span.scope()) { - /// if span.name() == "interesting_span" { - /// return true; - /// } - /// } - /// - /// // Otherwise, disable it. - /// false - /// }) - /// // Since the filter closure will only enable the `INFO` level and - /// // below, set the max level hint - /// .with_max_level_hint(LevelFilter::INFO); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// ``` - /// - /// [`Level`]: tracing_core::Level - /// [`Filter::max_level_hint`]: crate::layer::Filter::max_level_hint - pub fn with_max_level_hint(self, max_level_hint: impl Into) -> Self { - Self { - max_level_hint: Some(max_level_hint.into()), - ..self - } - } - - /// Adds a function for filtering callsites to this filter. - /// - /// When this filter's [`Filter::callsite_enabled`][cse] method is called, - /// the provided function will be used rather than the default. - /// - /// By default, `DynFilterFn` assumes that, because the filter _may_ depend - /// dynamically on the current [span context], its result should never be - /// cached. However, some filtering strategies may require dynamic information - /// from the current span context in *some* cases, but are able to make - /// static filtering decisions from [`Metadata`] alone in others. - /// - /// For example, consider the filter given in the example for - /// [`DynFilterFn::new`]. That filter enables all spans named - /// "interesting_span", and any events and spans that occur inside of an - /// interesting span. Since the span's name is part of its static - /// [`Metadata`], the "interesting_span" can be enabled in - /// [`callsite_enabled`][cse]: - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::DynFilterFn, - /// util::SubscriberInitExt, - /// }; - /// use tracing_core::subscriber::Interest; - /// - /// // Only enable spans or events within a span named "interesting_span". - /// let my_filter = DynFilterFn::new(|metadata, cx| { - /// // If this *is* "interesting_span", make sure to enable it. - /// if metadata.is_span() && metadata.name() == "interesting_span" { - /// return true; - /// } - /// - /// // Otherwise, are we in an interesting span? - /// if let Some(current_span) = cx.lookup_current() { - /// return current_span.name() == "interesting_span"; - /// } - /// - /// false - /// }).with_callsite_filter(|metadata| { - /// // If this is an "interesting_span", we know we will always - /// // enable it. - /// if metadata.is_span() && metadata.name() == "interesting_span" { - /// return Interest::always(); - /// } - /// - /// // Otherwise, it depends on whether or not we're in an interesting - /// // span. You'll have to ask us again for each span/event! - /// Interest::sometimes() - /// }); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// ``` - /// - /// [cse]: crate::layer::Filter::callsite_enabled - /// [`enabled`]: crate::layer::Filter::enabled - /// [`Metadata`]: tracing_core::Metadata - /// [span context]: crate::layer::Context - pub fn with_callsite_filter(self, callsite_enabled: R2) -> DynFilterFn - where - R2: Fn(&'static Metadata<'static>) -> Interest, - { - let register_callsite = Some(callsite_enabled); - let DynFilterFn { - enabled, - max_level_hint, - _s, - .. - } = self; - DynFilterFn { - enabled, - register_callsite, - max_level_hint, - _s, - } - } - - fn default_callsite_enabled(&self, metadata: &Metadata<'_>) -> Interest { - // If it's below the configured max level, assume that `enabled` will - // never enable it... - if !is_below_max_level(&self.max_level_hint, metadata) { - debug_assert!( - !(self.enabled)(metadata, &Context::none()), - "DynFilterFn<{}> claimed it would only enable {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - return Interest::never(); - } - - // Otherwise, since this `enabled` function is dynamic and depends on - // the current context, we don't know whether this span or event will be - // enabled or not. Ask again every time it's recorded! - Interest::sometimes() - } -} - -impl DynFilterFn -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, - R: Fn(&'static Metadata<'static>) -> Interest, -{ - #[inline] - fn is_enabled(&self, metadata: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - let enabled = (self.enabled)(metadata, cx); - debug_assert!( - !enabled || is_below_max_level(&self.max_level_hint, metadata), - "DynFilterFn<{}> claimed it would only enable {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - - enabled - } - - #[inline] - fn is_callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - let interest = self - .register_callsite - .as_ref() - .map(|callsite_enabled| callsite_enabled(metadata)) - .unwrap_or_else(|| self.default_callsite_enabled(metadata)); - debug_assert!( - interest.is_never() || is_below_max_level(&self.max_level_hint, metadata), - "DynFilterFn<{}, {}> claimed it was only interested in {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::(), - type_name::(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - - interest - } -} - -impl Layer for DynFilterFn -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool + 'static, - R: Fn(&'static Metadata<'static>) -> Interest + 'static, - S: Subscriber, -{ - fn enabled(&self, metadata: &Metadata<'_>, cx: Context<'_, S>) -> bool { - self.is_enabled(metadata, &cx) - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - self.is_callsite_enabled(metadata) - } - - fn max_level_hint(&self) -> Option { - self.max_level_hint - } -} - -impl fmt::Debug for DynFilterFn { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut s = f.debug_struct("DynFilterFn"); - s.field("enabled", &format_args!("{}", type_name::())); - if self.register_callsite.is_some() { - s.field( - "register_callsite", - &format_args!("Some({})", type_name::()), - ); - } else { - s.field("register_callsite", &format_args!("None")); - } - - s.field("max_level_hint", &self.max_level_hint).finish() - } -} - -impl Clone for DynFilterFn -where - F: Clone, - R: Clone, -{ - fn clone(&self) -> Self { - Self { - enabled: self.enabled.clone(), - register_callsite: self.register_callsite.clone(), - max_level_hint: self.max_level_hint, - _s: PhantomData, - } - } -} - -impl From for DynFilterFn -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, -{ - fn from(f: F) -> Self { - Self::new(f) - } -} - -// === PLF impls === - -feature! { - #![all(feature = "registry", feature = "std")] - use crate::layer::Filter; - - impl Filter for FilterFn - where - F: Fn(&Metadata<'_>) -> bool, - { - fn enabled(&self, metadata: &Metadata<'_>, _: &Context<'_, S>) -> bool { - self.is_enabled(metadata) - } - - fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - self.is_callsite_enabled(metadata) - } - - fn max_level_hint(&self) -> Option { - self.max_level_hint - } - } - - impl Filter for DynFilterFn - where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, - R: Fn(&'static Metadata<'static>) -> Interest, - { - fn enabled(&self, metadata: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - self.is_enabled(metadata, cx) - } - - fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - self.is_callsite_enabled(metadata) - } - - fn max_level_hint(&self) -> Option { - self.max_level_hint - } - } -} - -fn is_below_max_level(hint: &Option, metadata: &Metadata<'_>) -> bool { - hint.as_ref() - .map(|hint| metadata.level() <= hint) - .unwrap_or(true) -} diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs b/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs deleted file mode 100644 index e77fd3751..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs +++ /dev/null @@ -1,830 +0,0 @@ -//! ## Per-Layer Filtering -//! -//! Per-layer filters permit individual `Layer`s to have their own filter -//! configurations without interfering with other `Layer`s. -//! -//! This module is not public; the public APIs defined in this module are -//! re-exported in the top-level `filter` module. Therefore, this documentation -//! primarily concerns the internal implementation details. For the user-facing -//! public API documentation, see the individual public types in this module, as -//! well as the, see the `Layer` trait documentation's [per-layer filtering -//! section]][1]. -//! -//! ## How does per-layer filtering work? -//! -//! As described in the API documentation, the [`Filter`] trait defines a -//! filtering strategy for a per-layer filter. We expect there will be a variety -//! of implementations of [`Filter`], both in `tracing-subscriber` and in user -//! code. -//! -//! To actually *use* a [`Filter`] implementation, it is combined with a -//! [`Layer`] by the [`Filtered`] struct defined in this module. [`Filtered`] -//! implements [`Layer`] by calling into the wrapped [`Layer`], or not, based on -//! the filtering strategy. While there will be a variety of types that implement -//! [`Filter`], all actual *uses* of per-layer filtering will occur through the -//! [`Filtered`] struct. Therefore, most of the implementation details live -//! there. -//! -//! [1]: crate::layer#per-layer-filtering -//! [`Filter`]: crate::layer::Filter -use crate::{ - filter::LevelFilter, - layer::{self, Context, Layer}, - registry, -}; -use std::{ - any::TypeId, - cell::{Cell, RefCell}, - fmt, - marker::PhantomData, - sync::Arc, - thread_local, -}; -use tracing_core::{ - span, - subscriber::{Interest, Subscriber}, - Event, Metadata, -}; - -/// A [`Layer`] that wraps an inner [`Layer`] and adds a [`Filter`] which -/// controls what spans and events are enabled for that layer. -/// -/// This is returned by the [`Layer::with_filter`] method. See the -/// [documentation on per-layer filtering][plf] for details. -/// -/// [`Filter`]: crate::layer::Filter -/// [plf]: crate::layer#per-layer-filtering -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -#[derive(Clone)] -pub struct Filtered { - filter: F, - layer: L, - id: MagicPlfDowncastMarker, - _s: PhantomData, -} - -/// Uniquely identifies an individual [`Filter`] instance in the context of -/// a [`Subscriber`]. -/// -/// When adding a [`Filtered`] [`Layer`] to a [`Subscriber`], the [`Subscriber`] -/// generates a `FilterId` for that [`Filtered`] layer. The [`Filtered`] layer -/// will then use the generated ID to query whether a particular span was -/// previously enabled by that layer's [`Filter`]. -/// -/// **Note**: Currently, the [`Registry`] type provided by this crate is the -/// **only** [`Subscriber`] implementation capable of participating in per-layer -/// filtering. Therefore, the `FilterId` type cannot currently be constructed by -/// code outside of `tracing-subscriber`. In the future, new APIs will be added to `tracing-subscriber` to -/// allow non-Registry [`Subscriber`]s to also participate in per-layer -/// filtering. When those APIs are added, subscribers will be responsible -/// for generating and assigning `FilterId`s. -/// -/// [`Filter`]: crate::layer::Filter -/// [`Subscriber`]: tracing_core::Subscriber -/// [`Layer`]: crate::layer::Layer -/// [`Registry`]: crate::registry::Registry -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -#[derive(Copy, Clone)] -pub struct FilterId(u64); - -/// A bitmap tracking which [`FilterId`]s have enabled a given span or -/// event. -/// -/// This is currently a private type that's used exclusively by the -/// [`Registry`]. However, in the future, this may become a public API, in order -/// to allow user subscribers to host [`Filter`]s. -/// -/// [`Registry`]: crate::Registry -/// [`Filter`]: crate::layer::Filter -#[derive(Default, Copy, Clone, Eq, PartialEq)] -pub(crate) struct FilterMap { - bits: u64, -} - -/// The current state of `enabled` calls to per-layer filters on this -/// thread. -/// -/// When `Filtered::enabled` is called, the filter will set the bit -/// corresponding to its ID if the filter will disable the event/span being -/// filtered. When the event or span is recorded, the per-layer filter will -/// check its bit to determine if it disabled that event or span, and skip -/// forwarding the event or span to the inner layer if the bit is set. Once -/// a span or event has been skipped by a per-layer filter, it unsets its -/// bit, so that the `FilterMap` has been cleared for the next set of -/// `enabled` calls. -/// -/// FilterState is also read by the `Registry`, for two reasons: -/// -/// 1. When filtering a span, the Registry must store the `FilterMap` -/// generated by `Filtered::enabled` calls for that span as part of the -/// span's per-span data. This allows `Filtered` layers to determine -/// whether they had previously disabled a given span, and avoid showing it -/// to the wrapped layer if it was disabled. -/// -/// This allows `Filtered` layers to also filter out the spans they -/// disable from span traversals (such as iterating over parents, etc). -/// 2. If all the bits are set, then every per-layer filter has decided it -/// doesn't want to enable that span or event. In that case, the -/// `Registry`'s `enabled` method will return `false`, so that -/// recording a span or event can be skipped entirely. -#[derive(Debug)] -pub(crate) struct FilterState { - enabled: Cell, - // TODO(eliza): `Interest`s should _probably_ be `Copy`. The only reason - // they're not is our Obsessive Commitment to Forwards-Compatibility. If - // this changes in tracing-core`, we can make this a `Cell` rather than - // `RefCell`... - interest: RefCell>, - - #[cfg(debug_assertions)] - counters: DebugCounters, -} - -/// Extra counters added to `FilterState` used only to make debug assertions. -#[cfg(debug_assertions)] -#[derive(Debug, Default)] -struct DebugCounters { - /// How many per-layer filters have participated in the current `enabled` - /// call? - in_filter_pass: Cell, - - /// How many per-layer filters have participated in the current `register_callsite` - /// call? - in_interest_pass: Cell, -} - -thread_local! { - pub(crate) static FILTERING: FilterState = FilterState::new(); -} - -// === impl Filter === -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -impl layer::Filter for LevelFilter { - fn enabled(&self, meta: &Metadata<'_>, _: &Context<'_, S>) -> bool { - meta.level() <= self - } - - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - if meta.level() <= self { - Interest::always() - } else { - Interest::never() - } - } - - fn max_level_hint(&self) -> Option { - Some(*self) - } -} - -impl layer::Filter for Arc + Send + Sync + 'static> { - #[inline] - fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - (**self).enabled(meta, cx) - } - - #[inline] - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - (**self).callsite_enabled(meta) - } - - #[inline] - fn max_level_hint(&self) -> Option { - (**self).max_level_hint() - } -} - -impl layer::Filter for Box + Send + Sync + 'static> { - #[inline] - fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - (**self).enabled(meta, cx) - } - - #[inline] - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - (**self).callsite_enabled(meta) - } - - #[inline] - fn max_level_hint(&self) -> Option { - (**self).max_level_hint() - } -} - -// === impl Filtered === - -impl Filtered { - /// Wraps the provided [`Layer`] so that it is filtered by the given - /// [`Filter`]. - /// - /// This is equivalent to calling the [`Layer::with_filter`] method. - /// - /// See the [documentation on per-layer filtering][plf] for details. - /// - /// [`Filter`]: crate::layer::Filter - /// [plf]: crate::layer#per-layer-filtering - pub fn new(layer: L, filter: F) -> Self { - Self { - layer, - filter, - id: MagicPlfDowncastMarker(FilterId::disabled()), - _s: PhantomData, - } - } - - #[inline(always)] - fn id(&self) -> FilterId { - debug_assert!( - !self.id.0.is_disabled(), - "a `Filtered` layer was used, but it had no `FilterId`; \ - was it registered with the subscriber?" - ); - self.id.0 - } - - fn did_enable(&self, f: impl FnOnce()) { - FILTERING.with(|filtering| filtering.did_enable(self.id(), f)) - } -} - -impl Layer for Filtered -where - S: Subscriber + for<'span> registry::LookupSpan<'span> + 'static, - F: layer::Filter + 'static, - L: Layer, -{ - fn on_layer(&mut self, subscriber: &mut S) { - self.id = MagicPlfDowncastMarker(subscriber.register_filter()); - self.layer.on_layer(subscriber); - } - - // TODO(eliza): can we figure out a nice way to make the `Filtered` layer - // not call `is_enabled_for` in hooks that the inner layer doesn't actually - // have real implementations of? probably not... - // - // it would be cool if there was some wild rust reflection way of checking - // if a trait impl has the default impl of a trait method or not, but that's - // almsot certainly impossible...right? - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - let interest = self.filter.callsite_enabled(metadata); - - // If the filter didn't disable the callsite, allow the inner layer to - // register it — since `register_callsite` is also used for purposes - // such as reserving/caching per-callsite data, we want the inner layer - // to be able to perform any other registration steps. However, we'll - // ignore its `Interest`. - if !interest.is_never() { - self.layer.register_callsite(metadata); - } - - // Add our `Interest` to the current sum of per-layer filter `Interest`s - // for this callsite. - FILTERING.with(|filtering| filtering.add_interest(interest)); - - // don't short circuit! if the stack consists entirely of `Layer`s with - // per-layer filters, the `Registry` will return the actual `Interest` - // value that's the sum of all the `register_callsite` calls to those - // per-layer filters. if we returned an actual `never` interest here, a - // `Layered` layer would short-circuit and not allow any `Filtered` - // layers below us if _they_ are interested in the callsite. - Interest::always() - } - - fn enabled(&self, metadata: &Metadata<'_>, cx: Context<'_, S>) -> bool { - let cx = cx.with_filter(self.id()); - let enabled = self.filter.enabled(metadata, &cx); - FILTERING.with(|filtering| filtering.set(self.id(), enabled)); - - if enabled { - // If the filter enabled this metadata, ask the wrapped layer if - // _it_ wants it --- it might have a global filter. - self.layer.enabled(metadata, cx) - } else { - // Otherwise, return `true`. The _per-layer_ filter disabled this - // metadata, but returning `false` in `Layer::enabled` will - // short-circuit and globally disable the span or event. This is - // *not* what we want for per-layer filters, as other layers may - // still want this event. Returning `true` here means we'll continue - // asking the next layer in the stack. - // - // Once all per-layer filters have been evaluated, the `Registry` - // at the root of the stack will return `false` from its `enabled` - // method if *every* per-layer filter disabled this metadata. - // Otherwise, the individual per-layer filters will skip the next - // `new_span` or `on_event` call for their layer if *they* disabled - // the span or event, but it was not globally disabled. - true - } - } - - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, cx: Context<'_, S>) { - self.did_enable(|| { - self.layer.on_new_span(attrs, id, cx.with_filter(self.id())); - }) - } - - #[doc(hidden)] - fn max_level_hint(&self) -> Option { - self.filter.max_level_hint() - } - - fn on_record(&self, span: &span::Id, values: &span::Record<'_>, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(span, self.id()) { - self.layer.on_record(span, values, cx) - } - } - - fn on_follows_from(&self, span: &span::Id, follows: &span::Id, cx: Context<'_, S>) { - // only call `on_follows_from` if both spans are enabled by us - if cx.is_enabled_for(span, self.id()) && cx.is_enabled_for(follows, self.id()) { - self.layer - .on_follows_from(span, follows, cx.with_filter(self.id())) - } - } - - fn on_event(&self, event: &Event<'_>, cx: Context<'_, S>) { - self.did_enable(|| { - self.layer.on_event(event, cx.with_filter(self.id())); - }) - } - - fn on_enter(&self, id: &span::Id, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(id, self.id()) { - self.layer.on_enter(id, cx) - } - } - - fn on_exit(&self, id: &span::Id, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(id, self.id()) { - self.layer.on_exit(id, cx) - } - } - - fn on_close(&self, id: span::Id, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(&id, self.id()) { - self.layer.on_close(id, cx) - } - } - - // XXX(eliza): the existence of this method still makes me sad... - fn on_id_change(&self, old: &span::Id, new: &span::Id, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(old, self.id()) { - self.layer.on_id_change(old, new, cx) - } - } - - #[doc(hidden)] - #[inline] - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - match id { - id if id == TypeId::of::() => Some(self as *const _ as *const ()), - id if id == TypeId::of::() => Some(&self.layer as *const _ as *const ()), - id if id == TypeId::of::() => Some(&self.filter as *const _ as *const ()), - id if id == TypeId::of::() => { - Some(&self.id as *const _ as *const ()) - } - _ => self.layer.downcast_raw(id), - } - } -} - -impl fmt::Debug for Filtered -where - F: fmt::Debug, - L: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Filtered") - .field("filter", &self.filter) - .field("layer", &self.layer) - .field("id", &self.id) - .finish() - } -} - -// === impl FilterId === - -impl FilterId { - const fn disabled() -> Self { - Self(std::u64::MAX) - } - - /// Returns a `FilterId` that will consider _all_ spans enabled. - pub(crate) const fn none() -> Self { - Self(0) - } - - pub(crate) fn new(id: u8) -> Self { - assert!(id < 64, "filter IDs may not be greater than 64"); - Self(1 << id as usize) - } - - /// Combines two `FilterId`s, returning a new `FilterId` that will match a - /// [`FilterMap`] where the span was disabled by _either_ this `FilterId` - /// *or* the combined `FilterId`. - /// - /// This method is called by [`Context`]s when adding the `FilterId` of a - /// [`Filtered`] layer to the context. - /// - /// This is necessary for cases where we have a tree of nested [`Filtered`] - /// layers, like this: - /// - /// ```text - /// Filtered { - /// filter1, - /// Layered { - /// layer1, - /// Filtered { - /// filter2, - /// layer2, - /// }, - /// } - /// ``` - /// - /// We want `layer2` to be affected by both `filter1` _and_ `filter2`. - /// Without combining `FilterId`s, this works fine when filtering - /// `on_event`/`new_span`, because the outer `Filtered` layer (`filter1`) - /// won't call the inner layer's `on_event` or `new_span` callbacks if it - /// disabled the event/span. - /// - /// However, it _doesn't_ work when filtering span lookups and traversals - /// (e.g. `scope`). This is because the [`Context`] passed to `layer2` - /// would set its filter ID to the filter ID of `filter2`, and would skip - /// spans that were disabled by `filter2`. However, what if a span was - /// disabled by `filter1`? We wouldn't see it in `new_span`, but we _would_ - /// see it in lookups and traversals...which we don't want. - /// - /// When a [`Filtered`] layer adds its ID to a [`Context`], it _combines_ it - /// with any previous filter ID that the context had, rather than replacing - /// it. That way, `layer2`'s context will check if a span was disabled by - /// `filter1` _or_ `filter2`. The way we do this, instead of representing - /// `FilterId`s as a number number that we shift a 1 over by to get a mask, - /// we just store the actual mask,so we can combine them with a bitwise-OR. - /// - /// For example, if we consider the following case (pretending that the - /// masks are 8 bits instead of 64 just so i don't have to write out a bunch - /// of extra zeroes): - /// - /// - `filter1` has the filter id 1 (`0b0000_0001`) - /// - `filter2` has the filter id 2 (`0b0000_0010`) - /// - /// A span that gets disabled by filter 1 would have the [`FilterMap`] with - /// bits `0b0000_0001`. - /// - /// If the `FilterId` was internally represented as `(bits to shift + 1), - /// when `layer2`'s [`Context`] checked if it enabled the span, it would - /// make the mask `0b0000_0010` (`1 << 1`). That bit would not be set in the - /// [`FilterMap`], so it would see that it _didn't_ disable the span. Which - /// is *true*, it just doesn't reflect the tree-like shape of the actual - /// subscriber. - /// - /// By having the IDs be masks instead of shifts, though, when the - /// [`Filtered`] with `filter2` gets the [`Context`] with `filter1`'s filter ID, - /// instead of replacing it, it ors them together: - /// - /// ```ignore - /// 0b0000_0001 | 0b0000_0010 == 0b0000_0011; - /// ``` - /// - /// We then test if the span was disabled by seeing if _any_ bits in the - /// mask are `1`: - /// - /// ```ignore - /// filtermap & mask != 0; - /// 0b0000_0001 & 0b0000_0011 != 0; - /// 0b0000_0001 != 0; - /// true; - /// ``` - /// - /// [`Context`]: crate::layer::Context - pub(crate) fn and(self, FilterId(other): Self) -> Self { - // If this mask is disabled, just return the other --- otherwise, we - // would always see that every span is disabled. - if self.0 == Self::disabled().0 { - return Self(other); - } - - Self(self.0 | other) - } - - fn is_disabled(self) -> bool { - self.0 == Self::disabled().0 - } -} - -impl fmt::Debug for FilterId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // don't print a giant set of the numbers 0..63 if the filter ID is disabled. - if self.0 == Self::disabled().0 { - return f - .debug_tuple("FilterId") - .field(&format_args!("DISABLED")) - .finish(); - } - - if f.alternate() { - f.debug_struct("FilterId") - .field("ids", &format_args!("{:?}", FmtBitset(self.0))) - .field("bits", &format_args!("{:b}", self.0)) - .finish() - } else { - f.debug_tuple("FilterId").field(&FmtBitset(self.0)).finish() - } - } -} - -impl fmt::Binary for FilterId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("FilterId") - .field(&format_args!("{:b}", self.0)) - .finish() - } -} - -// === impl FilterMap === - -impl FilterMap { - pub(crate) fn set(self, FilterId(mask): FilterId, enabled: bool) -> Self { - if mask == std::u64::MAX { - return self; - } - - if enabled { - Self { - bits: self.bits & (!mask), - } - } else { - Self { - bits: self.bits | mask, - } - } - } - - #[inline] - pub(crate) fn is_enabled(self, FilterId(mask): FilterId) -> bool { - self.bits & mask == 0 - } - - #[inline] - pub(crate) fn any_enabled(self) -> bool { - self.bits != std::u64::MAX - } -} - -impl fmt::Debug for FilterMap { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let alt = f.alternate(); - let mut s = f.debug_struct("FilterMap"); - s.field("disabled_by", &format_args!("{:?}", &FmtBitset(self.bits))); - - if alt { - s.field("bits", &format_args!("{:b}", self.bits)); - } - - s.finish() - } -} - -impl fmt::Binary for FilterMap { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FilterMap") - .field("bits", &format_args!("{:b}", self.bits)) - .finish() - } -} - -// === impl FilterState === - -impl FilterState { - fn new() -> Self { - Self { - enabled: Cell::new(FilterMap::default()), - interest: RefCell::new(None), - - #[cfg(debug_assertions)] - counters: DebugCounters::default(), - } - } - - fn set(&self, filter: FilterId, enabled: bool) { - #[cfg(debug_assertions)] - { - let in_current_pass = self.counters.in_filter_pass.get(); - if in_current_pass == 0 { - debug_assert_eq!(self.enabled.get(), FilterMap::default()); - } - self.counters.in_filter_pass.set(in_current_pass + 1); - debug_assert_eq!( - self.counters.in_interest_pass.get(), - 0, - "if we are in or starting a filter pass, we must not be in an interest pass." - ) - } - - self.enabled.set(self.enabled.get().set(filter, enabled)) - } - - fn add_interest(&self, interest: Interest) { - let mut curr_interest = self.interest.borrow_mut(); - - #[cfg(debug_assertions)] - { - let in_current_pass = self.counters.in_interest_pass.get(); - if in_current_pass == 0 { - debug_assert!(curr_interest.is_none()); - } - self.counters.in_interest_pass.set(in_current_pass + 1); - } - - if let Some(curr_interest) = curr_interest.as_mut() { - if (curr_interest.is_always() && !interest.is_always()) - || (curr_interest.is_never() && !interest.is_never()) - { - *curr_interest = Interest::sometimes(); - } - // If the two interests are the same, do nothing. If the current - // interest is `sometimes`, stay sometimes. - } else { - *curr_interest = Some(interest); - } - } - - pub(crate) fn event_enabled() -> bool { - FILTERING - .try_with(|this| { - let enabled = this.enabled.get().any_enabled(); - #[cfg(debug_assertions)] - { - if this.counters.in_filter_pass.get() == 0 { - debug_assert_eq!(this.enabled.get(), FilterMap::default()); - } - - // Nothing enabled this event, we won't tick back down the - // counter in `did_enable`. Reset it. - if !enabled { - this.counters.in_filter_pass.set(0); - } - } - enabled - }) - .unwrap_or(true) - } - - /// Executes a closure if the filter with the provided ID did not disable - /// the current span/event. - /// - /// This is used to implement the `on_event` and `new_span` methods for - /// `Filtered`. - fn did_enable(&self, filter: FilterId, f: impl FnOnce()) { - let map = self.enabled.get(); - if map.is_enabled(filter) { - // If the filter didn't disable the current span/event, run the - // callback. - f(); - } else { - // Otherwise, if this filter _did_ disable the span or event - // currently being processed, clear its bit from this thread's - // `FilterState`. The bit has already been "consumed" by skipping - // this callback, and we need to ensure that the `FilterMap` for - // this thread is reset when the *next* `enabled` call occurs. - self.enabled.set(map.set(filter, true)); - } - #[cfg(debug_assertions)] - { - let in_current_pass = self.counters.in_filter_pass.get(); - if in_current_pass <= 1 { - debug_assert_eq!(self.enabled.get(), FilterMap::default()); - } - self.counters - .in_filter_pass - .set(in_current_pass.saturating_sub(1)); - debug_assert_eq!( - self.counters.in_interest_pass.get(), - 0, - "if we are in a filter pass, we must not be in an interest pass." - ) - } - } - - /// Clears the current in-progress filter state. - /// - /// This resets the [`FilterMap`] and current [`Interest`] as well as - /// clearing the debug counters. - pub(crate) fn clear_enabled() { - // Drop the `Result` returned by `try_with` --- if we are in the middle - // a panic and the thread-local has been torn down, that's fine, just - // ignore it ratehr than panicking. - let _ = FILTERING.try_with(|filtering| { - filtering.enabled.set(FilterMap::default()); - - #[cfg(debug_assertions)] - filtering.counters.in_filter_pass.set(0); - }); - } - - pub(crate) fn take_interest() -> Option { - FILTERING - .try_with(|filtering| { - #[cfg(debug_assertions)] - { - if filtering.counters.in_interest_pass.get() == 0 { - debug_assert!(filtering.interest.try_borrow().ok()?.is_none()); - } - filtering.counters.in_interest_pass.set(0); - } - filtering.interest.try_borrow_mut().ok()?.take() - }) - .ok()? - } - - pub(crate) fn filter_map(&self) -> FilterMap { - let map = self.enabled.get(); - #[cfg(debug_assertions)] - { - if self.counters.in_filter_pass.get() == 0 { - debug_assert_eq!(map, FilterMap::default()); - } - } - - map - } -} -/// This is a horrible and bad abuse of the downcasting system to expose -/// *internally* whether a layer has per-layer filtering, within -/// `tracing-subscriber`, without exposing a public API for it. -/// -/// If a `Layer` has per-layer filtering, it will downcast to a -/// `MagicPlfDowncastMarker`. Since layers which contain other layers permit -/// downcasting to recurse to their children, this will do the Right Thing with -/// layers like Reload, Option, etc. -/// -/// Why is this a wrapper around the `FilterId`, you may ask? Because -/// downcasting works by returning a pointer, and we don't want to risk -/// introducing UB by constructing pointers that _don't_ point to a valid -/// instance of the type they claim to be. In this case, we don't _intend_ for -/// this pointer to be dereferenced, so it would actually be fine to return one -/// that isn't a valid pointer...but we can't guarantee that the caller won't -/// (accidentally) dereference it, so it's better to be safe than sorry. We -/// could, alternatively, add an additional field to the type that's used only -/// for returning pointers to as as part of the evil downcasting hack, but I -/// thought it was nicer to just add a `repr(transparent)` wrapper to the -/// existing `FilterId` field, since it won't make the struct any bigger. -/// -/// Don't worry, this isn't on the test. :) -#[derive(Clone, Copy)] -#[repr(transparent)] -struct MagicPlfDowncastMarker(FilterId); -impl fmt::Debug for MagicPlfDowncastMarker { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Just pretend that `MagicPlfDowncastMarker` doesn't exist for - // `fmt::Debug` purposes...if no one *sees* it in their `Debug` output, - // they don't have to know I thought this code would be a good idea. - fmt::Debug::fmt(&self.0, f) - } -} - -pub(crate) fn is_plf_downcast_marker(type_id: TypeId) -> bool { - type_id == TypeId::of::() -} - -/// Does a type implementing `Subscriber` contain any per-layer filters? -pub(crate) fn subscriber_has_plf(subscriber: &S) -> bool -where - S: Subscriber, -{ - (subscriber as &dyn Subscriber).is::() -} - -/// Does a type implementing `Layer` contain any per-layer filters? -pub(crate) fn layer_has_plf(layer: &L) -> bool -where - L: Layer, - S: Subscriber, -{ - unsafe { - // Safety: we're not actually *doing* anything with this pointer --- we - // only care about the `Option`, which we're turning into a `bool`. So - // even if the layer decides to be evil and give us some kind of invalid - // pointer, we don't ever dereference it, so this is always safe. - layer.downcast_raw(TypeId::of::()) - } - .is_some() -} - -struct FmtBitset(u64); - -impl fmt::Debug for FmtBitset { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut set = f.debug_set(); - for bit in 0..64 { - // if the `bit`-th bit is set, add it to the debug set - if self.0 & (1 << bit) != 0 { - set.entry(&bit); - } - } - set.finish() - } -} diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/level.rs b/vendor/tracing-subscriber-0.3.3/src/filter/level.rs deleted file mode 100644 index 0fa601260..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/filter/level.rs +++ /dev/null @@ -1,27 +0,0 @@ -use tracing_core::{ - subscriber::{Interest, Subscriber}, - Metadata, -}; - -#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 -pub use tracing_core::metadata::{LevelFilter, ParseLevelFilterError as ParseError}; - -// === impl LevelFilter === - -impl crate::Layer for LevelFilter { - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - if self >= metadata.level() { - Interest::always() - } else { - Interest::never() - } - } - - fn enabled(&self, metadata: &Metadata<'_>, _: crate::layer::Context<'_, S>) -> bool { - self >= metadata.level() - } - - fn max_level_hint(&self) -> Option { - Some(*self) - } -} diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs b/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs deleted file mode 100644 index 000a27195..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! [`Layer`]s that control which spans and events are enabled by the wrapped -//! subscriber. -//! -//! This module contains a number of types that provide implementations of -//! various strategies for filtering which spans and events are enabled. For -//! details on filtering spans and events using [`Layer`]s, see the -//! [`layer` module's documentation]. -//! -//! [`layer` module's documentation]: crate::layer#filtering-with-layers -//! [`Layer`]: crate::layer -mod filter_fn; - -feature! { - #![all(feature = "env-filter", feature = "std")] - mod env; - pub use self::env::*; -} - -feature! { - #![all(feature = "registry", feature = "std")] - mod layer_filters; - pub use self::layer_filters::*; -} - -mod level; - -pub use self::filter_fn::*; -pub use self::level::{LevelFilter, ParseError as LevelParseError}; - -#[cfg(not(all(feature = "registry", feature = "std")))] -pub(crate) use self::has_plf_stubs::*; - -feature! { - #![any(feature = "std", feature = "alloc")] - pub mod targets; - pub use self::targets::Targets; - - mod directive; - pub use self::directive::ParseError; -} - -/// Stub implementations of the per-layer-fitler detection functions for when the -/// `registry` feature is disabled. -#[cfg(not(all(feature = "registry", feature = "std")))] -mod has_plf_stubs { - pub(crate) fn is_plf_downcast_marker(_: core::any::TypeId) -> bool { - false - } - - /// Does a type implementing `Subscriber` contain any per-layer filters? - pub(crate) fn subscriber_has_plf(_: &S) -> bool - where - S: tracing_core::Subscriber, - { - false - } - - /// Does a type implementing `Layer` contain any per-layer filters? - pub(crate) fn layer_has_plf(_: &L) -> bool - where - L: crate::Layer, - S: tracing_core::Subscriber, - { - false - } -} diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs b/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs deleted file mode 100644 index e0c7fcf82..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs +++ /dev/null @@ -1,681 +0,0 @@ -//! A [filter] that enables or disables spans and events based on their [target] and [level]. -//! -//! See [`Targets`] for details. -//! -//! [target]: tracing_core::Metadata::target -//! [level]: tracing_core::Level -//! [filter]: crate::layer#filtering-with-layers - -use crate::{ - filter::{ - directive::{DirectiveSet, ParseError, StaticDirective}, - LevelFilter, - }, - layer, -}; -#[cfg(not(feature = "std"))] -use alloc::string::String; -use core::{ - iter::{Extend, FilterMap, FromIterator}, - slice, - str::FromStr, -}; -use tracing_core::{Interest, Metadata, Subscriber}; - -/// A filter that enables or disables spans and events based on their [target] -/// and [level]. -/// -/// Targets are typically equal to the Rust module path of the code where the -/// span or event was recorded, although they may be overridden. -/// -/// This type can be used for both [per-layer filtering][plf] (using its -/// [`Filter`] implementation) and [global filtering][global] (using its -/// [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// # Filtering With `Targets` -/// -/// A `Targets` filter consists of one or more [target] prefixes, paired with -/// [`LevelFilter`]s. If a span or event's [target] begins with one of those -/// prefixes, and its [level] is at or below the [`LevelFilter`] enabled for -/// that prefix, then the span or event will be enabled. -/// -/// This is similar to the behavior implemented by the [`env_logger` crate] in -/// the `log` ecosystem. -/// -/// The [`EnvFilter`] type also provided by this crate is very similar to `Targets`, -/// but is capable of a more sophisticated form of filtering where events may -/// also be enabled or disabled based on the span they are recorded in. -/// `Targets` can be thought of as a lighter-weight form of [`EnvFilter`] that -/// can be used instead when this dynamic filtering is not required. -/// -/// # Examples -/// -/// A `Targets` filter can be constructed by programmatically adding targets and -/// levels to enable: -/// -/// ``` -/// use tracing_subscriber::{filter, prelude::*}; -/// use tracing_core::Level; -/// -/// let filter = filter::Targets::new() -/// // Enable the `INFO` level for anything in `my_crate` -/// .with_target("my_crate", Level::INFO) -/// // Enable the `DEBUG` level for a specific module. -/// .with_target("my_crate::interesting_module", Level::DEBUG); -/// -/// // Build a new subscriber with the `fmt` layer using the `Targets` -/// // filter we constructed above. -/// tracing_subscriber::registry() -/// .with(tracing_subscriber::fmt::layer()) -/// .with(filter) -/// .init(); -/// ``` -/// -/// [`LevelFilter::OFF`] can be used to disable a particular target: -/// ``` -/// use tracing_subscriber::filter::{Targets, LevelFilter}; -/// use tracing_core::Level; -/// -/// let filter = Targets::new() -/// .with_target("my_crate", Level::INFO) -/// // Disable all traces from `annoying_module`. -/// .with_target("my_crate::annoying_module", LevelFilter::OFF); -/// # drop(filter); -/// ``` -/// -/// Alternatively, `Targets` implements [`std::str::FromStr`], allowing it to be -/// parsed from a comma-delimited list of `target=level` pairs. For example: -/// -/// ```rust -/// # fn main() -> Result<(), Box> { -/// use tracing_subscriber::filter; -/// use tracing_core::Level; -/// -/// let filter = "my_crate=info,my_crate::interesting_module=trace,other_crate=debug" -/// .parse::()?; -/// -/// // The parsed filter is identical to a filter constructed using `with_target`: -/// assert_eq!( -/// filter, -/// filter::Targets::new() -/// .with_target("my_crate", Level::INFO) -/// .with_target("my_crate::interesting_module", Level::TRACE) -/// .with_target("other_crate", Level::DEBUG) -/// ); -/// # Ok(()) } -/// ``` -/// -/// This is particularly useful when the list of enabled targets is configurable -/// by the user at runtime. -/// -/// The `Targets` filter can be used as a [per-layer filter][plf] *and* as a -/// [global filter]: -/// -/// ```rust -/// use tracing_subscriber::{ -/// fmt, -/// filter::{Targets, LevelFilter}, -/// prelude::*, -/// }; -/// use tracing_core::Level; -/// use std::{sync::Arc, fs::File}; -/// # fn docs() -> Result<(), Box> { -/// -/// // A layer that logs events to stdout using the human-readable "pretty" -/// // format. -/// let stdout_log = fmt::layer().pretty(); -/// -/// // A layer that logs events to a file, using the JSON format. -/// let file = File::create("debug_log.json")?; -/// let debug_log = fmt::layer() -/// .with_writer(Arc::new(file)) -/// .json(); -/// -/// tracing_subscriber::registry() -/// // Only log INFO and above to stdout, unless the span or event -/// // has the `my_crate::cool_module` target prefix. -/// .with(stdout_log -/// .with_filter( -/// Targets::default() -/// .with_target("my_crate::cool_module", Level::DEBUG) -/// .with_default(Level::INFO) -/// ) -/// ) -/// // Log everything enabled by the global filter to `debug_log.json`. -/// .with(debug_log) -/// // Configure a global filter for the whole subscriber stack. This will -/// // control what spans and events are recorded by both the `debug_log` -/// // and the `stdout_log` layers, and `stdout_log` will *additionally* be -/// // filtered by its per-layer filter. -/// .with( -/// Targets::default() -/// .with_target("my_crate", Level::TRACE) -/// .with_target("other_crate", Level::INFO) -/// .with_target("other_crate::annoying_module", LevelFilter::OFF) -/// .with_target("third_crate", Level::DEBUG) -/// ).init(); -/// # Ok(()) } -///``` -/// -/// [target]: tracing_core::Metadata::target -/// [level]: tracing_core::Level -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -/// [`env_logger` crate]: https://docs.rs/env_logger/0.9.0/env_logger/index.html#enabling-logging -/// [`EnvFilter`]: crate::filter::EnvFilter -#[derive(Debug, Default, Clone, PartialEq)] -pub struct Targets(DirectiveSet); - -impl Targets { - /// Returns a new `Targets` filter. - /// - /// This filter will enable no targets. Call [`with_target`] or [`with_targets`] - /// to add enabled targets, and [`with_default`] to change the default level - /// enabled for spans and events that didn't match any of the provided targets. - /// - /// [`with_target`]: Targets::with_target - /// [`with_targets`]: Targets::with_targets - /// [`with_default`]: Targets::with_default - pub fn new() -> Self { - Self::default() - } - - /// Enables spans and events with [target]s starting with the provided target - /// prefix if they are at or below the provided [`LevelFilter`]. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::filter; - /// use tracing_core::Level; - /// - /// let filter = filter::Targets::new() - /// // Enable the `INFO` level for anything in `my_crate` - /// .with_target("my_crate", Level::INFO) - /// // Enable the `DEBUG` level for a specific module. - /// .with_target("my_crate::interesting_module", Level::DEBUG); - /// # drop(filter); - /// ``` - /// - /// [`LevelFilter::OFF`] can be used to disable a particular target: - /// ``` - /// use tracing_subscriber::filter::{Targets, LevelFilter}; - /// use tracing_core::Level; - /// - /// let filter = Targets::new() - /// .with_target("my_crate", Level::INFO) - /// // Disable all traces from `annoying_module`. - /// .with_target("my_crate::interesting_module", LevelFilter::OFF); - /// # drop(filter); - /// ``` - /// - /// [target]: tracing_core::Metadata::target - pub fn with_target(mut self, target: impl Into, level: impl Into) -> Self { - self.0.add(StaticDirective::new( - Some(target.into()), - Default::default(), - level.into(), - )); - self - } - /// Adds [target]s from an iterator of [target]-[`LevelFilter`] pairs to this filter. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::filter; - /// use tracing_core::Level; - /// - /// let filter = filter::Targets::new() - /// .with_targets(vec![ - /// ("my_crate", Level::INFO), - /// ("my_crate::some_module", Level::DEBUG), - /// ("my_crate::other_module::cool_stuff", Level::TRACE), - /// ("other_crate", Level::WARN) - /// ]); - /// # drop(filter); - /// ``` - /// - /// [`LevelFilter::OFF`] can be used to disable a particular target: - /// ``` - /// use tracing_subscriber::filter::{Targets, LevelFilter}; - /// use tracing_core::Level; - /// - /// let filter = Targets::new() - /// .with_target("my_crate", Level::INFO) - /// // Disable all traces from `annoying_module`. - /// .with_target("my_crate::interesting_module", LevelFilter::OFF); - /// # drop(filter); - /// ``` - /// - /// [target]: tracing_core::Metadata::target - pub fn with_targets(mut self, targets: impl IntoIterator) -> Self - where - String: From, - LevelFilter: From, - { - self.extend(targets); - self - } - - /// Sets the default level to enable for spans and events whose targets did - /// not match any of the configured prefixes. - /// - /// By default, this is [`LevelFilter::OFF`]. This means that spans and - /// events will only be enabled if they match one of the configured target - /// prefixes. If this is changed to a different [`LevelFilter`], spans and - /// events with targets that did not match any of the configured prefixes - /// will be enabled if their level is at or below the provided level. - pub fn with_default(mut self, level: impl Into) -> Self { - self.0 - .add(StaticDirective::new(None, Default::default(), level.into())); - self - } - - /// Returns an iterator over the [target]-[`LevelFilter`] pairs in this filter. - /// - /// The order of iteration is undefined. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::filter::{Targets, LevelFilter}; - /// use tracing_core::Level; - /// - /// let filter = Targets::new() - /// .with_target("my_crate", Level::INFO) - /// .with_target("my_crate::interesting_module", Level::DEBUG); - /// - /// let mut targets: Vec<_> = filter.iter().collect(); - /// targets.sort(); - /// - /// assert_eq!(targets, vec![ - /// ("my_crate", LevelFilter::INFO), - /// ("my_crate::interesting_module", LevelFilter::DEBUG), - /// ]); - /// ``` - /// - /// [target]: tracing_core::Metadata::target - pub fn iter(&self) -> Iter<'_> { - self.into_iter() - } - - #[inline] - fn interested(&self, metadata: &'static Metadata<'static>) -> Interest { - if self.0.enabled(metadata) { - Interest::always() - } else { - Interest::never() - } - } -} - -impl Extend<(T, L)> for Targets -where - T: Into, - L: Into, -{ - fn extend>(&mut self, iter: I) { - let iter = iter.into_iter().map(|(target, level)| { - StaticDirective::new(Some(target.into()), Default::default(), level.into()) - }); - self.0.extend(iter); - } -} - -impl FromIterator<(T, L)> for Targets -where - T: Into, - L: Into, -{ - fn from_iter>(iter: I) -> Self { - let mut this = Self::default(); - this.extend(iter); - this - } -} - -impl FromStr for Targets { - type Err = ParseError; - fn from_str(s: &str) -> Result { - s.split(',') - .map(StaticDirective::from_str) - .collect::>() - .map(Self) - } -} - -impl layer::Layer for Targets -where - S: Subscriber, -{ - fn enabled(&self, metadata: &Metadata<'_>, _: layer::Context<'_, S>) -> bool { - self.0.enabled(metadata) - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - self.interested(metadata) - } - - fn max_level_hint(&self) -> Option { - Some(self.0.max_level) - } -} - -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -impl layer::Filter for Targets { - fn enabled(&self, metadata: &Metadata<'_>, _: &layer::Context<'_, S>) -> bool { - self.0.enabled(metadata) - } - - fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - self.interested(metadata) - } - - fn max_level_hint(&self) -> Option { - Some(self.0.max_level) - } -} - -impl IntoIterator for Targets { - type Item = (String, LevelFilter); - - type IntoIter = IntoIter; - - fn into_iter(self) -> Self::IntoIter { - IntoIter::new(self) - } -} - -impl<'a> IntoIterator for &'a Targets { - type Item = (&'a str, LevelFilter); - - type IntoIter = Iter<'a>; - - fn into_iter(self) -> Self::IntoIter { - Iter::new(self) - } -} - -/// An owning iterator over the [target]-[level] pairs of a `Targets` filter. -/// -/// This struct is created by the `IntoIterator` trait implementation of [`Targets`]. -/// -/// # Examples -/// -/// Merge the targets from one `Targets` with another: -/// -/// ``` -/// use tracing_subscriber::filter::Targets; -/// use tracing_core::Level; -/// -/// let mut filter = Targets::new().with_target("my_crate", Level::INFO); -/// let overrides = Targets::new().with_target("my_crate::interesting_module", Level::DEBUG); -/// -/// filter.extend(overrides); -/// # drop(filter); -/// ``` -/// -/// [target]: tracing_core::Metadata::target -/// [level]: tracing_core::Level -#[derive(Debug)] -pub struct IntoIter( - #[allow(clippy::type_complexity)] // alias indirection would probably make this more confusing - FilterMap< - as IntoIterator>::IntoIter, - fn(StaticDirective) -> Option<(String, LevelFilter)>, - >, -); - -impl IntoIter { - fn new(targets: Targets) -> Self { - Self(targets.0.into_iter().filter_map(|directive| { - let level = directive.level; - directive.target.map(|target| (target, level)) - })) - } -} - -impl Iterator for IntoIter { - type Item = (String, LevelFilter); - - fn next(&mut self) -> Option { - self.0.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() - } -} - -/// A borrowing iterator over the [target]-[level] pairs of a `Targets` filter. -/// -/// This struct is created by [`iter`] method of [`Targets`], or from the `IntoIterator` -/// implementation for `&Targets`. -/// -/// [target]: tracing_core::Metadata::target -/// [level]: tracing_core::Level -/// [`iter`]: Targets::iter -#[derive(Debug)] -pub struct Iter<'a>( - FilterMap< - slice::Iter<'a, StaticDirective>, - fn(&'a StaticDirective) -> Option<(&'a str, LevelFilter)>, - >, -); - -impl<'a> Iter<'a> { - fn new(targets: &'a Targets) -> Self { - Self(targets.0.iter().filter_map(|directive| { - directive - .target - .as_deref() - .map(|target| (target, directive.level)) - })) - } -} - -impl<'a> Iterator for Iter<'a> { - type Item = (&'a str, LevelFilter); - - fn next(&mut self) -> Option { - self.0.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - feature! { - #![not(feature = "std")] - use alloc::{vec, vec::Vec, string::ToString}; - - // `dbg!` is only available with `libstd`; just nop it out when testing - // with alloc only. - macro_rules! dbg { - ($x:expr) => { $x } - } - } - - fn expect_parse(s: &str) -> Targets { - match dbg!(s).parse::() { - Err(e) => panic!("string {:?} did not parse successfully: {}", s, e), - Ok(e) => e, - } - } - - fn expect_parse_ralith(s: &str) { - let dirs = expect_parse(s).0.into_vec(); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("server".to_string())); - assert_eq!(dirs[0].level, LevelFilter::DEBUG); - assert_eq!(dirs[0].field_names, Vec::::new()); - - assert_eq!(dirs[1].target, Some("common".to_string())); - assert_eq!(dirs[1].level, LevelFilter::INFO); - assert_eq!(dirs[1].field_names, Vec::::new()); - } - - fn expect_parse_level_directives(s: &str) { - let dirs = expect_parse(s).0.into_vec(); - assert_eq!(dirs.len(), 6, "\nparsed: {:#?}", dirs); - - assert_eq!(dirs[0].target, Some("crate3::mod2::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::OFF); - assert_eq!(dirs[0].field_names, Vec::::new()); - - assert_eq!(dirs[1].target, Some("crate1::mod2::mod3".to_string())); - assert_eq!(dirs[1].level, LevelFilter::INFO); - assert_eq!(dirs[1].field_names, Vec::::new()); - - assert_eq!(dirs[2].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::WARN); - assert_eq!(dirs[2].field_names, Vec::::new()); - - assert_eq!(dirs[3].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[3].level, LevelFilter::ERROR); - assert_eq!(dirs[3].field_names, Vec::::new()); - - assert_eq!(dirs[4].target, Some("crate3".to_string())); - assert_eq!(dirs[4].level, LevelFilter::TRACE); - assert_eq!(dirs[4].field_names, Vec::::new()); - - assert_eq!(dirs[5].target, Some("crate2".to_string())); - assert_eq!(dirs[5].level, LevelFilter::DEBUG); - assert_eq!(dirs[5].field_names, Vec::::new()); - } - - #[test] - fn parse_ralith() { - expect_parse_ralith("common=info,server=debug"); - } - - #[test] - fn parse_ralith_uc() { - expect_parse_ralith("common=INFO,server=DEBUG"); - } - - #[test] - fn parse_ralith_mixed() { - expect_parse("common=iNfo,server=dEbUg"); - } - - #[test] - fn expect_parse_valid() { - let dirs = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off") - .0 - .into_vec(); - assert_eq!(dirs.len(), 4, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::TRACE); - assert_eq!(dirs[0].field_names, Vec::::new()); - - assert_eq!(dirs[1].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[1].level, LevelFilter::ERROR); - assert_eq!(dirs[1].field_names, Vec::::new()); - - assert_eq!(dirs[2].target, Some("crate3".to_string())); - assert_eq!(dirs[2].level, LevelFilter::OFF); - assert_eq!(dirs[2].field_names, Vec::::new()); - - assert_eq!(dirs[3].target, Some("crate2".to_string())); - assert_eq!(dirs[3].level, LevelFilter::DEBUG); - assert_eq!(dirs[3].field_names, Vec::::new()); - } - - #[test] - fn parse_level_directives() { - expect_parse_level_directives( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off", - ) - } - - #[test] - fn parse_uppercase_level_directives() { - expect_parse_level_directives( - "crate1::mod1=ERROR,crate1::mod2=WARN,crate1::mod2::mod3=INFO,\ - crate2=DEBUG,crate3=TRACE,crate3::mod2::mod1=OFF", - ) - } - - #[test] - fn parse_numeric_level_directives() { - expect_parse_level_directives( - "crate1::mod1=1,crate1::mod2=2,crate1::mod2::mod3=3,crate2=4,\ - crate3=5,crate3::mod2::mod1=0", - ) - } - - #[test] - fn targets_iter() { - let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off") - .with_default(LevelFilter::WARN); - - let mut targets: Vec<_> = filter.iter().collect(); - targets.sort(); - - assert_eq!( - targets, - vec![ - ("crate1::mod1", LevelFilter::ERROR), - ("crate1::mod2", LevelFilter::TRACE), - ("crate2", LevelFilter::DEBUG), - ("crate3", LevelFilter::OFF), - ] - ); - } - - #[test] - fn targets_into_iter() { - let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off") - .with_default(LevelFilter::WARN); - - let mut targets: Vec<_> = filter.into_iter().collect(); - targets.sort(); - - assert_eq!( - targets, - vec![ - ("crate1::mod1".to_string(), LevelFilter::ERROR), - ("crate1::mod2".to_string(), LevelFilter::TRACE), - ("crate2".to_string(), LevelFilter::DEBUG), - ("crate3".to_string(), LevelFilter::OFF), - ] - ); - } - - #[test] - // `println!` is only available with `libstd`. - #[cfg(feature = "std")] - fn size_of_filters() { - fn print_sz(s: &str) { - let filter = s.parse::().expect("filter should parse"); - println!( - "size_of_val({:?})\n -> {}B", - s, - std::mem::size_of_val(&filter) - ); - } - - print_sz("info"); - - print_sz("foo=debug"); - - print_sz( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off", - ); - } -} -- cgit v1.2.3