logger.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. use file_rotate::{compression::Compression, suffix::AppendCount, ContentLimit, FileRotate};
  2. use log::{Level, LevelFilter, Log, Metadata, Record};
  3. use simplelog::{
  4. ColorChoice, CombinedLogger, Config, ConfigBuilder, SharedLogger, TermLogger, TerminalMode,
  5. WriteLogger,
  6. };
  7. use std::{path::PathBuf, thread::sleep, time::Duration};
  8. #[cfg(target_os = "android")]
  9. const LOGS_ENABLED: bool = true;
  10. #[cfg(not(target_os = "android"))]
  11. const LOGS_ENABLED: bool = true;
  12. // Measured in bytes
  13. const LOGFILE_MAXSIZE: usize = 5_000_000;
  14. static MUTED_TARGETS: &[&'static str] = &[
  15. "sled",
  16. "rustls",
  17. "net::channel",
  18. "net::message_publisher",
  19. "net::hosts",
  20. "net::protocol",
  21. "net::session",
  22. "net::outbound_session",
  23. "net::tcp",
  24. "net::p2p::seed",
  25. "net::refinery::handshake_node()",
  26. "system::publisher",
  27. "event_graph::dag_sync()",
  28. "event_graph::dag_insert()",
  29. "event_graph::protocol",
  30. ];
  31. static ALLOW_TRACE: &[&'static str] = &["ui", "app", "gfx"];
  32. #[cfg(target_os = "android")]
  33. fn logfile_path() -> PathBuf {
  34. use crate::android::get_external_storage_path;
  35. get_external_storage_path().join("Download/darkfi.log")
  36. }
  37. #[cfg(not(target_os = "android"))]
  38. fn logfile_path() -> PathBuf {
  39. dirs::cache_dir().unwrap().join("darkfi/darkfi.log")
  40. }
  41. #[cfg(target_os = "android")]
  42. mod android {
  43. use super::*;
  44. use android_logger::{AndroidLogger, Config as AndroidConfig};
  45. /// Implements a wrapper around the android logger so it's compatible with simplelog.
  46. pub struct AndroidLoggerWrapper {
  47. logger: AndroidLogger,
  48. level: LevelFilter,
  49. config: Config,
  50. }
  51. impl AndroidLoggerWrapper {
  52. pub fn new(level: LevelFilter, config: Config) -> Box<Self> {
  53. let cfg = AndroidConfig::default().with_max_level(level).with_tag("darkfi");
  54. Box::new(Self { logger: AndroidLogger::new(cfg), level, config })
  55. }
  56. }
  57. impl Log for AndroidLoggerWrapper {
  58. fn enabled(&self, metadata: &Metadata<'_>) -> bool {
  59. let target = metadata.target();
  60. for allow in ALLOW_TRACE {
  61. if target.starts_with(allow) {
  62. return true
  63. }
  64. }
  65. for muted in MUTED_TARGETS {
  66. if target.starts_with(muted) {
  67. return false
  68. }
  69. }
  70. if metadata.level() > self.level {
  71. return false
  72. }
  73. self.logger.enabled(metadata)
  74. }
  75. fn log(&self, record: &Record<'_>) {
  76. if self.enabled(record.metadata()) {
  77. self.logger.log(record)
  78. }
  79. }
  80. fn flush(&self) {}
  81. }
  82. impl SharedLogger for AndroidLoggerWrapper {
  83. fn level(&self) -> LevelFilter {
  84. self.level
  85. }
  86. fn config(&self) -> Option<&Config> {
  87. Some(&self.config)
  88. }
  89. fn as_log(self: Box<Self>) -> Box<dyn Log> {
  90. Box::new(*self)
  91. }
  92. }
  93. }
  94. #[cfg(not(target_os = "android"))]
  95. mod desktop {
  96. use super::*;
  97. /// Implements a wrapper around the android logger so it's compatible with simplelog.
  98. pub struct CustomTermLogger {
  99. logger: TermLogger,
  100. }
  101. impl CustomTermLogger {
  102. pub fn new(level: LevelFilter, cfg: Config) -> Box<Self> {
  103. let logger =
  104. TermLogger::new(LevelFilter::Trace, cfg, TerminalMode::Mixed, ColorChoice::Auto);
  105. Box::new(Self { logger: *logger })
  106. }
  107. }
  108. impl Log for CustomTermLogger {
  109. fn enabled(&self, metadata: &Metadata<'_>) -> bool {
  110. let target = metadata.target();
  111. for allow in ALLOW_TRACE {
  112. if target.starts_with(allow) {
  113. return true
  114. }
  115. }
  116. for muted in MUTED_TARGETS {
  117. if target.starts_with(muted) {
  118. return false
  119. }
  120. }
  121. if metadata.level() > self.level() {
  122. return false
  123. }
  124. self.logger.enabled(metadata)
  125. }
  126. fn log(&self, record: &Record<'_>) {
  127. if self.enabled(record.metadata()) {
  128. self.logger.log(record)
  129. }
  130. }
  131. fn flush(&self) {
  132. self.logger.flush()
  133. }
  134. }
  135. impl SharedLogger for CustomTermLogger {
  136. fn level(&self) -> LevelFilter {
  137. self.logger.level()
  138. }
  139. fn config(&self) -> Option<&Config> {
  140. self.logger.config()
  141. }
  142. fn as_log(self: Box<Self>) -> Box<dyn Log> {
  143. Box::new(self.logger).as_log()
  144. }
  145. }
  146. }
  147. pub fn setup_logging() {
  148. // https://gist.github.com/jb-alvarado/6e223936446bb88cd9a93e7028fc2c4f
  149. let mut loggers: Vec<Box<dyn SharedLogger>> = vec![];
  150. let cfg = ConfigBuilder::new().build();
  151. if LOGS_ENABLED {
  152. let log_file = FileRotate::new(
  153. logfile_path(),
  154. AppendCount::new(0),
  155. ContentLimit::BytesSurpassed(LOGFILE_MAXSIZE),
  156. Compression::None,
  157. #[cfg(unix)]
  158. None,
  159. );
  160. let file_logger = WriteLogger::new(LevelFilter::Trace, cfg.clone(), log_file);
  161. loggers.push(file_logger);
  162. }
  163. #[cfg(target_os = "android")]
  164. {
  165. use android::AndroidLoggerWrapper;
  166. let android_logger = AndroidLoggerWrapper::new(LevelFilter::Debug, cfg);
  167. loggers.push(android_logger);
  168. }
  169. #[cfg(not(target_os = "android"))]
  170. {
  171. use desktop::CustomTermLogger;
  172. // For ANSI colors in the terminal
  173. colored::control::set_override(true);
  174. let term_logger = CustomTermLogger::new(LevelFilter::Debug, cfg);
  175. loggers.push(term_logger);
  176. }
  177. CombinedLogger::init(loggers).expect("logger");
  178. }