thread_local_logger.rs 1.9 KB

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