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