thread_local_logger.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. use std::cell::RefCell;
  2. use std::sync::{Arc, Once};
  3. use log::{Log, Metadata, Record};
  4. use std::fmt::Formatter;
  5. pub struct GlobalLogger;
  6. #[cfg(not(feature = "must-log"))]
  7. #[derive(Clone)]
  8. pub struct LocalLogger(Arc<dyn Log>);
  9. #[cfg(feature = "must-log")]
  10. #[derive(Clone)]
  11. pub struct LocalLogger(Option<Arc<dyn Log>>);
  12. thread_local!(static LOCAL_LOGGER: RefCell<LocalLogger> = Default::default());
  13. pub fn global_init_once() {
  14. static GLOBAL_LOGGER: GlobalLogger = GlobalLogger;
  15. static INIT_LOG_ONCE: Once = Once::new();
  16. INIT_LOG_ONCE.call_once(|| {
  17. log::set_logger(&GLOBAL_LOGGER).unwrap();
  18. // Enable all logging globally. Each local logger should have its own
  19. // filtering, which could be less efficient.
  20. log::set_max_level(log::LevelFilter::max());
  21. });
  22. }
  23. pub fn thread_init<T: 'static + Log>(logger: T) {
  24. global_init_once();
  25. #[cfg(not(feature = "must-log"))]
  26. self::set(LocalLogger(Arc::new(logger)));
  27. #[cfg(feature = "must-log")]
  28. self::set(LocalLogger(Some(Arc::new(logger))));
  29. }
  30. pub fn get() -> LocalLogger {
  31. LOCAL_LOGGER.with(|inner| inner.borrow().clone())
  32. }
  33. pub fn set(logger: LocalLogger) {
  34. LOCAL_LOGGER.with(|inner| inner.replace(logger));
  35. }
  36. pub fn reset() {
  37. self::set(LocalLogger::default())
  38. }
  39. impl Default for LocalLogger {
  40. fn default() -> Self {
  41. #[cfg(not(feature = "must-log"))]
  42. {
  43. Self(Arc::new(NopLogger))
  44. }
  45. #[cfg(feature = "must-log")]
  46. Self(None)
  47. }
  48. }
  49. impl std::ops::Deref for LocalLogger {
  50. type Target = dyn Log;
  51. fn deref(&self) -> &Self::Target {
  52. #[cfg(not(feature = "must-log"))]
  53. {
  54. self.0.deref()
  55. }
  56. #[cfg(feature = "must-log")]
  57. self.0.as_ref().unwrap().as_ref()
  58. }
  59. }
  60. impl std::fmt::Debug for LocalLogger {
  61. fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  62. f.write_str("thread local logger")
  63. }
  64. }
  65. impl Log for GlobalLogger {
  66. fn enabled(&self, metadata: &Metadata) -> bool {
  67. LOCAL_LOGGER.with(|inner| inner.borrow().enabled(metadata))
  68. }
  69. fn log(&self, record: &Record) {
  70. LOCAL_LOGGER.with(|inner| inner.borrow().log(record))
  71. }
  72. fn flush(&self) {
  73. LOCAL_LOGGER.with(|inner| inner.borrow().flush())
  74. }
  75. }
  76. struct NopLogger;
  77. impl Log for NopLogger {
  78. fn enabled(&self, _: &Metadata) -> bool {
  79. false
  80. }
  81. fn log(&self, _: &Record) {}
  82. fn flush(&self) {}
  83. }