1 use crate::filter::level::{self, LevelFilter};
2 #[cfg(not(feature = "smallvec"))]
3 use alloc::vec;
4 #[cfg(not(feature = "std"))]
5 use alloc::{string::String, vec::Vec};
6 
7 use core::{cmp::Ordering, fmt, iter::FromIterator, slice, str::FromStr};
8 use tracing_core::{Level, Metadata};
9 /// Indicates that a string could not be parsed as a filtering directive.
10 #[derive(Debug)]
11 pub struct ParseError {
12     kind: ParseErrorKind,
13 }
14 
15 /// A directive which will statically enable or disable a given callsite.
16 ///
17 /// Unlike a dynamic directive, this can be cached by the callsite.
18 #[derive(Debug, PartialEq, Eq, Clone)]
19 pub(crate) struct StaticDirective {
20     pub(in crate::filter) target: Option<String>,
21     pub(in crate::filter) field_names: Vec<String>,
22     pub(in crate::filter) level: LevelFilter,
23 }
24 
25 #[cfg(feature = "smallvec")]
26 pub(crate) type FilterVec<T> = smallvec::SmallVec<[T; 8]>;
27 #[cfg(not(feature = "smallvec"))]
28 pub(crate) type FilterVec<T> = Vec<T>;
29 
30 #[derive(Debug, PartialEq, Clone)]
31 pub(in crate::filter) struct DirectiveSet<T> {
32     directives: FilterVec<T>,
33     pub(in crate::filter) max_level: LevelFilter,
34 }
35 
36 pub(in crate::filter) trait Match {
cares_about(&self, meta: &Metadata<'_>) -> bool37     fn cares_about(&self, meta: &Metadata<'_>) -> bool;
level(&self) -> &LevelFilter38     fn level(&self) -> &LevelFilter;
39 }
40 
41 #[derive(Debug)]
42 enum ParseErrorKind {
43     #[cfg(feature = "std")]
44     Field(Box<dyn std::error::Error + Send + Sync>),
45     Level(level::ParseError),
46     Other(Option<&'static str>),
47 }
48 
49 // === impl DirectiveSet ===
50 
51 impl<T> DirectiveSet<T> {
52     // this is only used by `env-filter`.
53     #[cfg(all(feature = "std", feature = "env-filter"))]
is_empty(&self) -> bool54     pub(crate) fn is_empty(&self) -> bool {
55         self.directives.is_empty()
56     }
57 
iter(&self) -> slice::Iter<'_, T>58     pub(crate) fn iter(&self) -> slice::Iter<'_, T> {
59         self.directives.iter()
60     }
61 }
62 
63 impl<T: Ord> Default for DirectiveSet<T> {
default() -> Self64     fn default() -> Self {
65         Self {
66             directives: FilterVec::new(),
67             max_level: LevelFilter::OFF,
68         }
69     }
70 }
71 
72 impl<T: Match + Ord> DirectiveSet<T> {
directives(&self) -> impl Iterator<Item = &T>73     pub(crate) fn directives(&self) -> impl Iterator<Item = &T> {
74         self.directives.iter()
75     }
76 
directives_for<'a>( &'a self, metadata: &'a Metadata<'a>, ) -> impl Iterator<Item = &'a T> + 'a77     pub(crate) fn directives_for<'a>(
78         &'a self,
79         metadata: &'a Metadata<'a>,
80     ) -> impl Iterator<Item = &'a T> + 'a {
81         self.directives().filter(move |d| d.cares_about(metadata))
82     }
83 
add(&mut self, directive: T)84     pub(crate) fn add(&mut self, directive: T) {
85         // does this directive enable a more verbose level than the current
86         // max? if so, update the max level.
87         let level = *directive.level();
88         if level > self.max_level {
89             self.max_level = level;
90         }
91         // insert the directive into the vec of directives, ordered by
92         // specificity (length of target + number of field filters). this
93         // ensures that, when finding a directive to match a span or event, we
94         // search the directive set in most specific first order.
95         match self.directives.binary_search(&directive) {
96             Ok(i) => self.directives[i] = directive,
97             Err(i) => self.directives.insert(i, directive),
98         }
99     }
100 
101     #[cfg(test)]
into_vec(self) -> FilterVec<T>102     pub(in crate::filter) fn into_vec(self) -> FilterVec<T> {
103         self.directives
104     }
105 }
106 
107 impl<T: Match + Ord> FromIterator<T> for DirectiveSet<T> {
from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self108     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
109         let mut this = Self::default();
110         this.extend(iter);
111         this
112     }
113 }
114 
115 impl<T: Match + Ord> Extend<T> for DirectiveSet<T> {
extend<I: IntoIterator<Item = T>>(&mut self, iter: I)116     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
117         for directive in iter.into_iter() {
118             self.add(directive);
119         }
120     }
121 }
122 
123 impl<T> IntoIterator for DirectiveSet<T> {
124     type Item = T;
125 
126     #[cfg(feature = "smallvec")]
127     type IntoIter = smallvec::IntoIter<[T; 8]>;
128     #[cfg(not(feature = "smallvec"))]
129     type IntoIter = vec::IntoIter<T>;
130 
into_iter(self) -> Self::IntoIter131     fn into_iter(self) -> Self::IntoIter {
132         self.directives.into_iter()
133     }
134 }
135 
136 // === impl Statics ===
137 
138 impl DirectiveSet<StaticDirective> {
enabled(&self, meta: &Metadata<'_>) -> bool139     pub(crate) fn enabled(&self, meta: &Metadata<'_>) -> bool {
140         let level = meta.level();
141         match self.directives_for(meta).next() {
142             Some(d) => d.level >= *level,
143             None => false,
144         }
145     }
146 
147     /// Same as `enabled` above, but skips `Directive`'s with fields.
target_enabled(&self, target: &str, level: &Level) -> bool148     pub(crate) fn target_enabled(&self, target: &str, level: &Level) -> bool {
149         match self.directives_for_target(target).next() {
150             Some(d) => d.level >= *level,
151             None => false,
152         }
153     }
154 
directives_for_target<'a>( &'a self, target: &'a str, ) -> impl Iterator<Item = &'a StaticDirective> + 'a155     pub(crate) fn directives_for_target<'a>(
156         &'a self,
157         target: &'a str,
158     ) -> impl Iterator<Item = &'a StaticDirective> + 'a {
159         self.directives()
160             .filter(move |d| d.cares_about_target(target))
161     }
162 }
163 
164 // === impl StaticDirective ===
165 
166 impl StaticDirective {
new( target: Option<String>, field_names: Vec<String>, level: LevelFilter, ) -> Self167     pub(in crate::filter) fn new(
168         target: Option<String>,
169         field_names: Vec<String>,
170         level: LevelFilter,
171     ) -> Self {
172         Self {
173             target,
174             field_names,
175             level,
176         }
177     }
178 
cares_about_target(&self, to_check: &str) -> bool179     pub(in crate::filter) fn cares_about_target(&self, to_check: &str) -> bool {
180         // Does this directive have a target filter, and does it match the
181         // metadata's target?
182         if let Some(ref target) = self.target {
183             if !to_check.starts_with(&target[..]) {
184                 return false;
185             }
186         }
187 
188         if !self.field_names.is_empty() {
189             return false;
190         }
191 
192         true
193     }
194 }
195 
196 impl Ord for StaticDirective {
cmp(&self, other: &StaticDirective) -> Ordering197     fn cmp(&self, other: &StaticDirective) -> Ordering {
198         // We attempt to order directives by how "specific" they are. This
199         // ensures that we try the most specific directives first when
200         // attempting to match a piece of metadata.
201 
202         // First, we compare based on whether a target is specified, and the
203         // lengths of those targets if both have targets.
204         let ordering = self
205             .target
206             .as_ref()
207             .map(String::len)
208             .cmp(&other.target.as_ref().map(String::len))
209             // Then we compare how many field names are matched by each directive.
210             .then_with(|| self.field_names.len().cmp(&other.field_names.len()))
211             // Finally, we fall back to lexicographical ordering if the directives are
212             // equally specific. Although this is no longer semantically important,
213             // we need to define a total ordering to determine the directive's place
214             // in the BTreeMap.
215             .then_with(|| {
216                 self.target
217                     .cmp(&other.target)
218                     .then_with(|| self.field_names[..].cmp(&other.field_names[..]))
219             })
220             .reverse();
221 
222         #[cfg(debug_assertions)]
223         {
224             if ordering == Ordering::Equal {
225                 debug_assert_eq!(
226                     self.target, other.target,
227                     "invariant violated: Ordering::Equal must imply a.target == b.target"
228                 );
229                 debug_assert_eq!(
230                     self.field_names, other.field_names,
231                     "invariant violated: Ordering::Equal must imply a.field_names == b.field_names"
232                 );
233             }
234         }
235 
236         ordering
237     }
238 }
239 
240 impl PartialOrd for StaticDirective {
partial_cmp(&self, other: &Self) -> Option<Ordering>241     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
242         Some(self.cmp(other))
243     }
244 }
245 
246 impl Match for StaticDirective {
cares_about(&self, meta: &Metadata<'_>) -> bool247     fn cares_about(&self, meta: &Metadata<'_>) -> bool {
248         // Does this directive have a target filter, and does it match the
249         // metadata's target?
250         if let Some(ref target) = self.target {
251             if !meta.target().starts_with(&target[..]) {
252                 return false;
253             }
254         }
255 
256         if meta.is_event() && !self.field_names.is_empty() {
257             let fields = meta.fields();
258             for name in &self.field_names {
259                 if fields.field(name).is_none() {
260                     return false;
261                 }
262             }
263         }
264 
265         true
266     }
267 
level(&self) -> &LevelFilter268     fn level(&self) -> &LevelFilter {
269         &self.level
270     }
271 }
272 
273 impl Default for StaticDirective {
default() -> Self274     fn default() -> Self {
275         StaticDirective {
276             target: None,
277             field_names: Vec::new(),
278             level: LevelFilter::ERROR,
279         }
280     }
281 }
282 
283 impl fmt::Display for StaticDirective {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result284     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285         let mut wrote_any = false;
286         if let Some(ref target) = self.target {
287             fmt::Display::fmt(target, f)?;
288             wrote_any = true;
289         }
290 
291         if !self.field_names.is_empty() {
292             f.write_str("[")?;
293 
294             let mut fields = self.field_names.iter();
295             if let Some(field) = fields.next() {
296                 write!(f, "{{{}", field)?;
297                 for field in fields {
298                     write!(f, ",{}", field)?;
299                 }
300                 f.write_str("}")?;
301             }
302 
303             f.write_str("]")?;
304             wrote_any = true;
305         }
306 
307         if wrote_any {
308             f.write_str("=")?;
309         }
310 
311         fmt::Display::fmt(&self.level, f)
312     }
313 }
314 
315 impl FromStr for StaticDirective {
316     type Err = ParseError;
317 
from_str(s: &str) -> Result<Self, Self::Err>318     fn from_str(s: &str) -> Result<Self, Self::Err> {
319         // This method parses a filtering directive in one of the following
320         // forms:
321         //
322         // * `foo=trace` (TARGET=LEVEL)
323         // * `foo[{bar,baz}]=info` (TARGET[{FIELD,+}]=LEVEL)
324         // * `trace` (bare LEVEL)
325         // * `foo` (bare TARGET)
326         let mut split = s.split('=');
327         let part0 = split
328             .next()
329             .ok_or_else(|| ParseError::msg("string must not be empty"))?;
330 
331         // Directive includes an `=`:
332         // * `foo=trace`
333         // * `foo[{bar}]=trace`
334         // * `foo[{bar,baz}]=trace`
335         if let Some(part1) = split.next() {
336             if split.next().is_some() {
337                 return Err(ParseError::msg(
338                     "too many '=' in filter directive, expected 0 or 1",
339                 ));
340             }
341 
342             let mut split = part0.split("[{");
343             let target = split.next().map(String::from);
344             let mut field_names = Vec::new();
345             // Directive includes fields:
346             // * `foo[{bar}]=trace`
347             // * `foo[{bar,baz}]=trace`
348             if let Some(maybe_fields) = split.next() {
349                 if split.next().is_some() {
350                     return Err(ParseError::msg(
351                         "too many '[{' in filter directive, expected 0 or 1",
352                     ));
353                 }
354 
355                 if !maybe_fields.ends_with("}]") {
356                     return Err(ParseError::msg("expected fields list to end with '}]'"));
357                 }
358 
359                 let fields = maybe_fields
360                     .trim_end_matches("}]")
361                     .split(',')
362                     .filter_map(|s| {
363                         if s.is_empty() {
364                             None
365                         } else {
366                             Some(String::from(s))
367                         }
368                     });
369                 field_names.extend(fields);
370             };
371             let level = part1.parse()?;
372             return Ok(Self {
373                 level,
374                 field_names,
375                 target,
376             });
377         }
378 
379         // Okay, the part after the `=` was empty, the directive is either a
380         // bare level or a bare target.
381         // * `foo`
382         // * `info`
383         Ok(match part0.parse::<LevelFilter>() {
384             Ok(level) => Self {
385                 level,
386                 target: None,
387                 field_names: Vec::new(),
388             },
389             Err(_) => Self {
390                 target: Some(String::from(part0)),
391                 level: LevelFilter::TRACE,
392                 field_names: Vec::new(),
393             },
394         })
395     }
396 }
397 
398 // === impl ParseError ===
399 
400 impl ParseError {
401     #[cfg(all(feature = "std", feature = "env-filter"))]
new() -> Self402     pub(crate) fn new() -> Self {
403         ParseError {
404             kind: ParseErrorKind::Other(None),
405         }
406     }
407 
msg(s: &'static str) -> Self408     pub(crate) fn msg(s: &'static str) -> Self {
409         ParseError {
410             kind: ParseErrorKind::Other(Some(s)),
411         }
412     }
413 }
414 
415 impl fmt::Display for ParseError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result416     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417         match self.kind {
418             ParseErrorKind::Other(None) => f.pad("invalid filter directive"),
419             ParseErrorKind::Other(Some(msg)) => write!(f, "invalid filter directive: {}", msg),
420             ParseErrorKind::Level(ref l) => l.fmt(f),
421             #[cfg(feature = "std")]
422             ParseErrorKind::Field(ref e) => write!(f, "invalid field filter: {}", e),
423         }
424     }
425 }
426 
427 #[cfg(feature = "std")]
428 impl std::error::Error for ParseError {
description(&self) -> &str429     fn description(&self) -> &str {
430         "invalid filter directive"
431     }
432 
source(&self) -> Option<&(dyn std::error::Error + 'static)>433     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
434         match self.kind {
435             ParseErrorKind::Other(_) => None,
436             ParseErrorKind::Level(ref l) => Some(l),
437             ParseErrorKind::Field(ref n) => Some(n.as_ref()),
438         }
439     }
440 }
441 
442 #[cfg(feature = "std")]
443 impl From<Box<dyn std::error::Error + Send + Sync>> for ParseError {
from(e: Box<dyn std::error::Error + Send + Sync>) -> Self444     fn from(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
445         Self {
446             kind: ParseErrorKind::Field(e),
447         }
448     }
449 }
450 
451 impl From<level::ParseError> for ParseError {
from(l: level::ParseError) -> Self452     fn from(l: level::ParseError) -> Self {
453         Self {
454             kind: ParseErrorKind::Level(l),
455         }
456     }
457 }
458