1#![doc(
345 html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
346 html_favicon_url = "https://www.rust-lang.org/favicon.ico",
347 html_root_url = "https://docs.rs/log/0.4.28"
348)]
349#![warn(missing_docs)]
350#![deny(missing_debug_implementations, unconditional_recursion)]
351#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
352
353#[cfg(any(
354 all(feature = "max_level_off", feature = "max_level_error"),
355 all(feature = "max_level_off", feature = "max_level_warn"),
356 all(feature = "max_level_off", feature = "max_level_info"),
357 all(feature = "max_level_off", feature = "max_level_debug"),
358 all(feature = "max_level_off", feature = "max_level_trace"),
359 all(feature = "max_level_error", feature = "max_level_warn"),
360 all(feature = "max_level_error", feature = "max_level_info"),
361 all(feature = "max_level_error", feature = "max_level_debug"),
362 all(feature = "max_level_error", feature = "max_level_trace"),
363 all(feature = "max_level_warn", feature = "max_level_info"),
364 all(feature = "max_level_warn", feature = "max_level_debug"),
365 all(feature = "max_level_warn", feature = "max_level_trace"),
366 all(feature = "max_level_info", feature = "max_level_debug"),
367 all(feature = "max_level_info", feature = "max_level_trace"),
368 all(feature = "max_level_debug", feature = "max_level_trace"),
369))]
370compile_error!("multiple max_level_* features set");
371
372#[rustfmt::skip]
373#[cfg(any(
374 all(feature = "release_max_level_off", feature = "release_max_level_error"),
375 all(feature = "release_max_level_off", feature = "release_max_level_warn"),
376 all(feature = "release_max_level_off", feature = "release_max_level_info"),
377 all(feature = "release_max_level_off", feature = "release_max_level_debug"),
378 all(feature = "release_max_level_off", feature = "release_max_level_trace"),
379 all(feature = "release_max_level_error", feature = "release_max_level_warn"),
380 all(feature = "release_max_level_error", feature = "release_max_level_info"),
381 all(feature = "release_max_level_error", feature = "release_max_level_debug"),
382 all(feature = "release_max_level_error", feature = "release_max_level_trace"),
383 all(feature = "release_max_level_warn", feature = "release_max_level_info"),
384 all(feature = "release_max_level_warn", feature = "release_max_level_debug"),
385 all(feature = "release_max_level_warn", feature = "release_max_level_trace"),
386 all(feature = "release_max_level_info", feature = "release_max_level_debug"),
387 all(feature = "release_max_level_info", feature = "release_max_level_trace"),
388 all(feature = "release_max_level_debug", feature = "release_max_level_trace"),
389))]
390compile_error!("multiple release_max_level_* features set");
391
392#[cfg(all(not(feature = "std"), not(test)))]
393extern crate core as std;
394
395use std::cfg;
396#[cfg(feature = "std")]
397use std::error;
398use std::str::FromStr;
399use std::{cmp, fmt, mem};
400
401#[macro_use]
402mod macros;
403mod serde;
404
405#[cfg(feature = "kv")]
406pub mod kv;
407
408#[cfg(target_has_atomic = "ptr")]
409use std::sync::atomic::{AtomicUsize, Ordering};
410
411#[cfg(not(target_has_atomic = "ptr"))]
412use std::cell::Cell;
413#[cfg(not(target_has_atomic = "ptr"))]
414use std::sync::atomic::Ordering;
415
416#[cfg(not(target_has_atomic = "ptr"))]
417struct AtomicUsize {
418 v: Cell<usize>,
419}
420
421#[cfg(not(target_has_atomic = "ptr"))]
422impl AtomicUsize {
423 const fn new(v: usize) -> AtomicUsize {
424 AtomicUsize { v: Cell::new(v) }
425 }
426
427 fn load(&self, _order: Ordering) -> usize {
428 self.v.get()
429 }
430
431 fn store(&self, val: usize, _order: Ordering) {
432 self.v.set(val)
433 }
434}
435
436#[cfg(not(target_has_atomic = "ptr"))]
439unsafe impl Sync for AtomicUsize {}
440
441static mut LOGGER: &dyn Log = &NopLogger;
444
445static STATE: AtomicUsize = AtomicUsize::new(0);
446
447const UNINITIALIZED: usize = 0;
451const INITIALIZING: usize = 1;
452const INITIALIZED: usize = 2;
453
454static MAX_LOG_LEVEL_FILTER: AtomicUsize = AtomicUsize::new(0);
455
456static LOG_LEVEL_NAMES: [&str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
457
458static SET_LOGGER_ERROR: &str = "attempted to set a logger after the logging system \
459 was already initialized";
460static LEVEL_PARSE_ERROR: &str =
461 "attempted to convert a string that doesn't match an existing log level";
462
463#[repr(usize)]
470#[derive(#[automatically_derived]
impl ::core::clone::Clone for Level {
#[inline]
fn clone(&self) -> Level { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Level { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Level {
#[inline]
fn eq(&self, other: &Level) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Level {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Level {
#[inline]
fn partial_cmp(&self, other: &Level)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Level {
#[inline]
fn cmp(&self, other: &Level) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
}
}Ord, #[automatically_derived]
impl ::core::fmt::Debug for Level {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Level::Error => "Error",
Level::Warn => "Warn",
Level::Info => "Info",
Level::Debug => "Debug",
Level::Trace => "Trace",
})
}
}Debug, #[automatically_derived]
impl ::core::hash::Hash for Level {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash)]
471pub enum Level {
472 Error = 1,
479 Warn,
483 Info,
487 Debug,
491 Trace,
495}
496
497impl PartialEq<LevelFilter> for Level {
498 #[inline]
499 fn eq(&self, other: &LevelFilter) -> bool {
500 *self as usize == *other as usize
501 }
502}
503
504impl PartialOrd<LevelFilter> for Level {
505 #[inline]
506 fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
507 Some((*self as usize).cmp(&(*other as usize)))
508 }
509}
510
511impl FromStr for Level {
512 type Err = ParseLevelError;
513 fn from_str(level: &str) -> Result<Level, Self::Err> {
514 LOG_LEVEL_NAMES
515 .iter()
516 .position(|&name| name.eq_ignore_ascii_case(level))
517 .into_iter()
518 .filter(|&idx| idx != 0)
519 .map(|idx| Level::from_usize(idx).unwrap())
520 .next()
521 .ok_or(ParseLevelError(()))
522 }
523}
524
525impl fmt::Display for Level {
526 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
527 fmt.pad(self.as_str())
528 }
529}
530
531impl Level {
532 fn from_usize(u: usize) -> Option<Level> {
533 match u {
534 1 => Some(Level::Error),
535 2 => Some(Level::Warn),
536 3 => Some(Level::Info),
537 4 => Some(Level::Debug),
538 5 => Some(Level::Trace),
539 _ => None,
540 }
541 }
542
543 #[inline]
545 pub fn max() -> Level {
546 Level::Trace
547 }
548
549 #[inline]
551 pub fn to_level_filter(&self) -> LevelFilter {
552 LevelFilter::from_usize(*self as usize).unwrap()
553 }
554
555 pub fn as_str(&self) -> &'static str {
559 LOG_LEVEL_NAMES[*self as usize]
560 }
561
562 pub fn iter() -> impl Iterator<Item = Self> {
577 (1..6).map(|i| Self::from_usize(i).unwrap())
578 }
579
580 pub fn increment_severity(&self) -> Self {
597 let current = *self as usize;
598 Self::from_usize(current + 1).unwrap_or(*self)
599 }
600
601 pub fn decrement_severity(&self) -> Self {
618 let current = *self as usize;
619 Self::from_usize(current.saturating_sub(1)).unwrap_or(*self)
620 }
621}
622
623#[repr(usize)]
632#[derive(#[automatically_derived]
impl ::core::clone::Clone for LevelFilter {
#[inline]
fn clone(&self) -> LevelFilter { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for LevelFilter { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for LevelFilter {
#[inline]
fn eq(&self, other: &LevelFilter) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for LevelFilter {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for LevelFilter {
#[inline]
fn partial_cmp(&self, other: &LevelFilter)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for LevelFilter {
#[inline]
fn cmp(&self, other: &LevelFilter) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
}
}Ord, #[automatically_derived]
impl ::core::fmt::Debug for LevelFilter {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
LevelFilter::Off => "Off",
LevelFilter::Error => "Error",
LevelFilter::Warn => "Warn",
LevelFilter::Info => "Info",
LevelFilter::Debug => "Debug",
LevelFilter::Trace => "Trace",
})
}
}Debug, #[automatically_derived]
impl ::core::hash::Hash for LevelFilter {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash)]
633pub enum LevelFilter {
634 Off,
636 Error,
638 Warn,
640 Info,
642 Debug,
644 Trace,
646}
647
648impl PartialEq<Level> for LevelFilter {
649 #[inline]
650 fn eq(&self, other: &Level) -> bool {
651 other.eq(self)
652 }
653}
654
655impl PartialOrd<Level> for LevelFilter {
656 #[inline]
657 fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
658 Some((*self as usize).cmp(&(*other as usize)))
659 }
660}
661
662impl FromStr for LevelFilter {
663 type Err = ParseLevelError;
664 fn from_str(level: &str) -> Result<LevelFilter, Self::Err> {
665 LOG_LEVEL_NAMES
666 .iter()
667 .position(|&name| name.eq_ignore_ascii_case(level))
668 .map(|p| LevelFilter::from_usize(p).unwrap())
669 .ok_or(ParseLevelError(()))
670 }
671}
672
673impl fmt::Display for LevelFilter {
674 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
675 fmt.pad(self.as_str())
676 }
677}
678
679impl LevelFilter {
680 fn from_usize(u: usize) -> Option<LevelFilter> {
681 match u {
682 0 => Some(LevelFilter::Off),
683 1 => Some(LevelFilter::Error),
684 2 => Some(LevelFilter::Warn),
685 3 => Some(LevelFilter::Info),
686 4 => Some(LevelFilter::Debug),
687 5 => Some(LevelFilter::Trace),
688 _ => None,
689 }
690 }
691
692 #[inline]
694 pub fn max() -> LevelFilter {
695 LevelFilter::Trace
696 }
697
698 #[inline]
702 pub fn to_level(&self) -> Option<Level> {
703 Level::from_usize(*self as usize)
704 }
705
706 pub fn as_str(&self) -> &'static str {
710 LOG_LEVEL_NAMES[*self as usize]
711 }
712
713 pub fn iter() -> impl Iterator<Item = Self> {
728 (0..6).map(|i| Self::from_usize(i).unwrap())
729 }
730
731 pub fn increment_severity(&self) -> Self {
748 let current = *self as usize;
749 Self::from_usize(current + 1).unwrap_or(*self)
750 }
751
752 pub fn decrement_severity(&self) -> Self {
770 let current = *self as usize;
771 Self::from_usize(current.saturating_sub(1)).unwrap_or(*self)
772 }
773}
774
775#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for MaybeStaticStr<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for MaybeStaticStr<'a> {
#[inline]
fn clone(&self) -> MaybeStaticStr<'a> {
let _: ::core::clone::AssertParamIsClone<&'static str>;
let _: ::core::clone::AssertParamIsClone<&'a str>;
*self
}
}Clone, #[automatically_derived]
impl<'a> ::core::cmp::Eq for MaybeStaticStr<'a> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<&'static str>;
let _: ::core::cmp::AssertParamIsEq<&'a str>;
}
}Eq, #[automatically_derived]
impl<'a> ::core::cmp::PartialEq for MaybeStaticStr<'a> {
#[inline]
fn eq(&self, other: &MaybeStaticStr<'a>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(MaybeStaticStr::Static(__self_0),
MaybeStaticStr::Static(__arg1_0)) => __self_0 == __arg1_0,
(MaybeStaticStr::Borrowed(__self_0),
MaybeStaticStr::Borrowed(__arg1_0)) => __self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl<'a> ::core::cmp::Ord for MaybeStaticStr<'a> {
#[inline]
fn cmp(&self, other: &MaybeStaticStr<'a>) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(MaybeStaticStr::Static(__self_0),
MaybeStaticStr::Static(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(MaybeStaticStr::Borrowed(__self_0),
MaybeStaticStr::Borrowed(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => unsafe { ::core::intrinsics::unreachable() }
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl<'a> ::core::cmp::PartialOrd for MaybeStaticStr<'a> {
#[inline]
fn partial_cmp(&self, other: &MaybeStaticStr<'a>)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match (self, other) {
(MaybeStaticStr::Static(__self_0),
MaybeStaticStr::Static(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(MaybeStaticStr::Borrowed(__self_0),
MaybeStaticStr::Borrowed(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr),
}
}
}PartialOrd, #[automatically_derived]
impl<'a> ::core::hash::Hash for MaybeStaticStr<'a> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
MaybeStaticStr::Static(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
MaybeStaticStr::Borrowed(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
}
}
}Hash, #[automatically_derived]
impl<'a> ::core::fmt::Debug for MaybeStaticStr<'a> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
MaybeStaticStr::Static(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Static",
&__self_0),
MaybeStaticStr::Borrowed(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Borrowed", &__self_0),
}
}
}Debug)]
776enum MaybeStaticStr<'a> {
777 Static(&'static str),
778 Borrowed(&'a str),
779}
780
781impl<'a> MaybeStaticStr<'a> {
782 #[inline]
783 fn get(&self) -> &'a str {
784 match *self {
785 MaybeStaticStr::Static(s) => s,
786 MaybeStaticStr::Borrowed(s) => s,
787 }
788 }
789}
790
791)]
837pub struct Record<'a> {
838 metadata: Metadata<'a>,
839 args: fmt::Arguments<'a>,
840 module_path: Option<MaybeStaticStr<'a>>,
841 file: Option<MaybeStaticStr<'a>>,
842 line: Option<u32>,
843 #[cfg(feature = "kv")]
844 key_values: KeyValues<'a>,
845}
846
847#[cfg(feature = "kv")]
852#[derive(Clone)]
853struct KeyValues<'a>(&'a dyn kv::Source);
854
855#[cfg(feature = "kv")]
856impl<'a> fmt::Debug for KeyValues<'a> {
857 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
858 let mut visitor = f.debug_map();
859 self.0.visit(&mut visitor).map_err(|_| fmt::Error)?;
860 visitor.finish()
861 }
862}
863
864impl<'a> Record<'a> {
865 #[inline]
867 pub fn builder() -> RecordBuilder<'a> {
868 RecordBuilder::new()
869 }
870
871 #[inline]
873 pub fn args(&self) -> &fmt::Arguments<'a> {
874 &self.args
875 }
876
877 #[inline]
879 pub fn metadata(&self) -> &Metadata<'a> {
880 &self.metadata
881 }
882
883 #[inline]
885 pub fn level(&self) -> Level {
886 self.metadata.level()
887 }
888
889 #[inline]
891 pub fn target(&self) -> &'a str {
892 self.metadata.target()
893 }
894
895 #[inline]
897 pub fn module_path(&self) -> Option<&'a str> {
898 self.module_path.map(|s| s.get())
899 }
900
901 #[inline]
903 pub fn module_path_static(&self) -> Option<&'static str> {
904 match self.module_path {
905 Some(MaybeStaticStr::Static(s)) => Some(s),
906 _ => None,
907 }
908 }
909
910 #[inline]
912 pub fn file(&self) -> Option<&'a str> {
913 self.file.map(|s| s.get())
914 }
915
916 #[inline]
918 pub fn file_static(&self) -> Option<&'static str> {
919 match self.file {
920 Some(MaybeStaticStr::Static(s)) => Some(s),
921 _ => None,
922 }
923 }
924
925 #[inline]
927 pub fn line(&self) -> Option<u32> {
928 self.line
929 }
930
931 #[cfg(feature = "kv")]
933 #[inline]
934 pub fn key_values(&self) -> &dyn kv::Source {
935 self.key_values.0
936 }
937
938 #[cfg(feature = "kv")]
940 #[inline]
941 pub fn to_builder(&self) -> RecordBuilder {
942 RecordBuilder {
943 record: Record {
944 metadata: Metadata {
945 level: self.metadata.level,
946 target: self.metadata.target,
947 },
948 args: self.args,
949 module_path: self.module_path,
950 file: self.file,
951 line: self.line,
952 key_values: self.key_values.clone(),
953 },
954 }
955 }
956}
957
958)]
998pub struct RecordBuilder<'a> {
999 record: Record<'a>,
1000}
1001
1002impl<'a> RecordBuilder<'a> {
1003 #[inline]
1016 pub fn new() -> RecordBuilder<'a> {
1017 RecordBuilder {
1018 record: Record {
1019 args: format_args!("")format_args!(""),
1020 metadata: Metadata::builder().build(),
1021 module_path: None,
1022 file: None,
1023 line: None,
1024 #[cfg(feature = "kv")]
1025 key_values: KeyValues(&None::<(kv::Key, kv::Value)>),
1026 },
1027 }
1028 }
1029
1030 #[inline]
1032 pub fn args(&mut self, args: fmt::Arguments<'a>) -> &mut RecordBuilder<'a> {
1033 self.record.args = args;
1034 self
1035 }
1036
1037 #[inline]
1039 pub fn metadata(&mut self, metadata: Metadata<'a>) -> &mut RecordBuilder<'a> {
1040 self.record.metadata = metadata;
1041 self
1042 }
1043
1044 #[inline]
1046 pub fn level(&mut self, level: Level) -> &mut RecordBuilder<'a> {
1047 self.record.metadata.level = level;
1048 self
1049 }
1050
1051 #[inline]
1053 pub fn target(&mut self, target: &'a str) -> &mut RecordBuilder<'a> {
1054 self.record.metadata.target = target;
1055 self
1056 }
1057
1058 #[inline]
1060 pub fn module_path(&mut self, path: Option<&'a str>) -> &mut RecordBuilder<'a> {
1061 self.record.module_path = path.map(MaybeStaticStr::Borrowed);
1062 self
1063 }
1064
1065 #[inline]
1067 pub fn module_path_static(&mut self, path: Option<&'static str>) -> &mut RecordBuilder<'a> {
1068 self.record.module_path = path.map(MaybeStaticStr::Static);
1069 self
1070 }
1071
1072 #[inline]
1074 pub fn file(&mut self, file: Option<&'a str>) -> &mut RecordBuilder<'a> {
1075 self.record.file = file.map(MaybeStaticStr::Borrowed);
1076 self
1077 }
1078
1079 #[inline]
1081 pub fn file_static(&mut self, file: Option<&'static str>) -> &mut RecordBuilder<'a> {
1082 self.record.file = file.map(MaybeStaticStr::Static);
1083 self
1084 }
1085
1086 #[inline]
1088 pub fn line(&mut self, line: Option<u32>) -> &mut RecordBuilder<'a> {
1089 self.record.line = line;
1090 self
1091 }
1092
1093 #[cfg(feature = "kv")]
1095 #[inline]
1096 pub fn key_values(&mut self, kvs: &'a dyn kv::Source) -> &mut RecordBuilder<'a> {
1097 self.record.key_values = KeyValues(kvs);
1098 self
1099 }
1100
1101 #[inline]
1103 pub fn build(&self) -> Record<'a> {
1104 self.record.clone()
1105 }
1106}
1107
1108impl Default for RecordBuilder<'_> {
1109 fn default() -> Self {
1110 Self::new()
1111 }
1112}
1113
1114)]
1153pub struct Metadata<'a> {
1154 level: Level,
1155 target: &'a str,
1156}
1157
1158impl<'a> Metadata<'a> {
1159 #[inline]
1161 pub fn builder() -> MetadataBuilder<'a> {
1162 MetadataBuilder::new()
1163 }
1164
1165 #[inline]
1167 pub fn level(&self) -> Level {
1168 self.level
1169 }
1170
1171 #[inline]
1173 pub fn target(&self) -> &'a str {
1174 self.target
1175 }
1176}
1177
1178)]
1195pub struct MetadataBuilder<'a> {
1196 metadata: Metadata<'a>,
1197}
1198
1199impl<'a> MetadataBuilder<'a> {
1200 #[inline]
1207 pub fn new() -> MetadataBuilder<'a> {
1208 MetadataBuilder {
1209 metadata: Metadata {
1210 level: Level::Info,
1211 target: "",
1212 },
1213 }
1214 }
1215
1216 #[inline]
1218 pub fn level(&mut self, arg: Level) -> &mut MetadataBuilder<'a> {
1219 self.metadata.level = arg;
1220 self
1221 }
1222
1223 #[inline]
1225 pub fn target(&mut self, target: &'a str) -> &mut MetadataBuilder<'a> {
1226 self.metadata.target = target;
1227 self
1228 }
1229
1230 #[inline]
1232 pub fn build(&self) -> Metadata<'a> {
1233 self.metadata.clone()
1234 }
1235}
1236
1237impl Default for MetadataBuilder<'_> {
1238 fn default() -> Self {
1239 Self::new()
1240 }
1241}
1242
1243pub trait Log: Sync + Send {
1245 fn enabled(&self, metadata: &Metadata) -> bool;
1258
1259 fn log(&self, record: &Record);
1267
1268 fn flush(&self);
1275}
1276
1277struct NopLogger;
1279
1280impl Log for NopLogger {
1281 fn enabled(&self, _: &Metadata) -> bool {
1282 false
1283 }
1284
1285 fn log(&self, _: &Record) {}
1286 fn flush(&self) {}
1287}
1288
1289impl<T> Log for &'_ T
1290where
1291 T: ?Sized + Log,
1292{
1293 fn enabled(&self, metadata: &Metadata) -> bool {
1294 (**self).enabled(metadata)
1295 }
1296
1297 fn log(&self, record: &Record) {
1298 (**self).log(record);
1299 }
1300 fn flush(&self) {
1301 (**self).flush();
1302 }
1303}
1304
1305#[cfg(feature = "std")]
1306impl<T> Log for std::boxed::Box<T>
1307where
1308 T: ?Sized + Log,
1309{
1310 fn enabled(&self, metadata: &Metadata) -> bool {
1311 self.as_ref().enabled(metadata)
1312 }
1313
1314 fn log(&self, record: &Record) {
1315 self.as_ref().log(record);
1316 }
1317 fn flush(&self) {
1318 self.as_ref().flush();
1319 }
1320}
1321
1322#[cfg(feature = "std")]
1323impl<T> Log for std::sync::Arc<T>
1324where
1325 T: ?Sized + Log,
1326{
1327 fn enabled(&self, metadata: &Metadata) -> bool {
1328 self.as_ref().enabled(metadata)
1329 }
1330
1331 fn log(&self, record: &Record) {
1332 self.as_ref().log(record);
1333 }
1334 fn flush(&self) {
1335 self.as_ref().flush();
1336 }
1337}
1338
1339#[inline]
1345#[cfg(target_has_atomic = "ptr")]
1346pub fn set_max_level(level: LevelFilter) {
1347 MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed);
1348}
1349
1350#[inline]
1370pub unsafe fn set_max_level_racy(level: LevelFilter) {
1371 MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed);
1375}
1376
1377#[inline(always)]
1391pub fn max_level() -> LevelFilter {
1392 unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) }
1399}
1400
1401#[cfg(all(feature = "std", target_has_atomic = "ptr"))]
1415pub fn set_boxed_logger(logger: Box<dyn Log>) -> Result<(), SetLoggerError> {
1416 set_logger_inner(|| Box::leak(logger))
1417}
1418
1419#[cfg(target_has_atomic = "ptr")]
1473pub fn set_logger(logger: &'static dyn Log) -> Result<(), SetLoggerError> {
1474 set_logger_inner(|| logger)
1475}
1476
1477#[cfg(target_has_atomic = "ptr")]
1478fn set_logger_inner<F>(make_logger: F) -> Result<(), SetLoggerError>
1479where
1480 F: FnOnce() -> &'static dyn Log,
1481{
1482 match STATE.compare_exchange(
1483 UNINITIALIZED,
1484 INITIALIZING,
1485 Ordering::Acquire,
1486 Ordering::Relaxed,
1487 ) {
1488 Ok(UNINITIALIZED) => {
1489 unsafe {
1490 LOGGER = make_logger();
1491 }
1492 STATE.store(INITIALIZED, Ordering::Release);
1493 Ok(())
1494 }
1495 Err(INITIALIZING) => {
1496 while STATE.load(Ordering::Relaxed) == INITIALIZING {
1497 std::hint::spin_loop();
1498 }
1499 Err(SetLoggerError(()))
1500 }
1501 _ => Err(SetLoggerError(())),
1502 }
1503}
1504
1505pub unsafe fn set_logger_racy(logger: &'static dyn Log) -> Result<(), SetLoggerError> {
1525 match STATE.load(Ordering::Acquire) {
1526 UNINITIALIZED => {
1527 LOGGER = logger;
1528 STATE.store(INITIALIZED, Ordering::Release);
1529 Ok(())
1530 }
1531 INITIALIZING => {
1532 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("set_logger_racy must not be used with other initialization functions")));
}unreachable!("set_logger_racy must not be used with other initialization functions")
1534 }
1535 _ => Err(SetLoggerError(())),
1536 }
1537}
1538
1539#[allow(missing_copy_implementations)]
1543#[derive(#[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::fmt::Debug for SetLoggerError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "SetLoggerError",
&&self.0)
}
}Debug)]
1544pub struct SetLoggerError(());
1545
1546impl fmt::Display for SetLoggerError {
1547 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1548 fmt.write_str(SET_LOGGER_ERROR)
1549 }
1550}
1551
1552#[cfg(feature = "std")]
1554impl error::Error for SetLoggerError {}
1555
1556#[allow(missing_copy_implementations)]
1560#[derive(#[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::fmt::Debug for ParseLevelError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"ParseLevelError", &&self.0)
}
}Debug, #[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::cmp::PartialEq for ParseLevelError {
#[inline]
fn eq(&self, other: &ParseLevelError) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::cmp::Eq for ParseLevelError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<()>;
}
}Eq)]
1561pub struct ParseLevelError(());
1562
1563impl fmt::Display for ParseLevelError {
1564 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1565 fmt.write_str(LEVEL_PARSE_ERROR)
1566 }
1567}
1568
1569#[cfg(feature = "std")]
1571impl error::Error for ParseLevelError {}
1572
1573pub fn logger() -> &'static dyn Log {
1577 if STATE.load(Ordering::Acquire) != INITIALIZED {
1586 static NOP: NopLogger = NopLogger;
1587 &NOP
1588 } else {
1589 unsafe { LOGGER }
1590 }
1591}
1592
1593#[doc(hidden)]
1595pub mod __private_api;
1596
1597 {
1607 false if falsecfg!(feature = "release_max_level_off") => LevelFilter::Off,
1608 false if falsecfg!(feature = "release_max_level_error") => LevelFilter::Error,
1609 false if falsecfg!(feature = "release_max_level_warn") => LevelFilter::Warn,
1610 false if falsecfg!(feature = "release_max_level_info") => LevelFilter::Info,
1611 false if falsecfg!(feature = "release_max_level_debug") => LevelFilter::Debug,
1612 false if falsecfg!(feature = "release_max_level_trace") => LevelFilter::Trace,
1613 _ if falsecfg!(feature = "max_level_off") => LevelFilter::Off,
1614 _ if falsecfg!(feature = "max_level_error") => LevelFilter::Error,
1615 _ if falsecfg!(feature = "max_level_warn") => LevelFilter::Warn,
1616 _ if falsecfg!(feature = "max_level_info") => LevelFilter::Info,
1617 _ if falsecfg!(feature = "max_level_debug") => LevelFilter::Debug,
1618 _ => LevelFilter::Trace,
1619};
1620
1621#[cfg(test)]
1622mod tests {
1623 use super::{Level, LevelFilter, ParseLevelError, STATIC_MAX_LEVEL};
1624
1625 #[test]
1626 fn test_levelfilter_from_str() {
1627 let tests = [
1628 ("off", Ok(LevelFilter::Off)),
1629 ("error", Ok(LevelFilter::Error)),
1630 ("warn", Ok(LevelFilter::Warn)),
1631 ("info", Ok(LevelFilter::Info)),
1632 ("debug", Ok(LevelFilter::Debug)),
1633 ("trace", Ok(LevelFilter::Trace)),
1634 ("OFF", Ok(LevelFilter::Off)),
1635 ("ERROR", Ok(LevelFilter::Error)),
1636 ("WARN", Ok(LevelFilter::Warn)),
1637 ("INFO", Ok(LevelFilter::Info)),
1638 ("DEBUG", Ok(LevelFilter::Debug)),
1639 ("TRACE", Ok(LevelFilter::Trace)),
1640 ("asdf", Err(ParseLevelError(()))),
1641 ];
1642 for &(s, ref expected) in &tests {
1643 assert_eq!(expected, &s.parse());
1644 }
1645 }
1646
1647 #[test]
1648 fn test_level_from_str() {
1649 let tests = [
1650 ("OFF", Err(ParseLevelError(()))),
1651 ("error", Ok(Level::Error)),
1652 ("warn", Ok(Level::Warn)),
1653 ("info", Ok(Level::Info)),
1654 ("debug", Ok(Level::Debug)),
1655 ("trace", Ok(Level::Trace)),
1656 ("ERROR", Ok(Level::Error)),
1657 ("WARN", Ok(Level::Warn)),
1658 ("INFO", Ok(Level::Info)),
1659 ("DEBUG", Ok(Level::Debug)),
1660 ("TRACE", Ok(Level::Trace)),
1661 ("asdf", Err(ParseLevelError(()))),
1662 ];
1663 for &(s, ref expected) in &tests {
1664 assert_eq!(expected, &s.parse());
1665 }
1666 }
1667
1668 #[test]
1669 fn test_level_as_str() {
1670 let tests = &[
1671 (Level::Error, "ERROR"),
1672 (Level::Warn, "WARN"),
1673 (Level::Info, "INFO"),
1674 (Level::Debug, "DEBUG"),
1675 (Level::Trace, "TRACE"),
1676 ];
1677 for (input, expected) in tests {
1678 assert_eq!(*expected, input.as_str());
1679 }
1680 }
1681
1682 #[test]
1683 fn test_level_show() {
1684 assert_eq!("INFO", Level::Info.to_string());
1685 assert_eq!("ERROR", Level::Error.to_string());
1686 }
1687
1688 #[test]
1689 fn test_levelfilter_show() {
1690 assert_eq!("OFF", LevelFilter::Off.to_string());
1691 assert_eq!("ERROR", LevelFilter::Error.to_string());
1692 }
1693
1694 #[test]
1695 fn test_cross_cmp() {
1696 assert!(Level::Debug > LevelFilter::Error);
1697 assert!(LevelFilter::Warn < Level::Trace);
1698 assert!(LevelFilter::Off < Level::Error);
1699 }
1700
1701 #[test]
1702 fn test_cross_eq() {
1703 assert!(Level::Error == LevelFilter::Error);
1704 assert!(LevelFilter::Off != Level::Error);
1705 assert!(Level::Trace == LevelFilter::Trace);
1706 }
1707
1708 #[test]
1709 fn test_to_level() {
1710 assert_eq!(Some(Level::Error), LevelFilter::Error.to_level());
1711 assert_eq!(None, LevelFilter::Off.to_level());
1712 assert_eq!(Some(Level::Debug), LevelFilter::Debug.to_level());
1713 }
1714
1715 #[test]
1716 fn test_to_level_filter() {
1717 assert_eq!(LevelFilter::Error, Level::Error.to_level_filter());
1718 assert_eq!(LevelFilter::Trace, Level::Trace.to_level_filter());
1719 }
1720
1721 #[test]
1722 fn test_level_filter_as_str() {
1723 let tests = &[
1724 (LevelFilter::Off, "OFF"),
1725 (LevelFilter::Error, "ERROR"),
1726 (LevelFilter::Warn, "WARN"),
1727 (LevelFilter::Info, "INFO"),
1728 (LevelFilter::Debug, "DEBUG"),
1729 (LevelFilter::Trace, "TRACE"),
1730 ];
1731 for (input, expected) in tests {
1732 assert_eq!(*expected, input.as_str());
1733 }
1734 }
1735
1736 #[test]
1737 fn test_level_up() {
1738 let info = Level::Info;
1739 let up = info.increment_severity();
1740 assert_eq!(up, Level::Debug);
1741
1742 let trace = Level::Trace;
1743 let up = trace.increment_severity();
1744 assert_eq!(up, trace);
1746 }
1747
1748 #[test]
1749 fn test_level_filter_up() {
1750 let info = LevelFilter::Info;
1751 let up = info.increment_severity();
1752 assert_eq!(up, LevelFilter::Debug);
1753
1754 let trace = LevelFilter::Trace;
1755 let up = trace.increment_severity();
1756 assert_eq!(up, trace);
1758 }
1759
1760 #[test]
1761 fn test_level_down() {
1762 let info = Level::Info;
1763 let down = info.decrement_severity();
1764 assert_eq!(down, Level::Warn);
1765
1766 let error = Level::Error;
1767 let down = error.decrement_severity();
1768 assert_eq!(down, error);
1770 }
1771
1772 #[test]
1773 fn test_level_filter_down() {
1774 let info = LevelFilter::Info;
1775 let down = info.decrement_severity();
1776 assert_eq!(down, LevelFilter::Warn);
1777
1778 let error = LevelFilter::Error;
1779 let down = error.decrement_severity();
1780 assert_eq!(down, LevelFilter::Off);
1781 assert_eq!(down.decrement_severity(), down);
1783 }
1784
1785 #[test]
1786 #[cfg_attr(not(debug_assertions), ignore)]
1787 fn test_static_max_level_debug() {
1788 if cfg!(feature = "max_level_off") {
1789 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Off);
1790 } else if cfg!(feature = "max_level_error") {
1791 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Error);
1792 } else if cfg!(feature = "max_level_warn") {
1793 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Warn);
1794 } else if cfg!(feature = "max_level_info") {
1795 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Info);
1796 } else if cfg!(feature = "max_level_debug") {
1797 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Debug);
1798 } else {
1799 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Trace);
1800 }
1801 }
1802
1803 #[test]
1804 #[cfg_attr(debug_assertions, ignore)]
1805 fn test_static_max_level_release() {
1806 if cfg!(feature = "release_max_level_off") {
1807 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Off);
1808 } else if cfg!(feature = "release_max_level_error") {
1809 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Error);
1810 } else if cfg!(feature = "release_max_level_warn") {
1811 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Warn);
1812 } else if cfg!(feature = "release_max_level_info") {
1813 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Info);
1814 } else if cfg!(feature = "release_max_level_debug") {
1815 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Debug);
1816 } else if cfg!(feature = "release_max_level_trace") {
1817 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Trace);
1818 } else if cfg!(feature = "max_level_off") {
1819 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Off);
1820 } else if cfg!(feature = "max_level_error") {
1821 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Error);
1822 } else if cfg!(feature = "max_level_warn") {
1823 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Warn);
1824 } else if cfg!(feature = "max_level_info") {
1825 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Info);
1826 } else if cfg!(feature = "max_level_debug") {
1827 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Debug);
1828 } else {
1829 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Trace);
1830 }
1831 }
1832
1833 #[test]
1834 #[cfg(feature = "std")]
1835 fn test_error_trait() {
1836 use super::SetLoggerError;
1837 let e = SetLoggerError(());
1838 assert_eq!(
1839 &e.to_string(),
1840 "attempted to set a logger after the logging system \
1841 was already initialized"
1842 );
1843 }
1844
1845 #[test]
1846 fn test_metadata_builder() {
1847 use super::MetadataBuilder;
1848 let target = "myApp";
1849 let metadata_test = MetadataBuilder::new()
1850 .level(Level::Debug)
1851 .target(target)
1852 .build();
1853 assert_eq!(metadata_test.level(), Level::Debug);
1854 assert_eq!(metadata_test.target(), "myApp");
1855 }
1856
1857 #[test]
1858 fn test_metadata_convenience_builder() {
1859 use super::Metadata;
1860 let target = "myApp";
1861 let metadata_test = Metadata::builder()
1862 .level(Level::Debug)
1863 .target(target)
1864 .build();
1865 assert_eq!(metadata_test.level(), Level::Debug);
1866 assert_eq!(metadata_test.target(), "myApp");
1867 }
1868
1869 #[test]
1870 fn test_record_builder() {
1871 use super::{MetadataBuilder, RecordBuilder};
1872 let target = "myApp";
1873 let metadata = MetadataBuilder::new().target(target).build();
1874 let fmt_args = format_args!("hello");
1875 let record_test = RecordBuilder::new()
1876 .args(fmt_args)
1877 .metadata(metadata)
1878 .module_path(Some("foo"))
1879 .file(Some("bar"))
1880 .line(Some(30))
1881 .build();
1882 assert_eq!(record_test.metadata().target(), "myApp");
1883 assert_eq!(record_test.module_path(), Some("foo"));
1884 assert_eq!(record_test.file(), Some("bar"));
1885 assert_eq!(record_test.line(), Some(30));
1886 }
1887
1888 #[test]
1889 fn test_record_convenience_builder() {
1890 use super::{Metadata, Record};
1891 let target = "myApp";
1892 let metadata = Metadata::builder().target(target).build();
1893 let fmt_args = format_args!("hello");
1894 let record_test = Record::builder()
1895 .args(fmt_args)
1896 .metadata(metadata)
1897 .module_path(Some("foo"))
1898 .file(Some("bar"))
1899 .line(Some(30))
1900 .build();
1901 assert_eq!(record_test.target(), "myApp");
1902 assert_eq!(record_test.module_path(), Some("foo"));
1903 assert_eq!(record_test.file(), Some("bar"));
1904 assert_eq!(record_test.line(), Some(30));
1905 }
1906
1907 #[test]
1908 fn test_record_complete_builder() {
1909 use super::{Level, Record};
1910 let target = "myApp";
1911 let record_test = Record::builder()
1912 .module_path(Some("foo"))
1913 .file(Some("bar"))
1914 .line(Some(30))
1915 .target(target)
1916 .level(Level::Error)
1917 .build();
1918 assert_eq!(record_test.target(), "myApp");
1919 assert_eq!(record_test.level(), Level::Error);
1920 assert_eq!(record_test.module_path(), Some("foo"));
1921 assert_eq!(record_test.file(), Some("bar"));
1922 assert_eq!(record_test.line(), Some(30));
1923 }
1924
1925 #[test]
1926 #[cfg(feature = "kv")]
1927 fn test_record_key_values_builder() {
1928 use super::Record;
1929 use crate::kv::{self, VisitSource};
1930
1931 struct TestVisitSource {
1932 seen_pairs: usize,
1933 }
1934
1935 impl<'kvs> VisitSource<'kvs> for TestVisitSource {
1936 fn visit_pair(
1937 &mut self,
1938 _: kv::Key<'kvs>,
1939 _: kv::Value<'kvs>,
1940 ) -> Result<(), kv::Error> {
1941 self.seen_pairs += 1;
1942 Ok(())
1943 }
1944 }
1945
1946 let kvs: &[(&str, i32)] = &[("a", 1), ("b", 2)];
1947 let record_test = Record::builder().key_values(&kvs).build();
1948
1949 let mut visitor = TestVisitSource { seen_pairs: 0 };
1950
1951 record_test.key_values().visit(&mut visitor).unwrap();
1952
1953 assert_eq!(2, visitor.seen_pairs);
1954 }
1955
1956 #[test]
1957 #[cfg(feature = "kv")]
1958 fn test_record_key_values_get_coerce() {
1959 use super::Record;
1960
1961 let kvs: &[(&str, &str)] = &[("a", "1"), ("b", "2")];
1962 let record = Record::builder().key_values(&kvs).build();
1963
1964 assert_eq!(
1965 "2",
1966 record
1967 .key_values()
1968 .get("b".into())
1969 .expect("missing key")
1970 .to_borrowed_str()
1971 .expect("invalid value")
1972 );
1973 }
1974
1975 #[test]
1978 fn test_foreign_impl() {
1979 use super::Log;
1980 #[cfg(feature = "std")]
1981 use std::sync::Arc;
1982
1983 fn assert_is_log<T: Log + ?Sized>() {}
1984
1985 assert_is_log::<&dyn Log>();
1986
1987 #[cfg(feature = "std")]
1988 assert_is_log::<Box<dyn Log>>();
1989
1990 #[cfg(feature = "std")]
1991 assert_is_log::<Arc<dyn Log>>();
1992
1993 #[allow(unused)]
1995 fn forall<T: Log + ?Sized>() {
1996 #[cfg(feature = "std")]
1997 assert_is_log::<Box<T>>();
1998
1999 assert_is_log::<&T>();
2000
2001 #[cfg(feature = "std")]
2002 assert_is_log::<Arc<T>>();
2003 }
2004 }
2005}