summaryrefslogtreecommitdiffstats
path: root/vendor/tracing-subscriber-0.3.3/src/filter/env
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:50 +0000
commit2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35 (patch)
treed325add32978dbdc1db975a438b3a77d571b1ab8 /vendor/tracing-subscriber-0.3.3/src/filter/env
parentReleasing progress-linux version 1.68.2+dfsg1-1~progress7.99u1. (diff)
downloadrustc-2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35.tar.xz
rustc-2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35.zip
Merging upstream version 1.69.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/tracing-subscriber-0.3.3/src/filter/env')
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs846
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs416
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs738
3 files changed, 0 insertions, 2000 deletions
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<String>,
- fields: Vec<field::Match>,
- pub(crate) target: Option<String>,
- pub(crate) level: LevelFilter,
-}
-
-/// A set of dynamic filtering directives.
-pub(super) type Dynamics = DirectiveSet<Directive>;
-
-/// A set of static filtering directives.
-pub(super) type Statics = DirectiveSet<StaticDirective>;
-
-pub(crate) type CallsiteMatcher = MatchSet<field::CallsiteMatch>;
-pub(crate) type SpanMatcher = MatchSet<field::SpanMatch>;
-
-#[derive(Debug, PartialEq, Eq)]
-pub(crate) struct MatchSet<T> {
- field_matches: FilterVec<T>,
- 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<StaticDirective> {
- 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<field::CallsiteMatch> {
- 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::<Result<FieldMap<_>, ()>>()
- .ok()?;
- Some(field::CallsiteMatch {
- fields,
- level: self.level,
- })
- }
-
- pub(super) fn make_tables(
- directives: impl IntoIterator<Item = Directive>,
- ) -> (Dynamics, Statics) {
- // TODO(eliza): this could be made more efficient...
- let (dyns, stats): (Vec<Directive>, Vec<Directive>) =
- 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<Self, Self::Err> {
- lazy_static! {
- static ref DIRECTIVE_RE: Regex = Regex::new(
- r"(?x)
- ^(?P<global_level>(?i:trace|debug|info|warn|error|off|[0-5]))$ |
- # ^^^.
- # `note: we match log level names case-insensitively
- ^
- (?: # target name or span name
- (?P<target>[\w:-]+)|(?P<span>\[[^\]]*\])
- ){1,2}
- (?: # level or nothing
- =(?P<level>(?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<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).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::<LevelFilter>().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::<Result<Vec<_>, _>>()
- })
- .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<Ordering> {
- 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<LevelFilter> for Directive {
- fn from(level: LevelFilter) -> Self {
- Self {
- level,
- ..Self::default()
- }
- }
-}
-
-impl From<Level> for Directive {
- fn from(level: Level) -> Self {
- LevelFilter::from_level(level).into()
- }
-}
-
-// === impl Dynamics ===
-
-impl Dynamics {
- pub(crate) fn matcher(&self, metadata: &Metadata<'_>) -> Option<CallsiteMatcher> {
- 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<str>) -> Vec<Directive> {
- dirs.as_ref()
- .split(',')
- .filter_map(|s| s.parse().ok())
- .collect()
- }
-
- fn expect_parse(dirs: impl AsRef<str>) -> Vec<Directive> {
- 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::<Vec<_>>();
-
- 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::<Vec<_>>();
-
- 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::<Vec<_>>();
-
- 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::<Vec<_>>();
-
- 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<ValueMatch>,
-}
-
-#[derive(Debug, Eq, PartialEq)]
-pub(crate) struct CallsiteMatch {
- pub(crate) fields: FieldMap<ValueMatch>,
- 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<MatchPattern>),
-}
-
-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<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-#[derive(Debug, Clone)]
-pub(crate) struct MatchPattern {
- pub(crate) matcher: Pattern,
- pattern: Arc<str>,
-}
-
-/// 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<dyn Error + Send + Sync>;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- 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<Ordering> {
- 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<Self, Self::Err> {
- s.parse::<bool>()
- .map(ValueMatch::Bool)
- .or_else(|_| s.parse::<u64>().map(ValueMatch::U64))
- .or_else(|_| s.parse::<i64>().map(ValueMatch::I64))
- .or_else(|_| s.parse::<f64>().map(value_match_f64))
- .or_else(|_| {
- s.parse::<MatchPattern>()
- .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<Self, Self::Err> {
- let matcher = s.parse::<Pattern>()?;
- 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<str> for MatchPattern {
- #[inline]
- fn as_ref(&self) -> &str {
- self.pattern.as_ref()
- }
-}
-
-impl MatchPattern {
- #[inline]
- fn str_matches(&self, s: &impl AsRef<str>) -> 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<Ordering> {
- 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<LevelFilter> {
- 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<HashMap<span::Id, directive::SpanMatcher>>,
- by_cs: RwLock<HashMap<callsite::Identifier, directive::CallsiteMatcher>>,
-}
-
-thread_local! {
- static SCOPE: RefCell<Vec<LevelFilter>> = RefCell::new(Vec::new());
-}
-
-type FieldMap<T> = HashMap<Field, T>;
-
-/// 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<A: AsRef<str>>(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<S: AsRef<str>>(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<S: AsRef<str>>(dirs: S) -> Result<Self, directive::ParseError> {
- let directives = dirs
- .as_ref()
- .split(',')
- .map(|s| s.parse())
- .collect::<Result<Vec<_>, _>>()?;
- 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, FromEnvError> {
- 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<A: AsRef<str>>(env: A) -> Result<Self, FromEnvError> {
- 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<dyn ::std::error::Error>> {
- /// 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<Item = Directive>) -> 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<S: Subscriber> Layer<S> 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<LevelFilter> {
- 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, Self::Err> {
- Self::try_new(spec)
- }
-}
-
-impl<S> From<S> for EnvFilter
-where
- S: AsRef<str>,
-{
- 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<directive::ParseError> for FromEnvError {
- fn from(p: directive::ParseError) -> Self {
- Self {
- kind: ErrorKind::Parse(p),
- }
- }
-}
-
-impl From<env::VarError> 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::<EnvFilter>().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",
- );
- }
-}