tracing_subscriber/filter/
directive.rs
1use crate::filter::level::{self, LevelFilter};
2use alloc::{string::String, vec::Vec};
3use core::{cmp::Ordering, fmt, iter::FromIterator, slice, str::FromStr};
4use tracing_core::{Level, Metadata};
5#[derive(Debug)]
7pub struct ParseError {
8 kind: ParseErrorKind,
9}
10
11#[derive(Debug, PartialEq, Eq, Clone)]
15pub(crate) struct StaticDirective {
16 pub(in crate::filter) target: Option<String>,
17 pub(in crate::filter) field_names: Vec<String>,
18 pub(in crate::filter) level: LevelFilter,
19}
20
21#[cfg(feature = "smallvec")]
22pub(crate) type FilterVec<T> = smallvec::SmallVec<[T; 8]>;
23#[cfg(not(feature = "smallvec"))]
24pub(crate) type FilterVec<T> = Vec<T>;
25
26#[derive(Debug, PartialEq, Clone)]
27pub(in crate::filter) struct DirectiveSet<T> {
28 directives: FilterVec<T>,
29 pub(in crate::filter) max_level: LevelFilter,
30}
31
32pub(in crate::filter) trait Match {
33 fn cares_about(&self, meta: &Metadata<'_>) -> bool;
34 fn level(&self) -> &LevelFilter;
35}
36
37#[derive(Debug)]
38enum ParseErrorKind {
39 #[cfg(feature = "std")]
40 Field(Box<dyn std::error::Error + Send + Sync>),
41 Level(level::ParseError),
42 Other(Option<&'static str>),
43}
44
45impl<T> DirectiveSet<T> {
48 #[cfg(all(feature = "std", feature = "env-filter"))]
50 pub(crate) fn is_empty(&self) -> bool {
51 self.directives.is_empty()
52 }
53
54 pub(crate) fn iter(&self) -> slice::Iter<'_, T> {
55 self.directives.iter()
56 }
57}
58
59impl<T: Ord> Default for DirectiveSet<T> {
60 fn default() -> Self {
61 Self {
62 directives: FilterVec::new(),
63 max_level: LevelFilter::OFF,
64 }
65 }
66}
67
68impl<T: Match + Ord> DirectiveSet<T> {
69 pub(crate) fn directives(&self) -> impl Iterator<Item = &T> {
70 self.directives.iter()
71 }
72
73 pub(crate) fn directives_for<'a>(
74 &'a self,
75 metadata: &'a Metadata<'a>,
76 ) -> impl Iterator<Item = &'a T> + 'a {
77 self.directives().filter(move |d| d.cares_about(metadata))
78 }
79
80 pub(crate) fn add(&mut self, directive: T) {
81 let level = *directive.level();
84 if level > self.max_level {
85 self.max_level = level;
86 }
87 match self.directives.binary_search(&directive) {
92 Ok(i) => self.directives[i] = directive,
93 Err(i) => self.directives.insert(i, directive),
94 }
95 }
96
97 #[cfg(test)]
98 pub(in crate::filter) fn into_vec(self) -> FilterVec<T> {
99 self.directives
100 }
101}
102
103impl<T: Match + Ord> FromIterator<T> for DirectiveSet<T> {
104 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
105 let mut this = Self::default();
106 this.extend(iter);
107 this
108 }
109}
110
111impl<T: Match + Ord> Extend<T> for DirectiveSet<T> {
112 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
113 for directive in iter.into_iter() {
114 self.add(directive);
115 }
116 }
117}
118
119impl<T> IntoIterator for DirectiveSet<T> {
120 type Item = T;
121
122 #[cfg(feature = "smallvec")]
123 type IntoIter = smallvec::IntoIter<[T; 8]>;
124 #[cfg(not(feature = "smallvec"))]
125 type IntoIter = alloc::vec::IntoIter<T>;
126
127 fn into_iter(self) -> Self::IntoIter {
128 self.directives.into_iter()
129 }
130}
131
132impl DirectiveSet<StaticDirective> {
135 pub(crate) fn enabled(&self, meta: &Metadata<'_>) -> bool {
136 let level = meta.level();
137 match self.directives_for(meta).next() {
138 Some(d) => d.level >= *level,
139 None => false,
140 }
141 }
142
143 pub(crate) fn target_enabled(&self, target: &str, level: &Level) -> bool {
145 match self.directives_for_target(target).next() {
146 Some(d) => d.level >= *level,
147 None => false,
148 }
149 }
150
151 pub(crate) fn directives_for_target<'a>(
152 &'a self,
153 target: &'a str,
154 ) -> impl Iterator<Item = &'a StaticDirective> + 'a {
155 self.directives()
156 .filter(move |d| d.cares_about_target(target))
157 }
158}
159
160impl StaticDirective {
163 pub(in crate::filter) fn new(
164 target: Option<String>,
165 field_names: Vec<String>,
166 level: LevelFilter,
167 ) -> Self {
168 Self {
169 target,
170 field_names,
171 level,
172 }
173 }
174
175 pub(in crate::filter) fn cares_about_target(&self, to_check: &str) -> bool {
176 if let Some(ref target) = self.target {
179 if !to_check.starts_with(&target[..]) {
180 return false;
181 }
182 }
183
184 if !self.field_names.is_empty() {
185 return false;
186 }
187
188 true
189 }
190}
191
192impl Ord for StaticDirective {
193 fn cmp(&self, other: &StaticDirective) -> Ordering {
194 let ordering = self
201 .target
202 .as_ref()
203 .map(String::len)
204 .cmp(&other.target.as_ref().map(String::len))
205 .then_with(|| self.field_names.len().cmp(&other.field_names.len()))
207 .then_with(|| {
212 self.target
213 .cmp(&other.target)
214 .then_with(|| self.field_names[..].cmp(&other.field_names[..]))
215 })
216 .reverse();
217
218 #[cfg(debug_assertions)]
219 {
220 if ordering == Ordering::Equal {
221 debug_assert_eq!(
222 self.target, other.target,
223 "invariant violated: Ordering::Equal must imply a.target == b.target"
224 );
225 debug_assert_eq!(
226 self.field_names, other.field_names,
227 "invariant violated: Ordering::Equal must imply a.field_names == b.field_names"
228 );
229 }
230 }
231
232 ordering
233 }
234}
235
236impl PartialOrd for StaticDirective {
237 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
238 Some(self.cmp(other))
239 }
240}
241
242impl Match for StaticDirective {
243 fn cares_about(&self, meta: &Metadata<'_>) -> bool {
244 if let Some(ref target) = self.target {
247 if !meta.target().starts_with(&target[..]) {
248 return false;
249 }
250 }
251
252 if meta.is_event() && !self.field_names.is_empty() {
253 let fields = meta.fields();
254 for name in &self.field_names {
255 if fields.field(name).is_none() {
256 return false;
257 }
258 }
259 }
260
261 true
262 }
263
264 fn level(&self) -> &LevelFilter {
265 &self.level
266 }
267}
268
269impl Default for StaticDirective {
270 fn default() -> Self {
271 StaticDirective {
272 target: None,
273 field_names: Vec::new(),
274 level: LevelFilter::ERROR,
275 }
276 }
277}
278
279impl fmt::Display for StaticDirective {
280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281 let mut wrote_any = false;
282 if let Some(ref target) = self.target {
283 fmt::Display::fmt(target, f)?;
284 wrote_any = true;
285 }
286
287 if !self.field_names.is_empty() {
288 f.write_str("[")?;
289
290 let mut fields = self.field_names.iter();
291 if let Some(field) = fields.next() {
292 write!(f, "{{{}", field)?;
293 for field in fields {
294 write!(f, ",{}", field)?;
295 }
296 f.write_str("}")?;
297 }
298
299 f.write_str("]")?;
300 wrote_any = true;
301 }
302
303 if wrote_any {
304 f.write_str("=")?;
305 }
306
307 fmt::Display::fmt(&self.level, f)
308 }
309}
310
311impl FromStr for StaticDirective {
312 type Err = ParseError;
313
314 fn from_str(s: &str) -> Result<Self, Self::Err> {
315 let mut split = s.split('=');
323 let part0 = split
324 .next()
325 .ok_or_else(|| ParseError::msg("string must not be empty"))?;
326
327 if let Some(part1) = split.next() {
332 if split.next().is_some() {
333 return Err(ParseError::msg(
334 "too many '=' in filter directive, expected 0 or 1",
335 ));
336 }
337
338 let mut split = part0.split("[{");
339 let target = split.next().map(String::from);
340 let mut field_names = Vec::new();
341 if let Some(maybe_fields) = split.next() {
345 if split.next().is_some() {
346 return Err(ParseError::msg(
347 "too many '[{' in filter directive, expected 0 or 1",
348 ));
349 }
350
351 let fields = maybe_fields
352 .strip_suffix("}]")
353 .ok_or_else(|| ParseError::msg("expected fields list to end with '}]'"))?;
354 field_names.extend(fields.split(',').filter_map(|s| {
355 if s.is_empty() {
356 None
357 } else {
358 Some(String::from(s))
359 }
360 }));
361 };
362 let level = part1.parse()?;
363 return Ok(Self {
364 level,
365 field_names,
366 target,
367 });
368 }
369
370 Ok(match part0.parse::<LevelFilter>() {
375 Ok(level) => Self {
376 level,
377 target: None,
378 field_names: Vec::new(),
379 },
380 Err(_) => Self {
381 target: Some(String::from(part0)),
382 level: LevelFilter::TRACE,
383 field_names: Vec::new(),
384 },
385 })
386 }
387}
388
389impl ParseError {
392 #[cfg(all(feature = "std", feature = "env-filter"))]
393 pub(crate) fn new() -> Self {
394 ParseError {
395 kind: ParseErrorKind::Other(None),
396 }
397 }
398
399 pub(crate) fn msg(s: &'static str) -> Self {
400 ParseError {
401 kind: ParseErrorKind::Other(Some(s)),
402 }
403 }
404}
405
406impl fmt::Display for ParseError {
407 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
408 match self.kind {
409 ParseErrorKind::Other(None) => f.pad("invalid filter directive"),
410 ParseErrorKind::Other(Some(msg)) => write!(f, "invalid filter directive: {}", msg),
411 ParseErrorKind::Level(ref l) => l.fmt(f),
412 #[cfg(feature = "std")]
413 ParseErrorKind::Field(ref e) => write!(f, "invalid field filter: {}", e),
414 }
415 }
416}
417
418#[cfg(feature = "std")]
419impl std::error::Error for ParseError {
420 fn description(&self) -> &str {
421 "invalid filter directive"
422 }
423
424 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
425 match self.kind {
426 ParseErrorKind::Other(_) => None,
427 ParseErrorKind::Level(ref l) => Some(l),
428 ParseErrorKind::Field(ref n) => Some(n.as_ref()),
429 }
430 }
431}
432
433#[cfg(feature = "std")]
434impl From<Box<dyn std::error::Error + Send + Sync>> for ParseError {
435 fn from(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
436 Self {
437 kind: ParseErrorKind::Field(e),
438 }
439 }
440}
441
442impl From<level::ParseError> for ParseError {
443 fn from(l: level::ParseError) -> Self {
444 Self {
445 kind: ParseErrorKind::Level(l),
446 }
447 }
448}