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: RwLock<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: ErrorHandler::default(),
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<F: Into<ErrorHandler>>(&self, handler: F) {
387 *self.error_handler.write_expect() = handler.into();
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: RwLock::new(self.error_handler.read_expect().clone()),
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 self.error_handler.read_expect().call_internal(
510 format!(
511 "Logger ({})",
512 self.name.as_ref().map_or("*no name*", String::as_str)
513 ),
514 err,
515 );
516 }
517
518 #[must_use]
519 fn should_flush(&self, record: &Record) -> bool {
520 self.flush_level_filter().test(record.level())
521 }
522}
523
524impl Clone for Logger {
525 fn clone(&self) -> Self {
532 if self.periodic_flusher.lock_expect().is_some() {
533 panic!(
534 "you can't clone a `Logger` with a `flush_period` value, \
535 clone a `Arc<Logger>` instead."
536 );
537 }
538 self.clone_lossy()
539 }
540}
541
542#[allow(missing_docs)]
543#[derive(Clone)]
544pub struct LoggerBuilder {
545 name: Option<String>,
546 level_filter: LevelFilter,
547 sinks: Sinks,
548 flush_level_filter: LevelFilter,
549 error_handler: ErrorHandler,
550}
551
552impl LoggerBuilder {
553 #[allow(clippy::new_without_default)]
555 #[deprecated(
556 since = "0.3.0",
557 note = "it may be removed in the future, use `Logger::builder()` instead"
558 )]
559 #[must_use]
560 pub fn new() -> Self {
561 Logger::builder()
562 }
563
564 pub fn name<S>(&mut self, name: S) -> &mut Self
576 where
577 S: Into<String>,
578 {
579 self.name = Some(name.into());
580 self
581 }
582
583 pub fn level_filter(&mut self, level_filter: LevelFilter) -> &mut Self {
587 self.level_filter = level_filter;
588 self
589 }
590
591 pub fn sink(&mut self, sink: Arc<dyn Sink>) -> &mut Self {
593 self.sinks.push(sink);
594 self
595 }
596
597 pub fn sinks<I>(&mut self, sinks: I) -> &mut Self
599 where
600 I: IntoIterator<Item = Arc<dyn Sink>>,
601 {
602 self.sinks.append(&mut sinks.into_iter().collect());
603 self
604 }
605
606 pub fn flush_level_filter(&mut self, level_filter: LevelFilter) -> &mut Self {
613 self.flush_level_filter = level_filter;
614 self
615 }
616
617 pub fn error_handler<F: Into<ErrorHandler>>(&mut self, handler: F) -> &mut Self {
624 self.error_handler = handler.into();
625 self
626 }
627
628 pub fn build(&mut self) -> Result<Logger> {
630 self.build_inner(self.preset_level(false))
631 }
632
633 pub(crate) fn build_default(&mut self) -> Result<Logger> {
634 self.build_inner(self.preset_level(true))
635 }
636
637 #[must_use]
638 fn preset_level(&self, is_default: bool) -> Option<LevelFilter> {
639 if is_default {
640 env_level::logger_level(env_level::LoggerKind::Default)
641 } else {
642 env_level::logger_level(env_level::LoggerKind::Other(self.name.as_deref()))
643 }
644 }
645
646 fn build_inner(&mut self, preset_level: Option<LevelFilter>) -> Result<Logger> {
647 if let Some(name) = &self.name {
648 check_logger_name(name).map_err(InvalidArgumentError::from)?;
649 }
650
651 let logger = Logger {
652 name: self.name.clone(),
653 level_filter: Atomic::new(self.level_filter),
654 sinks: self.sinks.clone(),
655 flush_level_filter: Atomic::new(self.flush_level_filter),
656 error_handler: RwLock::new(self.error_handler.clone()),
657 periodic_flusher: Mutex::new(None),
658 };
659
660 if let Some(preset_level) = preset_level {
661 logger.set_level_filter(preset_level);
662 }
663
664 Ok(logger)
665 }
666
667 #[cfg(test)]
668 #[must_use]
669 fn build_inner_for_test(&mut self, env_level: &str, is_default: bool) -> Logger {
670 let preset_level = if is_default {
671 env_level::logger_level_inner(
672 &env_level::from_str_inner(env_level).unwrap(),
673 env_level::LoggerKind::Default,
674 )
675 } else {
676 env_level::logger_level_inner(
677 &env_level::from_str_inner(env_level).unwrap(),
678 env_level::LoggerKind::Other(self.name.as_deref()),
679 )
680 };
681
682 self.build_inner(preset_level).unwrap()
683 }
684}
685
686#[cfg(test)]
687mod tests {
688 use std::{thread, time::Duration};
689
690 use super::*;
691 use crate::{prelude::*, test_utils::*};
692
693 #[test]
694 fn logger_traits() {
695 assert_trait!(Logger: Send + Sync + Debug);
696 }
697
698 #[test]
699 fn flush_level() {
700 let test_sink = Arc::new(TestSink::new());
701 let test_logger = Logger::builder().sink(test_sink.clone()).build().unwrap();
702
703 trace!(logger: test_logger, "");
704 error!(logger: test_logger, "");
705 assert_eq!(test_sink.flush_count(), 0);
706 test_sink.reset();
707
708 test_logger.set_flush_level_filter(LevelFilter::MoreSevereEqual(Level::Warn));
709 debug!(logger: test_logger, "");
710 warn!(logger: test_logger, "");
711 assert_eq!(test_sink.flush_count(), 1);
712 test_sink.reset();
713
714 test_logger.set_flush_level_filter(LevelFilter::Off);
715 info!(logger: test_logger, "");
716 trace!(logger: test_logger, "");
717 assert_eq!(test_sink.flush_count(), 0);
718 test_sink.reset();
719
720 test_logger.set_flush_level_filter(LevelFilter::MoreSevereEqual(Level::Trace));
721 info!(logger: test_logger, "");
722 warn!(logger: test_logger, "");
723 assert_eq!(test_sink.flush_count(), 2);
724 test_sink.reset();
725 }
726
727 #[test]
728 fn periodic_flush() {
729 let test_sink = Arc::new(TestSink::new());
730 let test_logger = Arc::new(Logger::builder().sink(test_sink.clone()).build().unwrap());
731
732 test_logger.set_flush_period(Some(Duration::from_secs(1)));
733
734 assert_eq!(test_sink.flush_count(), 0);
735
736 thread::sleep(Duration::from_millis(1250));
737 assert_eq!(test_sink.flush_count(), 1);
738
739 thread::sleep(Duration::from_millis(1250));
740 assert_eq!(test_sink.flush_count(), 2);
741
742 test_logger.set_flush_period(None);
743
744 thread::sleep(Duration::from_millis(1250));
745 assert_eq!(test_sink.flush_count(), 2);
746
747 test_logger.set_flush_period(Some(Duration::from_secs(1)));
748
749 thread::sleep(Duration::from_millis(1250));
750 assert_eq!(test_sink.flush_count(), 3);
751 }
752
753 #[test]
754 fn builder_name() {
755 Logger::builder().name("hello-world");
756
757 macro_rules! assert_name_err {
758 ( $($name:literal),+ $(,)? ) => {
759 $(match Logger::builder().name($name).build() {
760 Err(Error::InvalidArgument(InvalidArgumentError::LoggerName(err))) => {
761 assert_eq!(err.name(), $name)
762 }
763 _ => panic!("test case '{}' failed", $name),
764 })+
765 };
766 }
767
768 assert_name_err! {
769 " hello", "hello ",
770 "hello,world", "hello=world", "hello*world", "hello?world", "hello$world",
771 "hello{world", "hello}world", r#"hello"world"#, "hello'world", "hello;world",
772 };
773 }
774
775 #[test]
776 fn env_level() {
777 macro_rules! assert_levels {
778 ($env_level:literal, DEFAULT => $default:expr, UNNAMED => $unnamed:expr, NAMED($name:literal) => $named:expr $(,)?) => {
779 assert_eq!(
780 Logger::builder()
781 .build_inner_for_test($env_level, true)
782 .level_filter(),
783 $default
784 );
785 assert_eq!(
786 Logger::builder()
787 .build_inner_for_test($env_level, false)
788 .level_filter(),
789 $unnamed
790 );
791 assert_eq!(
792 Logger::builder()
793 .name($name)
794 .build_inner_for_test($env_level, false)
795 .level_filter(),
796 $named
797 );
798 };
799 (_, DEFAULT => $default:expr, UNNAMED => $unnamed:expr, NAMED($name:literal) => $named:expr $(,)?) => {
800 assert_eq!(
801 Logger::builder().build_default().unwrap().level_filter(),
802 $default
803 );
804 assert_eq!(Logger::builder().build().unwrap().level_filter(), $unnamed);
805 assert_eq!(
806 Logger::builder()
807 .name($name)
808 .build()
809 .unwrap()
810 .level_filter(),
811 $named
812 );
813 };
814 }
815
816 let unchanged = LevelFilter::MoreSevereEqual(Level::Info);
817
818 assert_levels!(
819 _,
820 DEFAULT => unchanged,
821 UNNAMED => unchanged,
822 NAMED("name") => unchanged,
823 );
824
825 assert_levels!(
826 "deBug",
827 DEFAULT => LevelFilter::MoreSevereEqual(Level::Debug),
828 UNNAMED => unchanged,
829 NAMED("name") => unchanged,
830 );
831
832 assert_levels!(
833 "deBug,*=tRace",
834 DEFAULT => LevelFilter::MoreSevereEqual(Level::Debug),
835 UNNAMED => LevelFilter::MoreSevereEqual(Level::Trace),
836 NAMED("name") => LevelFilter::MoreSevereEqual(Level::Trace),
837 );
838
839 assert_levels!(
840 "=trAce",
841 DEFAULT => unchanged,
842 UNNAMED => LevelFilter::MoreSevereEqual(Level::Trace),
843 NAMED("name") => unchanged,
844 );
845
846 assert_levels!(
847 "*=waRn",
848 DEFAULT => unchanged,
849 UNNAMED => LevelFilter::MoreSevereEqual(Level::Warn),
850 NAMED("name") => LevelFilter::MoreSevereEqual(Level::Warn),
851 );
852
853 assert_levels!(
854 "=eRror,*=waRn",
855 DEFAULT => unchanged,
856 UNNAMED => LevelFilter::MoreSevereEqual(Level::Error),
857 NAMED("name") => LevelFilter::MoreSevereEqual(Level::Warn),
858 );
859
860 assert_levels!(
861 "=eRror,*=waRn,name=trAce",
862 DEFAULT => unchanged,
863 UNNAMED => LevelFilter::MoreSevereEqual(Level::Error),
864 NAMED("name") => LevelFilter::MoreSevereEqual(Level::Trace),
865 );
866
867 assert_levels!(
868 "all,*=all",
869 DEFAULT => LevelFilter::All,
870 UNNAMED => LevelFilter::All,
871 NAMED("name") => LevelFilter::All,
872 );
873
874 assert_levels!(
875 "off,*=all",
876 DEFAULT => LevelFilter::Off,
877 UNNAMED => LevelFilter::All,
878 NAMED("name") => LevelFilter::All,
879 );
880 }
881
882 #[test]
883 fn fork_logger() {
884 let test_sink = (Arc::new(TestSink::new()), Arc::new(TestSink::new()));
885 let logger = Arc::new(build_test_logger(|b| b.sink(test_sink.0.clone())));
886
887 assert!(logger.name().is_none());
888 assert_eq!(test_sink.0.log_count(), 0);
889 assert_eq!(test_sink.0.flush_count(), 0);
890 assert_eq!(test_sink.1.log_count(), 0);
891 assert_eq!(test_sink.1.flush_count(), 0);
892
893 info!(logger: logger, "qwq");
894 assert!(logger.name().is_none());
895 assert_eq!(test_sink.0.log_count(), 1);
896 assert_eq!(test_sink.0.flush_count(), 0);
897 assert_eq!(test_sink.1.log_count(), 0);
898 assert_eq!(test_sink.1.flush_count(), 0);
899
900 let old = logger;
901 let new = old.fork_with_name(Some("cat")).unwrap();
902 info!(logger: new, "meow");
903 assert!(old.name().is_none());
904 assert_eq!(new.name(), Some("cat"));
905 assert_eq!(test_sink.0.log_count(), 2);
906 assert_eq!(test_sink.0.flush_count(), 0);
907 assert_eq!(test_sink.1.log_count(), 0);
908 assert_eq!(test_sink.1.flush_count(), 0);
909
910 let old = new;
911 let new = old
912 .fork_with(|new| {
913 new.set_name(Some("dog")).unwrap();
914 new.sinks_mut().push(test_sink.1.clone());
915 Ok(())
916 })
917 .unwrap();
918 info!(logger: new, "woof");
919 assert_eq!(old.name(), Some("cat"));
920 assert_eq!(new.name(), Some("dog"));
921 assert_eq!(test_sink.0.log_count(), 3);
922 assert_eq!(test_sink.0.flush_count(), 0);
923 assert_eq!(test_sink.1.log_count(), 1);
924 assert_eq!(test_sink.1.flush_count(), 0);
925
926 assert!(matches!(
927 new.fork_with_name(Some("invalid,name")),
928 Err(Error::InvalidArgument(InvalidArgumentError::LoggerName(_)))
929 ));
930
931 assert!(new
932 .fork_with_name(None as Option<&str>)
933 .unwrap()
934 .name()
935 .is_none());
936
937 let test_sink = (Arc::new(TestSink::new()), Arc::new(TestSink::new()));
938 let old = Arc::new(build_test_logger(|b| b.sink(test_sink.0.clone())));
939 old.set_flush_period(Some(Duration::from_secs(1)));
940 std::thread::sleep(Duration::from_millis(1250));
941
942 let _new = old
943 .fork_with(|new| {
944 new.sinks_mut().clear();
945 new.sinks_mut().push(test_sink.1.clone());
946 Ok(())
947 })
948 .unwrap();
949 std::thread::sleep(Duration::from_millis(1250));
950
951 assert_eq!(test_sink.0.log_count(), 0);
952 assert_eq!(test_sink.0.flush_count(), 2);
953 assert_eq!(test_sink.1.log_count(), 0);
954 assert_eq!(test_sink.1.flush_count(), 1);
955 }
956}