summaryrefslogtreecommitdiffstats
path: root/vendor/tracing-subscriber-0.3.3/src/filter
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:28 +0000
commit94a0819fe3a0d679c3042a77bfe6a2afc505daea (patch)
tree2b827afe6a05f3538db3f7803a88c4587fe85648 /vendor/tracing-subscriber-0.3.3/src/filter
parentAdding upstream version 1.64.0+dfsg1. (diff)
downloadrustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.tar.xz
rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.zip
Adding upstream version 1.66.0+dfsg1.upstream/1.66.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/tracing-subscriber-0.3.3/src/filter')
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/directive.rs424
-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
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs749
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs830
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/level.rs27
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/mod.rs66
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/targets.rs681
9 files changed, 4777 insertions, 0 deletions
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs b/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs
new file mode 100644
index 000000000..dd6b063c4
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs
@@ -0,0 +1,424 @@
+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<String>,
+ pub(in crate::filter) field_names: Vec<String>,
+ pub(in crate::filter) level: LevelFilter,
+}
+
+#[cfg(feature = "smallvec")]
+pub(crate) type FilterVec<T> = smallvec::SmallVec<[T; 8]>;
+#[cfg(not(feature = "smallvec"))]
+pub(crate) type FilterVec<T> = Vec<T>;
+
+#[derive(Debug, PartialEq, Clone)]
+pub(in crate::filter) struct DirectiveSet<T> {
+ directives: FilterVec<T>,
+ 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<dyn std::error::Error + Send + Sync>),
+ Level(level::ParseError),
+ Other(Option<&'static str>),
+}
+
+// === impl DirectiveSet ===
+
+impl<T> DirectiveSet<T> {
+ #[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<T: Ord> Default for DirectiveSet<T> {
+ fn default() -> Self {
+ Self {
+ directives: FilterVec::new(),
+ max_level: LevelFilter::OFF,
+ }
+ }
+}
+
+impl<T: Match + Ord> DirectiveSet<T> {
+ pub(crate) fn directives(&self) -> impl Iterator<Item = &T> {
+ self.directives.iter()
+ }
+
+ pub(crate) fn directives_for<'a>(
+ &'a self,
+ metadata: &'a Metadata<'a>,
+ ) -> impl Iterator<Item = &'a T> + '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<T> {
+ self.directives
+ }
+}
+
+impl<T: Match + Ord> FromIterator<T> for DirectiveSet<T> {
+ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
+ let mut this = Self::default();
+ this.extend(iter);
+ this
+ }
+}
+
+impl<T: Match + Ord> Extend<T> for DirectiveSet<T> {
+ fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
+ for directive in iter.into_iter() {
+ self.add(directive);
+ }
+ }
+}
+
+impl<T> IntoIterator for DirectiveSet<T> {
+ type Item = T;
+
+ #[cfg(feature = "smallvec")]
+ type IntoIter = smallvec::IntoIter<[T; 8]>;
+ #[cfg(not(feature = "smallvec"))]
+ type IntoIter = vec::IntoIter<T>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.directives.into_iter()
+ }
+}
+
+// === impl Statics ===
+
+impl DirectiveSet<StaticDirective> {
+ 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<String>,
+ field_names: Vec<String>,
+ 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<Ordering> {
+ 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<Self, Self::Err> {
+ // 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::<LevelFilter>() {
+ 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<Box<dyn std::error::Error + Send + Sync>> for ParseError {
+ fn from(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
+ Self {
+ kind: ParseErrorKind::Field(e),
+ }
+ }
+}
+
+impl From<level::ParseError> 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
new file mode 100644
index 000000000..66ca23dc4
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs
@@ -0,0 +1,846 @@
+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
new file mode 100644
index 000000000..970850f92
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs
@@ -0,0 +1,416 @@
+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
new file mode 100644
index 000000000..81fe0e62d
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs
@@ -0,0 +1,738 @@
+//! 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",
+ );
+ }
+}
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
new file mode 100644
index 000000000..332bf860a
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs
@@ -0,0 +1,749 @@
+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<F = fn(&Metadata<'_>) -> bool> {
+ enabled: F,
+ max_level_hint: Option<LevelFilter>,
+}
+
+/// 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<R>,
+ max_level_hint: Option<LevelFilter>,
+ _s: PhantomData<fn(S)>,
+}
+
+// === 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: F) -> FilterFn<F>
+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<S, F>(f: F) -> DynFilterFn<S, F>
+where
+ F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
+{
+ DynFilterFn::new(f)
+}
+
+impl<F> FilterFn<F>
+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<LevelFilter>) -> 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::<F>(),
+ 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::<F>(),
+ 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<S, F> Layer<S> for FilterFn<F>
+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<LevelFilter> {
+ self.max_level_hint
+ }
+}
+
+impl<F> From<F> for FilterFn<F>
+where
+ F: Fn(&Metadata<'_>) -> bool,
+{
+ fn from(enabled: F) -> Self {
+ Self::new(enabled)
+ }
+}
+
+impl<F> fmt::Debug for FilterFn<F> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("FilterFn")
+ .field("enabled", &format_args!("{}", type_name::<F>()))
+ .field("max_level_hint", &self.max_level_hint)
+ .finish()
+ }
+}
+
+// === impl DynFilterFn ==
+
+impl<S, F> DynFilterFn<S, F>
+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<S, F, R> DynFilterFn<S, F, R>
+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<LevelFilter>) -> 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<R2>(self, callsite_enabled: R2) -> DynFilterFn<S, F, R2>
+ 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::<F>(),
+ 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<S, F, R> DynFilterFn<S, F, R>
+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::<F>(),
+ 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::<F>(),
+ type_name::<R>(),
+ self.max_level_hint.unwrap(),
+ metadata.level(),
+ metadata,
+ );
+
+ interest
+ }
+}
+
+impl<S, F, R> Layer<S> for DynFilterFn<S, F, R>
+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<LevelFilter> {
+ self.max_level_hint
+ }
+}
+
+impl<S, F, R> fmt::Debug for DynFilterFn<S, F, R> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut s = f.debug_struct("DynFilterFn");
+ s.field("enabled", &format_args!("{}", type_name::<F>()));
+ if self.register_callsite.is_some() {
+ s.field(
+ "register_callsite",
+ &format_args!("Some({})", type_name::<R>()),
+ );
+ } else {
+ s.field("register_callsite", &format_args!("None"));
+ }
+
+ s.field("max_level_hint", &self.max_level_hint).finish()
+ }
+}
+
+impl<S, F, R> Clone for DynFilterFn<S, F, R>
+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<F, S> From<F> for DynFilterFn<S, F>
+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<S, F> Filter<S> for FilterFn<F>
+ 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<LevelFilter> {
+ self.max_level_hint
+ }
+ }
+
+ impl<S, F, R> Filter<S> for DynFilterFn<S, F, R>
+ 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<LevelFilter> {
+ self.max_level_hint
+ }
+ }
+}
+
+fn is_below_max_level(hint: &Option<LevelFilter>, 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
new file mode 100644
index 000000000..e77fd3751
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs
@@ -0,0 +1,830 @@
+//! ## 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<L, F, S> {
+ filter: F,
+ layer: L,
+ id: MagicPlfDowncastMarker,
+ _s: PhantomData<fn(S)>,
+}
+
+/// 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<FilterMap>,
+ // 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<Option<Interest>>,
+
+ #[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<usize>,
+
+ /// How many per-layer filters have participated in the current `register_callsite`
+ /// call?
+ in_interest_pass: Cell<usize>,
+}
+
+thread_local! {
+ pub(crate) static FILTERING: FilterState = FilterState::new();
+}
+
+// === impl Filter ===
+#[cfg(feature = "registry")]
+#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+impl<S> layer::Filter<S> 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<LevelFilter> {
+ Some(*self)
+ }
+}
+
+impl<S> layer::Filter<S> for Arc<dyn layer::Filter<S> + 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<LevelFilter> {
+ (**self).max_level_hint()
+ }
+}
+
+impl<S> layer::Filter<S> for Box<dyn layer::Filter<S> + 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<LevelFilter> {
+ (**self).max_level_hint()
+ }
+}
+
+// === impl Filtered ===
+
+impl<L, F, S> Filtered<L, F, S> {
+ /// 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<S, L, F> Layer<S> for Filtered<L, F, S>
+where
+ S: Subscriber + for<'span> registry::LookupSpan<'span> + 'static,
+ F: layer::Filter<S> + 'static,
+ L: Layer<S>,
+{
+ 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<LevelFilter> {
+ 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::<Self>() => Some(self as *const _ as *const ()),
+ id if id == TypeId::of::<L>() => Some(&self.layer as *const _ as *const ()),
+ id if id == TypeId::of::<F>() => Some(&self.filter as *const _ as *const ()),
+ id if id == TypeId::of::<MagicPlfDowncastMarker>() => {
+ Some(&self.id as *const _ as *const ())
+ }
+ _ => self.layer.downcast_raw(id),
+ }
+ }
+}
+
+impl<F, L, S> fmt::Debug for Filtered<F, L, S>
+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<Interest> {
+ 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::<MagicPlfDowncastMarker>()
+}
+
+/// Does a type implementing `Subscriber` contain any per-layer filters?
+pub(crate) fn subscriber_has_plf<S>(subscriber: &S) -> bool
+where
+ S: Subscriber,
+{
+ (subscriber as &dyn Subscriber).is::<MagicPlfDowncastMarker>()
+}
+
+/// Does a type implementing `Layer` contain any per-layer filters?
+pub(crate) fn layer_has_plf<L, S>(layer: &L) -> bool
+where
+ L: Layer<S>,
+ 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::<MagicPlfDowncastMarker>())
+ }
+ .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
new file mode 100644
index 000000000..0fa601260
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/level.rs
@@ -0,0 +1,27 @@
+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<S: Subscriber> crate::Layer<S> 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<LevelFilter> {
+ 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
new file mode 100644
index 000000000..000a27195
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs
@@ -0,0 +1,66 @@
+//! [`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>(_: &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, S>(_: &L) -> bool
+ where
+ L: crate::Layer<S>,
+ 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
new file mode 100644
index 000000000..e0c7fcf82
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs
@@ -0,0 +1,681 @@
+//! 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<dyn std::error::Error>> {
+/// use tracing_subscriber::filter;
+/// use tracing_core::Level;
+///
+/// let filter = "my_crate=info,my_crate::interesting_module=trace,other_crate=debug"
+/// .parse::<filter::Targets>()?;
+///
+/// // 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<dyn std::error::Error>> {
+///
+/// // 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<StaticDirective>);
+
+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<String>, level: impl Into<LevelFilter>) -> 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<T, L>(mut self, targets: impl IntoIterator<Item = (T, L)>) -> Self
+ where
+ String: From<T>,
+ LevelFilter: From<L>,
+ {
+ 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<LevelFilter>) -> 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<T, L> Extend<(T, L)> for Targets
+where
+ T: Into<String>,
+ L: Into<LevelFilter>,
+{
+ fn extend<I: IntoIterator<Item = (T, L)>>(&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<T, L> FromIterator<(T, L)> for Targets
+where
+ T: Into<String>,
+ L: Into<LevelFilter>,
+{
+ fn from_iter<I: IntoIterator<Item = (T, L)>>(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<Self, Self::Err> {
+ s.split(',')
+ .map(StaticDirective::from_str)
+ .collect::<Result<_, _>>()
+ .map(Self)
+ }
+}
+
+impl<S> layer::Layer<S> 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<LevelFilter> {
+ Some(self.0.max_level)
+ }
+}
+
+#[cfg(feature = "registry")]
+#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+impl<S> layer::Filter<S> 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<LevelFilter> {
+ 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<
+ <DirectiveSet<StaticDirective> 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::Item> {
+ self.0.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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::Item> {
+ self.0.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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::<Targets>() {
+ 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::<String>::new());
+
+ assert_eq!(dirs[1].target, Some("common".to_string()));
+ assert_eq!(dirs[1].level, LevelFilter::INFO);
+ assert_eq!(dirs[1].field_names, Vec::<String>::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::<String>::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::<String>::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::<String>::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::<String>::new());
+
+ assert_eq!(dirs[4].target, Some("crate3".to_string()));
+ assert_eq!(dirs[4].level, LevelFilter::TRACE);
+ assert_eq!(dirs[4].field_names, Vec::<String>::new());
+
+ assert_eq!(dirs[5].target, Some("crate2".to_string()));
+ assert_eq!(dirs[5].level, LevelFilter::DEBUG);
+ assert_eq!(dirs[5].field_names, Vec::<String>::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::<String>::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::<String>::new());
+
+ assert_eq!(dirs[2].target, Some("crate3".to_string()));
+ assert_eq!(dirs[2].level, LevelFilter::OFF);
+ assert_eq!(dirs[2].field_names, Vec::<String>::new());
+
+ assert_eq!(dirs[3].target, Some("crate2".to_string()));
+ assert_eq!(dirs[3].level, LevelFilter::DEBUG);
+ assert_eq!(dirs[3].field_names, Vec::<String>::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::<Targets>().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",
+ );
+ }
+}