tracing_core/
metadata.rs1use super::{callsite, field};
3use crate::stdlib::{
4 cmp, fmt,
5 str::FromStr,
6 sync::atomic::{AtomicUsize, Ordering},
7};
8
9pub struct Metadata<'a> {
58 name: &'static str,
60
61 target: &'a str,
64
65 level: Level,
67
68 module_path: Option<&'a str>,
71
72 file: Option<&'a str>,
75
76 line: Option<u32>,
79
80 fields: field::FieldSet,
83
84 kind: Kind,
86}
87
88#[derive(Clone, Eq, PartialEq)]
90pub struct Kind(u8);
91
92#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
221pub struct Level(LevelInner);
222
223#[repr(transparent)]
238#[derive(Copy, Clone, Eq, PartialEq, Hash)]
239pub struct LevelFilter(Option<Level>);
240
241#[derive(Clone, Debug)]
243pub struct ParseLevelFilterError(());
244
245static MAX_LEVEL: AtomicUsize = AtomicUsize::new(LevelFilter::OFF_USIZE);
246
247impl<'a> Metadata<'a> {
250 pub const fn new(
253 name: &'static str,
254 target: &'a str,
255 level: Level,
256 file: Option<&'a str>,
257 line: Option<u32>,
258 module_path: Option<&'a str>,
259 fields: field::FieldSet,
260 kind: Kind,
261 ) -> Self {
262 Metadata {
263 name,
264 target,
265 level,
266 module_path,
267 file,
268 line,
269 fields,
270 kind,
271 }
272 }
273
274 #[inline]
276 pub fn fields(&self) -> &field::FieldSet {
277 &self.fields
278 }
279
280 pub fn level(&self) -> &Level {
282 &self.level
283 }
284
285 pub fn name(&self) -> &'static str {
287 self.name
288 }
289
290 pub fn target(&self) -> &'a str {
296 self.target
297 }
298
299 pub fn module_path(&self) -> Option<&'a str> {
302 self.module_path
303 }
304
305 pub fn file(&self) -> Option<&'a str> {
308 self.file
309 }
310
311 pub fn line(&self) -> Option<u32> {
314 self.line
315 }
316
317 #[inline]
320 pub fn callsite(&self) -> callsite::Identifier {
321 self.fields.callsite()
322 }
323
324 pub fn is_event(&self) -> bool {
326 self.kind.is_event()
327 }
328
329 pub fn is_span(&self) -> bool {
331 self.kind.is_span()
332 }
333}
334
335impl fmt::Debug for Metadata<'_> {
336 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337 let mut meta = f.debug_struct("Metadata");
338 meta.field("name", &self.name)
339 .field("target", &self.target)
340 .field("level", &self.level);
341
342 if let Some(path) = self.module_path() {
343 meta.field("module_path", &path);
344 }
345
346 match (self.file(), self.line()) {
347 (Some(file), Some(line)) => {
348 meta.field("location", &format_args!("{}:{}", file, line));
349 }
350 (Some(file), None) => {
351 meta.field("file", &format_args!("{}", file));
352 }
353
354 (None, Some(line)) => {
356 meta.field("line", &line);
357 }
358 (None, None) => {}
359 };
360
361 meta.field("fields", &format_args!("{}", self.fields))
362 .field("callsite", &self.callsite())
363 .field("kind", &self.kind)
364 .finish()
365 }
366}
367
368impl Kind {
369 const EVENT_BIT: u8 = 1 << 0;
370 const SPAN_BIT: u8 = 1 << 1;
371 const HINT_BIT: u8 = 1 << 2;
372
373 pub const EVENT: Kind = Kind(Self::EVENT_BIT);
375
376 pub const SPAN: Kind = Kind(Self::SPAN_BIT);
378
379 pub const HINT: Kind = Kind(Self::HINT_BIT);
383
384 pub fn is_span(&self) -> bool {
386 self.0 & Self::SPAN_BIT == Self::SPAN_BIT
387 }
388
389 pub fn is_event(&self) -> bool {
391 self.0 & Self::EVENT_BIT == Self::EVENT_BIT
392 }
393
394 pub fn is_hint(&self) -> bool {
396 self.0 & Self::HINT_BIT == Self::HINT_BIT
397 }
398
399 pub const fn hint(self) -> Self {
404 Self(self.0 | Self::HINT_BIT)
405 }
406}
407
408impl fmt::Debug for Kind {
409 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410 f.write_str("Kind(")?;
411 let mut has_bits = false;
412 let mut write_bit = |name: &str| {
413 if has_bits {
414 f.write_str(" | ")?;
415 }
416 f.write_str(name)?;
417 has_bits = true;
418 Ok(())
419 };
420
421 if self.is_event() {
422 write_bit("EVENT")?;
423 }
424
425 if self.is_span() {
426 write_bit("SPAN")?;
427 }
428
429 if self.is_hint() {
430 write_bit("HINT")?;
431 }
432
433 if !has_bits {
436 write!(f, "{:#b}", self.0)?;
437 }
438
439 f.write_str(")")
440 }
441}
442
443impl Eq for Metadata<'_> {}
444
445impl PartialEq for Metadata<'_> {
446 #[inline]
447 fn eq(&self, other: &Self) -> bool {
448 if core::ptr::eq(self, other) {
449 true
450 } else if cfg!(not(debug_assertions)) {
451 self.callsite() == other.callsite()
454 } else {
455 let Metadata {
462 name: lhs_name,
463 target: lhs_target,
464 level: lhs_level,
465 module_path: lhs_module_path,
466 file: lhs_file,
467 line: lhs_line,
468 fields: lhs_fields,
469 kind: lhs_kind,
470 } = self;
471
472 let Metadata {
473 name: rhs_name,
474 target: rhs_target,
475 level: rhs_level,
476 module_path: rhs_module_path,
477 file: rhs_file,
478 line: rhs_line,
479 fields: rhs_fields,
480 kind: rhs_kind,
481 } = &other;
482
483 self.callsite() == other.callsite()
487 && lhs_name == rhs_name
488 && lhs_target == rhs_target
489 && lhs_level == rhs_level
490 && lhs_module_path == rhs_module_path
491 && lhs_file == rhs_file
492 && lhs_line == rhs_line
493 && lhs_fields == rhs_fields
494 && lhs_kind == rhs_kind
495 }
496 }
497}
498
499impl Level {
502 pub const ERROR: Level = Level(LevelInner::Error);
506 pub const WARN: Level = Level(LevelInner::Warn);
510 pub const INFO: Level = Level(LevelInner::Info);
514 pub const DEBUG: Level = Level(LevelInner::Debug);
518 pub const TRACE: Level = Level(LevelInner::Trace);
522
523 pub fn as_str(&self) -> &'static str {
527 match *self {
528 Level::TRACE => "TRACE",
529 Level::DEBUG => "DEBUG",
530 Level::INFO => "INFO",
531 Level::WARN => "WARN",
532 Level::ERROR => "ERROR",
533 }
534 }
535}
536
537impl fmt::Display for Level {
538 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539 match *self {
540 Level::TRACE => f.pad("TRACE"),
541 Level::DEBUG => f.pad("DEBUG"),
542 Level::INFO => f.pad("INFO"),
543 Level::WARN => f.pad("WARN"),
544 Level::ERROR => f.pad("ERROR"),
545 }
546 }
547}
548
549#[cfg(feature = "std")]
550#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
551impl crate::stdlib::error::Error for ParseLevelError {}
552
553impl FromStr for Level {
554 type Err = ParseLevelError;
555 fn from_str(s: &str) -> Result<Self, ParseLevelError> {
556 s.parse::<usize>()
557 .map_err(|_| ParseLevelError { _p: () })
558 .and_then(|num| match num {
559 1 => Ok(Level::ERROR),
560 2 => Ok(Level::WARN),
561 3 => Ok(Level::INFO),
562 4 => Ok(Level::DEBUG),
563 5 => Ok(Level::TRACE),
564 _ => Err(ParseLevelError { _p: () }),
565 })
566 .or_else(|_| match s {
567 s if s.eq_ignore_ascii_case("error") => Ok(Level::ERROR),
568 s if s.eq_ignore_ascii_case("warn") => Ok(Level::WARN),
569 s if s.eq_ignore_ascii_case("info") => Ok(Level::INFO),
570 s if s.eq_ignore_ascii_case("debug") => Ok(Level::DEBUG),
571 s if s.eq_ignore_ascii_case("trace") => Ok(Level::TRACE),
572 _ => Err(ParseLevelError { _p: () }),
573 })
574 }
575}
576
577#[repr(usize)]
578#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
579enum LevelInner {
580 Trace = 0,
584 Debug = 1,
588 Info = 2,
592 Warn = 3,
596 Error = 4,
600}
601
602impl From<Level> for LevelFilter {
605 #[inline]
606 fn from(level: Level) -> Self {
607 Self::from_level(level)
608 }
609}
610
611impl From<Option<Level>> for LevelFilter {
612 #[inline]
613 fn from(level: Option<Level>) -> Self {
614 Self(level)
615 }
616}
617
618impl From<LevelFilter> for Option<Level> {
619 #[inline]
620 fn from(filter: LevelFilter) -> Self {
621 filter.into_level()
622 }
623}
624
625impl LevelFilter {
626 pub const OFF: LevelFilter = LevelFilter(None);
630 pub const ERROR: LevelFilter = LevelFilter::from_level(Level::ERROR);
634 pub const WARN: LevelFilter = LevelFilter::from_level(Level::WARN);
638 pub const INFO: LevelFilter = LevelFilter::from_level(Level::INFO);
642 pub const DEBUG: LevelFilter = LevelFilter::from_level(Level::DEBUG);
646 pub const TRACE: LevelFilter = LevelFilter(Some(Level::TRACE));
650
651 pub const fn from_level(level: Level) -> Self {
654 Self(Some(level))
655 }
656
657 pub const fn into_level(self) -> Option<Level> {
662 self.0
663 }
664
665 const ERROR_USIZE: usize = LevelInner::Error as usize;
668 const WARN_USIZE: usize = LevelInner::Warn as usize;
669 const INFO_USIZE: usize = LevelInner::Info as usize;
670 const DEBUG_USIZE: usize = LevelInner::Debug as usize;
671 const TRACE_USIZE: usize = LevelInner::Trace as usize;
672 const OFF_USIZE: usize = LevelInner::Error as usize + 1;
678
679 #[inline(always)]
696 pub fn current() -> Self {
697 match MAX_LEVEL.load(Ordering::Relaxed) {
698 Self::ERROR_USIZE => Self::ERROR,
699 Self::WARN_USIZE => Self::WARN,
700 Self::INFO_USIZE => Self::INFO,
701 Self::DEBUG_USIZE => Self::DEBUG,
702 Self::TRACE_USIZE => Self::TRACE,
703 Self::OFF_USIZE => Self::OFF,
704 #[cfg(debug_assertions)]
705 unknown => unreachable!(
706 "/!\\ `LevelFilter` representation seems to have changed! /!\\ \n\
707 This is a bug (and it's pretty bad). Please contact the `tracing` \
708 maintainers. Thank you and I'm sorry.\n \
709 The offending repr was: {:?}",
710 unknown,
711 ),
712 #[cfg(not(debug_assertions))]
713 _ => unsafe {
714 crate::stdlib::hint::unreachable_unchecked()
733 },
734 }
735 }
736
737 pub(crate) fn set_max(LevelFilter(level): LevelFilter) {
738 let val = match level {
739 Some(Level(level)) => level as usize,
740 None => Self::OFF_USIZE,
741 };
742
743 MAX_LEVEL.swap(val, Ordering::AcqRel);
746 }
747}
748
749impl fmt::Display for LevelFilter {
750 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
751 match *self {
752 LevelFilter::OFF => f.pad("off"),
753 LevelFilter::ERROR => f.pad("error"),
754 LevelFilter::WARN => f.pad("warn"),
755 LevelFilter::INFO => f.pad("info"),
756 LevelFilter::DEBUG => f.pad("debug"),
757 LevelFilter::TRACE => f.pad("trace"),
758 }
759 }
760}
761
762impl fmt::Debug for LevelFilter {
763 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
764 match *self {
765 LevelFilter::OFF => f.pad("LevelFilter::OFF"),
766 LevelFilter::ERROR => f.pad("LevelFilter::ERROR"),
767 LevelFilter::WARN => f.pad("LevelFilter::WARN"),
768 LevelFilter::INFO => f.pad("LevelFilter::INFO"),
769 LevelFilter::DEBUG => f.pad("LevelFilter::DEBUG"),
770 LevelFilter::TRACE => f.pad("LevelFilter::TRACE"),
771 }
772 }
773}
774
775impl FromStr for LevelFilter {
776 type Err = ParseLevelFilterError;
777 fn from_str(from: &str) -> Result<Self, Self::Err> {
778 from.parse::<usize>()
779 .ok()
780 .and_then(|num| match num {
781 0 => Some(LevelFilter::OFF),
782 1 => Some(LevelFilter::ERROR),
783 2 => Some(LevelFilter::WARN),
784 3 => Some(LevelFilter::INFO),
785 4 => Some(LevelFilter::DEBUG),
786 5 => Some(LevelFilter::TRACE),
787 _ => None,
788 })
789 .or_else(|| match from {
790 "" => Some(LevelFilter::ERROR),
791 s if s.eq_ignore_ascii_case("error") => Some(LevelFilter::ERROR),
792 s if s.eq_ignore_ascii_case("warn") => Some(LevelFilter::WARN),
793 s if s.eq_ignore_ascii_case("info") => Some(LevelFilter::INFO),
794 s if s.eq_ignore_ascii_case("debug") => Some(LevelFilter::DEBUG),
795 s if s.eq_ignore_ascii_case("trace") => Some(LevelFilter::TRACE),
796 s if s.eq_ignore_ascii_case("off") => Some(LevelFilter::OFF),
797 _ => None,
798 })
799 .ok_or(ParseLevelFilterError(()))
800 }
801}
802
803#[derive(Debug)]
805pub struct ParseLevelError {
806 _p: (),
807}
808
809impl fmt::Display for ParseLevelError {
810 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
811 f.pad(
812 "error parsing level: expected one of \"error\", \"warn\", \
813 \"info\", \"debug\", \"trace\", or a number 1-5",
814 )
815 }
816}
817
818impl fmt::Display for ParseLevelFilterError {
819 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
820 f.pad(
821 "error parsing level filter: expected one of \"off\", \"error\", \
822 \"warn\", \"info\", \"debug\", \"trace\", or a number 0-5",
823 )
824 }
825}
826
827#[cfg(feature = "std")]
828impl std::error::Error for ParseLevelFilterError {}
829
830impl PartialEq<LevelFilter> for Level {
904 #[inline(always)]
905 fn eq(&self, other: &LevelFilter) -> bool {
906 self.0 as usize == filter_as_usize(&other.0)
907 }
908}
909
910impl PartialOrd for Level {
911 #[inline(always)]
912 fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
913 Some(self.cmp(other))
914 }
915
916 #[inline(always)]
917 fn lt(&self, other: &Level) -> bool {
918 (other.0 as usize) < (self.0 as usize)
919 }
920
921 #[inline(always)]
922 fn le(&self, other: &Level) -> bool {
923 (other.0 as usize) <= (self.0 as usize)
924 }
925
926 #[inline(always)]
927 fn gt(&self, other: &Level) -> bool {
928 (other.0 as usize) > (self.0 as usize)
929 }
930
931 #[inline(always)]
932 fn ge(&self, other: &Level) -> bool {
933 (other.0 as usize) >= (self.0 as usize)
934 }
935}
936
937impl Ord for Level {
938 #[inline(always)]
939 fn cmp(&self, other: &Self) -> cmp::Ordering {
940 (other.0 as usize).cmp(&(self.0 as usize))
941 }
942}
943
944impl PartialOrd<LevelFilter> for Level {
945 #[inline(always)]
946 fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
947 Some(filter_as_usize(&other.0).cmp(&(self.0 as usize)))
948 }
949
950 #[inline(always)]
951 fn lt(&self, other: &LevelFilter) -> bool {
952 filter_as_usize(&other.0) < (self.0 as usize)
953 }
954
955 #[inline(always)]
956 fn le(&self, other: &LevelFilter) -> bool {
957 filter_as_usize(&other.0) <= (self.0 as usize)
958 }
959
960 #[inline(always)]
961 fn gt(&self, other: &LevelFilter) -> bool {
962 filter_as_usize(&other.0) > (self.0 as usize)
963 }
964
965 #[inline(always)]
966 fn ge(&self, other: &LevelFilter) -> bool {
967 filter_as_usize(&other.0) >= (self.0 as usize)
968 }
969}
970
971#[inline(always)]
972fn filter_as_usize(x: &Option<Level>) -> usize {
973 match x {
974 Some(Level(f)) => *f as usize,
975 None => LevelFilter::OFF_USIZE,
976 }
977}
978
979impl PartialEq<Level> for LevelFilter {
980 #[inline(always)]
981 fn eq(&self, other: &Level) -> bool {
982 filter_as_usize(&self.0) == other.0 as usize
983 }
984}
985
986impl PartialOrd for LevelFilter {
987 #[inline(always)]
988 fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
989 Some(self.cmp(other))
990 }
991
992 #[inline(always)]
993 fn lt(&self, other: &LevelFilter) -> bool {
994 filter_as_usize(&other.0) < filter_as_usize(&self.0)
995 }
996
997 #[inline(always)]
998 fn le(&self, other: &LevelFilter) -> bool {
999 filter_as_usize(&other.0) <= filter_as_usize(&self.0)
1000 }
1001
1002 #[inline(always)]
1003 fn gt(&self, other: &LevelFilter) -> bool {
1004 filter_as_usize(&other.0) > filter_as_usize(&self.0)
1005 }
1006
1007 #[inline(always)]
1008 fn ge(&self, other: &LevelFilter) -> bool {
1009 filter_as_usize(&other.0) >= filter_as_usize(&self.0)
1010 }
1011}
1012
1013impl Ord for LevelFilter {
1014 #[inline(always)]
1015 fn cmp(&self, other: &Self) -> cmp::Ordering {
1016 filter_as_usize(&other.0).cmp(&filter_as_usize(&self.0))
1017 }
1018}
1019
1020impl PartialOrd<Level> for LevelFilter {
1021 #[inline(always)]
1022 fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
1023 Some((other.0 as usize).cmp(&filter_as_usize(&self.0)))
1024 }
1025
1026 #[inline(always)]
1027 fn lt(&self, other: &Level) -> bool {
1028 (other.0 as usize) < filter_as_usize(&self.0)
1029 }
1030
1031 #[inline(always)]
1032 fn le(&self, other: &Level) -> bool {
1033 (other.0 as usize) <= filter_as_usize(&self.0)
1034 }
1035
1036 #[inline(always)]
1037 fn gt(&self, other: &Level) -> bool {
1038 (other.0 as usize) > filter_as_usize(&self.0)
1039 }
1040
1041 #[inline(always)]
1042 fn ge(&self, other: &Level) -> bool {
1043 (other.0 as usize) >= filter_as_usize(&self.0)
1044 }
1045}
1046
1047#[cfg(test)]
1048mod tests {
1049 use super::*;
1050 use crate::stdlib::mem;
1051
1052 #[test]
1053 fn level_from_str() {
1054 assert_eq!("error".parse::<Level>().unwrap(), Level::ERROR);
1055 assert_eq!("4".parse::<Level>().unwrap(), Level::DEBUG);
1056 assert!("0".parse::<Level>().is_err())
1057 }
1058
1059 #[test]
1060 fn filter_level_conversion() {
1061 let mapping = [
1062 (LevelFilter::OFF, None),
1063 (LevelFilter::ERROR, Some(Level::ERROR)),
1064 (LevelFilter::WARN, Some(Level::WARN)),
1065 (LevelFilter::INFO, Some(Level::INFO)),
1066 (LevelFilter::DEBUG, Some(Level::DEBUG)),
1067 (LevelFilter::TRACE, Some(Level::TRACE)),
1068 ];
1069 for (filter, level) in mapping.iter() {
1070 assert_eq!(filter.into_level(), *level);
1071 match level {
1072 Some(level) => {
1073 let actual: LevelFilter = (*level).into();
1074 assert_eq!(actual, *filter);
1075 }
1076 None => {
1077 let actual: LevelFilter = None.into();
1078 assert_eq!(actual, *filter);
1079 }
1080 }
1081 }
1082 }
1083
1084 #[test]
1085 fn level_filter_is_usize_sized() {
1086 assert_eq!(
1087 mem::size_of::<LevelFilter>(),
1088 mem::size_of::<usize>(),
1089 "`LevelFilter` is no longer `usize`-sized! global MAX_LEVEL may now be invalid!"
1090 )
1091 }
1092
1093 #[test]
1094 fn level_filter_reprs() {
1095 let mapping = [
1096 (LevelFilter::OFF, LevelInner::Error as usize + 1),
1097 (LevelFilter::ERROR, LevelInner::Error as usize),
1098 (LevelFilter::WARN, LevelInner::Warn as usize),
1099 (LevelFilter::INFO, LevelInner::Info as usize),
1100 (LevelFilter::DEBUG, LevelInner::Debug as usize),
1101 (LevelFilter::TRACE, LevelInner::Trace as usize),
1102 ];
1103 for &(filter, expected) in &mapping {
1104 let repr = unsafe {
1105 mem::transmute::<LevelFilter, usize>(filter)
1110 };
1111 assert_eq!(expected, repr, "repr changed for {:?}", filter)
1112 }
1113 }
1114}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4