1use std::{fmt::Debug, result::Result as StdResult, time::Duration};
2
3use crate::{
4 env_level,
5 error::{Error, ErrorHandler, InvalidArgumentError, SetLoggerNameError},
6 periodic_worker::PeriodicWorker,
7 sink::{Sink, Sinks},
8 sync::*,
9 Level, LevelFilter, Record, Result,
10};
11
12fn check_logger_name(name: impl AsRef<str>) -> StdResult<(), SetLoggerNameError> {
13 let name = name.as_ref();
14
15 if name.chars().any(|ch| {
16 ch == ','
17 || ch == '='
18 || ch == '*'
19 || ch == '?'
20 || ch == '$'
21 || ch == '{'
22 || ch == '}'
23 || ch == '"'
24 || ch == '\''
25 || ch == ';'
26 }) || name.starts_with(' ')
27 || name.ends_with(' ')
28 {
29 Err(SetLoggerNameError::new(name))
30 } else {
31 Ok(())
32 }
33}
34
35pub struct Logger {
110 name: Option<String>,
111 level_filter: Atomic<LevelFilter>,
112 sinks: Sinks,
113 flush_level_filter: Atomic<LevelFilter>,
114 error_handler: SpinRwLock<Option<ErrorHandler>>,
115 periodic_flusher: Mutex<Option<(Duration, PeriodicWorker)>>,
116}
117
118impl Debug for Logger {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 f.debug_struct("Logger")
121 .field("name", &self.name)
122 .field("level_filter", &self.level_filter())
123 .field(
124 "sinks",
125 &self
126 .sinks
127 .iter()
128 .map(|sink| sink.level_filter())
129 .collect::<Vec<_>>(),
130 )
131 .field("flush_level_filter", &self.flush_level_filter())
132 .field("error_handler", &self.error_handler.read())
133 .field(
134 "periodic_flusher",
135 &self
136 .periodic_flusher
137 .lock()
138 .as_deref()
139 .map(|opt| opt.as_ref().map(|(dur, _)| *dur))
140 .as_ref()
141 .map(|dur| dur as &dyn Debug)
142 .unwrap_or(&"*lock is poisoned*"),
143 )
144 .finish()
145 }
146}
147
148impl Logger {
149 #[must_use]
168 pub fn builder() -> LoggerBuilder {
169 LoggerBuilder {
170 name: None,
171 level_filter: LevelFilter::MoreSevereEqual(Level::Info),
172 sinks: vec![],
173 flush_level_filter: LevelFilter::Off,
174 error_handler: None,
175 }
176 }
177
178 #[must_use]
182 pub fn name(&self) -> Option<&str> {
183 self.name.as_ref().map(|s| s.as_ref())
184 }
185
186 pub fn set_name<S>(&mut self, name: Option<S>) -> StdResult<(), SetLoggerNameError>
188 where
189 S: Into<String>,
190 {
191 if let Some(name) = name {
192 let name = name.into();
193 check_logger_name(&name)?;
194 self.name = Some(name);
195 } else {
196 self.name = None;
197 }
198 Ok(())
199 }
200
201 #[must_use]
226 pub fn should_log(&self, level: Level) -> bool {
227 self.level_filter().test(level)
228 }
229
230 pub fn log(&self, record: &Record) {
239 if !self.should_log(record.level()) {
240 return;
241 }
242 self.sink_record(record);
243 }
244
245 pub fn flush(&self) {
256 self.flush_sinks();
257 }
258
259 #[must_use]
261 pub fn flush_level_filter(&self) -> LevelFilter {
262 self.flush_level_filter.load(Ordering::Relaxed)
263 }
264
265 pub fn set_flush_level_filter(&self, level_filter: LevelFilter) {
290 self.flush_level_filter
291 .store(level_filter, Ordering::Relaxed);
292 }
293
294 #[must_use]
296 pub fn level_filter(&self) -> LevelFilter {
297 self.level_filter.load(Ordering::Relaxed)
298 }
299
300 pub fn set_level_filter(&self, level_filter: LevelFilter) {
306 self.level_filter.store(level_filter, Ordering::Relaxed);
307 }
308
309 pub fn set_flush_period(self: &Arc<Self>, interval: Option<Duration>) {
339 let mut periodic_flusher = self.periodic_flusher.lock_expect();
340
341 *periodic_flusher = None;
342
343 if let Some(interval) = interval {
344 let weak = Arc::downgrade(self);
345 let callback = move || {
346 let strong = weak.upgrade();
347 if let Some(strong) = strong {
348 strong.flush_sinks();
349 true
350 } else {
351 false }
354 };
355 *periodic_flusher = Some((interval, PeriodicWorker::new(callback, interval)));
356 }
357 }
358
359 #[must_use]
361 pub fn sinks(&self) -> &[Arc<dyn Sink>] {
362 &self.sinks
363 }
364
365 #[must_use]
367 pub fn sinks_mut(&mut self) -> &mut Sinks {
368 &mut self.sinks
369 }
370
371 pub fn set_error_handler(&self, handler: Option<ErrorHandler>) {
387 *self.error_handler.write() = handler;
388 }
389
390 #[doc = include_str!(concat!(env!("OUT_DIR"), "/test_utils/common_for_doc_test.rs"))]
402 pub fn fork_with<F>(self: &Arc<Self>, modifier: F) -> Result<Arc<Self>>
424 where
425 F: FnOnce(&mut Logger) -> Result<()>,
426 {
427 let flush_period = self.periodic_flusher.lock_expect().as_ref().map(|v| v.0);
428
429 let mut new_logger = self.clone_lossy();
430 modifier(&mut new_logger)?;
431
432 let new_logger = Arc::new(new_logger);
433 if let Some(interval) = flush_period {
434 new_logger.set_flush_period(Some(interval));
435 }
436
437 Ok(new_logger)
438 }
439
440 pub fn fork_with_name<S>(self: &Arc<Self>, new_name: Option<S>) -> Result<Arc<Self>>
464 where
465 S: Into<String>,
466 {
467 self.fork_with(|new| {
468 new.set_name(new_name).map_err(InvalidArgumentError::from)?;
469 Ok(())
470 })
471 }
472
473 #[must_use]
475 fn clone_lossy(&self) -> Self {
476 Logger {
477 name: self.name.clone(),
478 level_filter: Atomic::new(self.level_filter()),
479 sinks: self.sinks.clone(),
480 flush_level_filter: Atomic::new(self.flush_level_filter()),
481 periodic_flusher: Mutex::new(None),
482 error_handler: SpinRwLock::new(*self.error_handler.read()),
483 }
484 }
485
486 fn sink_record(&self, record: &Record) {
487 self.sinks.iter().for_each(|sink| {
488 if sink.should_log(record.level()) {
489 if let Err(err) = sink.log(record) {
490 self.handle_error(err);
491 }
492 }
493 });
494
495 if self.should_flush(record) {
496 self.flush();
497 }
498 }
499
500 fn flush_sinks(&self) {
501 self.sinks.iter().for_each(|sink| {
502 if let Err(err) = sink.flush() {
503 self.handle_error(err);
504 }
505 });
506 }
507
508 fn handle_error(&self, err: Error) {
509 if let Some(handler) = self.error_handler.read().as_ref() {
510 handler(err)
511 } else {
512 crate::default_error_handler(
513 format!(
514 "Logger ({})",
515 self.name.as_ref().map_or("*no name*", String::as_str)
516 ),
517 err,
518 );
519 }
520 }
521
522 #[must_use]
523 fn should_flush(&self, record: &Record) -> bool {
524 self.flush_level_filter().test(record.level())
525 }
526}
527
528impl Clone for Logger {
529 fn clone(&self) -> Self {
536 if self.periodic_flusher.lock_expect().is_some() {
537 panic!(
538 "you can't clone a `Logger` with a `flush_period` value, \
539 clone a `Arc<Logger>` instead."
540 );
541 }
542 self.clone_lossy()
543 }
544}
545
546#[allow(missing_docs)]
547#[derive(Clone)]
548pub struct LoggerBuilder {
549 name: Option<String>,
550 level_filter: LevelFilter,
551 sinks: Sinks,
552 flush_level_filter: LevelFilter,
553 error_handler: Option<ErrorHandler>,
554}
555
556impl LoggerBuilder {
557 #[allow(clippy::new_without_default)]
559 #[deprecated(
560 since = "0.3.0",
561 note = "it may be removed in the future, use `Logger::builder()` instead"
562 )]
563 #[must_use]
564 pub fn new() -> Self {
565 Logger::builder()
566 }
567
568 pub fn name<S>(&mut self, name: S) -> &mut Self
580 where
581 S: Into<String>,
582 {
583 self.name = Some(name.into());
584 self
585 }
586
587 pub fn level_filter(&mut self, level_filter: LevelFilter) -> &mut Self {
591 self.level_filter = level_filter;
592 self
593 }
594
595 pub fn sink(&mut self, sink: Arc<dyn Sink>) -> &mut Self {
597 self.sinks.push(sink);
598 self
599 }
600
601 pub fn sinks<I>(&mut self, sinks: I) -> &mut Self
603 where
604 I: IntoIterator<Item = Arc<dyn Sink>>,
605 {
606 self.sinks.append(&mut sinks.into_iter().collect());
607 self
608 }
609
610 pub fn flush_level_filter(&mut self, level_filter: LevelFilter) -> &mut Self {
617 self.flush_level_filter = level_filter;
618 self
619 }
620
621 pub fn error_handler(&mut self, handler: ErrorHandler) -> &mut Self {
628 self.error_handler = Some(handler);
629 self
630 }
631
632 pub fn build(&mut self) -> Result<Logger> {
634 self.build_inner(self.preset_level(false))
635 }
636
637 pub(crate) fn build_default(&mut self) -> Result<Logger> {
638 self.build_inner(self.preset_level(true))
639 }
640
641 #[must_use]
642 fn preset_level(&self, is_default: bool) -> Option<LevelFilter> {
643 if is_default {
644 env_level::logger_level(env_level::LoggerKind::Default)
645 } else {
646 env_level::logger_level(env_level::LoggerKind::Other(self.name.as_deref()))
647 }
648 }
649
650 fn build_inner(&mut self, preset_level: Option<LevelFilter>) -> Result<Logger> {
651 if let Some(name) = &self.name {
652 check_logger_name(name).map_err(InvalidArgumentError::from)?;
653 }
654
655 let logger = Logger {
656 name: self.name.clone(),
657 level_filter: Atomic::new(self.level_filter),
658 sinks: self.sinks.clone(),
659 flush_level_filter: Atomic::new(self.flush_level_filter),
660 error_handler: SpinRwLock::new(self.error_handler),
661 periodic_flusher: Mutex::new(None),
662 };
663
664 if let Some(preset_level) = preset_level {
665 logger.set_level_filter(preset_level);
666 }
667
668 Ok(logger)
669 }
670
671 #[cfg(test)]
672 #[must_use]
673 fn build_inner_for_test(&mut self, env_level: &str, is_default: bool) -> Logger {
674 let preset_level = if is_default {
675 env_level::logger_level_inner(
676 &env_level::from_str_inner(env_level).unwrap(),
677 env_level::LoggerKind::Default,
678 )
679 } else {
680 env_level::logger_level_inner(
681 &env_level::from_str_inner(env_level).unwrap(),
682 env_level::LoggerKind::Other(self.name.as_deref()),
683 )
684 };
685
686 self.build_inner(preset_level).unwrap()
687 }
688}
689
690#[cfg(test)]
691mod tests {
692 use std::{thread, time::Duration};
693
694 use super::*;
695 use crate::{prelude::*, test_utils::*};
696
697 #[test]
698 fn logger_traits() {
699 assert_trait!(Logger: Send + Sync + Debug);
700 }
701
702 #[test]
703 fn flush_level() {
704 let test_sink = Arc::new(TestSink::new());
705 let test_logger = Logger::builder().sink(test_sink.clone()).build().unwrap();
706
707 trace!(logger: test_logger, "");
708 error!(logger: test_logger, "");
709 assert_eq!(test_sink.flush_count(), 0);
710 test_sink.reset();
711
712 test_logger.set_flush_level_filter(LevelFilter::MoreSevereEqual(Level::Warn));
713 debug!(logger: test_logger, "");
714 warn!(logger: test_logger, "");
715 assert_eq!(test_sink.flush_count(), 1);
716 test_sink.reset();
717
718 test_logger.set_flush_level_filter(LevelFilter::Off);
719 info!(logger: test_logger, "");
720 trace!(logger: test_logger, "");
721 assert_eq!(test_sink.flush_count(), 0);
722 test_sink.reset();
723
724 test_logger.set_flush_level_filter(LevelFilter::MoreSevereEqual(Level::Trace));
725 info!(logger: test_logger, "");
726 warn!(logger: test_logger, "");
727 assert_eq!(test_sink.flush_count(), 2);
728 test_sink.reset();
729 }
730
731 #[test]
732 fn periodic_flush() {
733 let test_sink = Arc::new(TestSink::new());
734 let test_logger = Arc::new(Logger::builder().sink(test_sink.clone()).build().unwrap());
735
736 test_logger.set_flush_period(Some(Duration::from_secs(1)));
737
738 assert_eq!(test_sink.flush_count(), 0);
739
740 thread::sleep(Duration::from_millis(1250));
741 assert_eq!(test_sink.flush_count(), 1);
742
743 thread::sleep(Duration::from_millis(1250));
744 assert_eq!(test_sink.flush_count(), 2);
745
746 test_logger.set_flush_period(None);
747
748 thread::sleep(Duration::from_millis(1250));
749 assert_eq!(test_sink.flush_count(), 2);
750
751 test_logger.set_flush_period(Some(Duration::from_secs(1)));
752
753 thread::sleep(Duration::from_millis(1250));
754 assert_eq!(test_sink.flush_count(), 3);
755 }
756
757 #[test]
758 fn builder_name() {
759 Logger::builder().name("hello-world");
760
761 macro_rules! assert_name_err {
762 ( $($name:literal),+ $(,)? ) => {
763 $(match Logger::builder().name($name).build() {
764 Err(Error::InvalidArgument(InvalidArgumentError::LoggerName(err))) => {
765 assert_eq!(err.name(), $name)
766 }
767 _ => panic!("test case '{}' failed", $name),
768 })+
769 };
770 }
771
772 assert_name_err! {
773 " hello", "hello ",
774 "hello,world", "hello=world", "hello*world", "hello?world", "hello$world",
775 "hello{world", "hello}world", r#"hello"world"#, "hello'world", "hello;world",
776 };
777 }
778
779 #[test]
780 fn env_level() {
781 macro_rules! assert_levels {
782 ($env_level:literal, DEFAULT => $default:expr, UNNAMED => $unnamed:expr, NAMED($name:literal) => $named:expr $(,)?) => {
783 assert_eq!(
784 Logger::builder()
785 .build_inner_for_test($env_level, true)
786 .level_filter(),
787 $default
788 );
789 assert_eq!(
790 Logger::builder()
791 .build_inner_for_test($env_level, false)
792 .level_filter(),
793 $unnamed
794 );
795 assert_eq!(
796 Logger::builder()
797 .name($name)
798 .build_inner_for_test($env_level, false)
799 .level_filter(),
800 $named
801 );
802 };
803 (_, DEFAULT => $default:expr, UNNAMED => $unnamed:expr, NAMED($name:literal) => $named:expr $(,)?) => {
804 assert_eq!(
805 Logger::builder().build_default().unwrap().level_filter(),
806 $default
807 );
808 assert_eq!(Logger::builder().build().unwrap().level_filter(), $unnamed);
809 assert_eq!(
810 Logger::builder()
811 .name($name)
812 .build()
813 .unwrap()
814 .level_filter(),
815 $named
816 );
817 };
818 }
819
820 let unchanged = LevelFilter::MoreSevereEqual(Level::Info);
821
822 assert_levels!(
823 _,
824 DEFAULT => unchanged,
825 UNNAMED => unchanged,
826 NAMED("name") => unchanged,
827 );
828
829 assert_levels!(
830 "deBug",
831 DEFAULT => LevelFilter::MoreSevereEqual(Level::Debug),
832 UNNAMED => unchanged,
833 NAMED("name") => unchanged,
834 );
835
836 assert_levels!(
837 "deBug,*=tRace",
838 DEFAULT => LevelFilter::MoreSevereEqual(Level::Debug),
839 UNNAMED => LevelFilter::MoreSevereEqual(Level::Trace),
840 NAMED("name") => LevelFilter::MoreSevereEqual(Level::Trace),
841 );
842
843 assert_levels!(
844 "=trAce",
845 DEFAULT => unchanged,
846 UNNAMED => LevelFilter::MoreSevereEqual(Level::Trace),
847 NAMED("name") => unchanged,
848 );
849
850 assert_levels!(
851 "*=waRn",
852 DEFAULT => unchanged,
853 UNNAMED => LevelFilter::MoreSevereEqual(Level::Warn),
854 NAMED("name") => LevelFilter::MoreSevereEqual(Level::Warn),
855 );
856
857 assert_levels!(
858 "=eRror,*=waRn",
859 DEFAULT => unchanged,
860 UNNAMED => LevelFilter::MoreSevereEqual(Level::Error),
861 NAMED("name") => LevelFilter::MoreSevereEqual(Level::Warn),
862 );
863
864 assert_levels!(
865 "=eRror,*=waRn,name=trAce",
866 DEFAULT => unchanged,
867 UNNAMED => LevelFilter::MoreSevereEqual(Level::Error),
868 NAMED("name") => LevelFilter::MoreSevereEqual(Level::Trace),
869 );
870
871 assert_levels!(
872 "all,*=all",
873 DEFAULT => LevelFilter::All,
874 UNNAMED => LevelFilter::All,
875 NAMED("name") => LevelFilter::All,
876 );
877
878 assert_levels!(
879 "off,*=all",
880 DEFAULT => LevelFilter::Off,
881 UNNAMED => LevelFilter::All,
882 NAMED("name") => LevelFilter::All,
883 );
884 }
885
886 #[test]
887 fn fork_logger() {
888 let test_sink = (Arc::new(TestSink::new()), Arc::new(TestSink::new()));
889 let logger = Arc::new(build_test_logger(|b| b.sink(test_sink.0.clone())));
890
891 assert!(logger.name().is_none());
892 assert_eq!(test_sink.0.log_count(), 0);
893 assert_eq!(test_sink.0.flush_count(), 0);
894 assert_eq!(test_sink.1.log_count(), 0);
895 assert_eq!(test_sink.1.flush_count(), 0);
896
897 info!(logger: logger, "qwq");
898 assert!(logger.name().is_none());
899 assert_eq!(test_sink.0.log_count(), 1);
900 assert_eq!(test_sink.0.flush_count(), 0);
901 assert_eq!(test_sink.1.log_count(), 0);
902 assert_eq!(test_sink.1.flush_count(), 0);
903
904 let old = logger;
905 let new = old.fork_with_name(Some("cat")).unwrap();
906 info!(logger: new, "meow");
907 assert!(old.name().is_none());
908 assert_eq!(new.name(), Some("cat"));
909 assert_eq!(test_sink.0.log_count(), 2);
910 assert_eq!(test_sink.0.flush_count(), 0);
911 assert_eq!(test_sink.1.log_count(), 0);
912 assert_eq!(test_sink.1.flush_count(), 0);
913
914 let old = new;
915 let new = old
916 .fork_with(|new| {
917 new.set_name(Some("dog")).unwrap();
918 new.sinks_mut().push(test_sink.1.clone());
919 Ok(())
920 })
921 .unwrap();
922 info!(logger: new, "woof");
923 assert_eq!(old.name(), Some("cat"));
924 assert_eq!(new.name(), Some("dog"));
925 assert_eq!(test_sink.0.log_count(), 3);
926 assert_eq!(test_sink.0.flush_count(), 0);
927 assert_eq!(test_sink.1.log_count(), 1);
928 assert_eq!(test_sink.1.flush_count(), 0);
929
930 assert!(matches!(
931 new.fork_with_name(Some("invalid,name")),
932 Err(Error::InvalidArgument(InvalidArgumentError::LoggerName(_)))
933 ));
934
935 assert!(new
936 .fork_with_name(None as Option<&str>)
937 .unwrap()
938 .name()
939 .is_none());
940
941 let test_sink = (Arc::new(TestSink::new()), Arc::new(TestSink::new()));
942 let old = Arc::new(build_test_logger(|b| b.sink(test_sink.0.clone())));
943 old.set_flush_period(Some(Duration::from_secs(1)));
944 std::thread::sleep(Duration::from_millis(1250));
945
946 let _new = old
947 .fork_with(|new| {
948 new.sinks_mut().clear();
949 new.sinks_mut().push(test_sink.1.clone());
950 Ok(())
951 })
952 .unwrap();
953 std::thread::sleep(Duration::from_millis(1250));
954
955 assert_eq!(test_sink.0.log_count(), 0);
956 assert_eq!(test_sink.0.flush_count(), 2);
957 assert_eq!(test_sink.1.log_count(), 0);
958 assert_eq!(test_sink.1.flush_count(), 1);
959 }
960}