tag2upload_service_manager/
logging.rs

1
2// This replaces Rocket's default subscriber.
3//
4// Ours is nicer, and also  prints messages from non-Rocket code.
5// (I'm not sure what's wrong with the Rocket one
6// but I'm not inclined to debug it.)
7
8use crate::prelude::*;
9
10pub use tracing_subscriber::filter::LevelFilter;
11pub use tracing_subscriber::util::SubscriberInitExt as _;
12
13pub use tracing_logrotate::{Interval, LevelConfig};
14
15pub fn default_schedule() -> tracing_logrotate::Config {
16    use LevelFilter as L;
17    use Interval as I;
18
19    [
20        (L::DEBUG, I::Hour, 72),
21        (L::INFO,  I::Day,  28),
22    ]
23        .into_iter()
24        .map(|(level, interval, max_files)| {
25            (level, LevelConfig { interval, max_files })
26        })
27        .collect::<BTreeMap<_, _>>()
28        .into()
29}
30
31pub fn setup(config: &Config) -> Result<(), StartupError> {
32    use StartupError as SE;
33
34    #[cfg(test)]
35    match crate::test::t_logging_setup() {
36        Ok(()) => {},
37        Err(()) => return Ok(()),
38    }
39
40    let level = config.log.level
41        .or_else(|| {
42            let _log_dir = config.log.dir.as_ref()?;
43            let l = config.log.schedule.most_verbose_level();
44            Some(l)
45        })
46        .unwrap_or(LevelFilter::INFO);
47
48    let tracing = format!(
49        // rocket::server emits 3 INFO for every request.
50        // We don't want them in our info log and we don't want to
51        // try to fix this with tracing's broken abstractions.
52        // just filter them out.
53        "tag2upload_service_manager={},rocket::server=warn,info,{}",
54        level,
55        config.log.tracing,
56    );
57
58    let filter = tracing_subscriber::filter::EnvFilter::builder()
59        .parse(&tracing)
60        .with_context(|| format!(
61 "failed to parse tracing EnvFilter specification {tracing:?}"
62        ))
63        .map_err(SE::Logging)?;
64
65    let subscriber = tracing_subscriber::FmtSubscriber::builder()
66        .with_env_filter(filter);
67
68    macro_rules! finish_with_subscriber { { $subscriber:expr } => {
69        // tracing_subscribers' generics are quite fearsome.
70        // the builder gets tainted by the writer.
71        $subscriber
72            .try_init()
73            .map_err(|e| SE::Logging(
74                anyhow!("tracing subscriber already initialised? {e}")
75            ))?;
76    } }
77
78    if let Some(log_dir) = &config.log.dir {
79        let writer = tracing_logrotate::Appender::new(
80            log_dir.clone().into(),
81            &config.log.schedule,
82        )
83            .context("failed to set up logfile writer")
84            .map_err(SE::Logging)?;
85
86        let subscriber = subscriber
87            .with_ansi(false)
88            .with_writer(writer);
89        finish_with_subscriber!(subscriber);
90    } else {
91        finish_with_subscriber!(subscriber);
92    };
93
94    Ok(())
95}