secret_scraper/
logging.rs1use std::{
4 io::{self, Write},
5 sync::atomic::{AtomicBool, Ordering},
6};
7
8use tracing_appender::non_blocking::WorkerGuard;
9use tracing_subscriber::{EnvFilter, filter, fmt, prelude::*};
10
11static LOGGING_DISABLED: AtomicBool = AtomicBool::new(false);
12
13#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15pub enum LogLevel {
16 Warn,
18 Info,
20}
21
22impl LogLevel {
23 fn as_filter(self) -> &'static str {
24 match self {
25 Self::Warn => "warn",
26 Self::Info => "info",
27 }
28 }
29}
30
31pub fn cli_log_level(verbose: bool) -> LogLevel {
33 if verbose {
34 LogLevel::Info
35 } else {
36 LogLevel::Warn
37 }
38}
39
40pub fn init_tracing_with_level(level: LogLevel) -> WorkerGuard {
45 LOGGING_DISABLED.store(false, Ordering::SeqCst);
46
47 let file_appender = tracing_appender::rolling::daily("./logs", "scraper.log");
48 let (file_writer, guard) = tracing_appender::non_blocking(file_appender);
49
50 let filter = EnvFilter::try_new(level.as_filter()).expect("valid filter");
51 let shutdown_filter = filter::filter_fn(|_| !LOGGING_DISABLED.load(Ordering::SeqCst));
52
53 let stdout_layer = fmt::layer()
54 .with_writer(std::io::stdout)
55 .with_ansi(true)
56 .compact()
57 .with_filter(shutdown_filter.clone());
58
59 let file_layer = fmt::layer()
60 .json()
61 .with_writer(file_writer)
62 .with_ansi(false)
63 .with_target(true)
64 .with_file(true)
65 .with_line_number(true)
66 .with_filter(shutdown_filter);
67
68 tracing_subscriber::registry()
69 .with(filter)
70 .with(stdout_layer)
71 .with(file_layer)
72 .init();
73
74 guard
75}
76
77pub fn notify_shutdown(mut writer: impl Write) -> io::Result<()> {
79 disable_logging();
80 writeln!(writer, "Shutdown...")
81}
82
83pub fn disable_logging() {
85 LOGGING_DISABLED.store(true, Ordering::SeqCst);
86}
87
88#[cfg(test)]
90pub fn logging_disabled() -> bool {
91 LOGGING_DISABLED.load(Ordering::SeqCst)
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn shutdown_notification_disables_logging_and_prints_message() {
100 let mut out = Vec::new();
101
102 notify_shutdown(&mut out).expect("notify shutdown");
103
104 assert!(logging_disabled());
105 assert_eq!(
106 String::from_utf8(out).expect("utf8 output"),
107 "Shutdown...\n"
108 );
109 }
110
111 #[test]
112 fn cli_log_level_defaults_to_warn_and_verbose_enables_info() {
113 assert_eq!(cli_log_level(false), LogLevel::Warn);
114 assert_eq!(cli_log_level(true), LogLevel::Info);
115 }
116}