1use std::borrow::Cow;
2use tracing_subscriber::filter::ParseError;
3use tracing_subscriber::EnvFilter;
4
5const DEFAULT_RUST_LOG: &str = "tokio_reactor=info,\
7 config=info,\
8 unc=info,\
9 recompress=info,\
10 stats=info,\
11 telemetry=info,\
12 db=info,\
13 delay_detector=info,\
14 unc-performance-metrics=info,\
15 state_viewer=info,\
16 warn";
17
18#[non_exhaustive]
19#[derive(thiserror::Error, Debug)]
20pub enum BuildEnvFilterError {
21 #[error("could not create a log filter for {1}")]
22 CreateEnvFilter(#[source] ParseError, String),
23}
24
25#[derive(Debug)]
26pub struct EnvFilterBuilder<'a> {
27 rust_log: Cow<'a, str>,
28 verbose: Option<&'a str>,
29}
30
31impl<'a> EnvFilterBuilder<'a> {
32 pub fn from_env() -> Self {
35 Self::new(
36 std::env::var("RUST_LOG").map(Cow::Owned).unwrap_or(Cow::Borrowed(DEFAULT_RUST_LOG)),
37 )
38 }
39
40 pub fn new<S: Into<Cow<'a, str>>>(rust_log: S) -> Self {
44 Self { rust_log: rust_log.into(), verbose: None }
45 }
46
47 pub fn verbose(mut self, target: Option<&'a str>) -> Self {
52 self.verbose = target;
53 self
54 }
55
56 pub fn finish(self) -> Result<EnvFilter, BuildEnvFilterError> {
58 let mut env_filter = EnvFilter::try_new(self.rust_log.clone())
59 .map_err(|err| BuildEnvFilterError::CreateEnvFilter(err, self.rust_log.to_string()))?;
60 if let Some(module) = self.verbose {
61 env_filter = env_filter
62 .add_directive("cranelift_codegen=warn".parse().expect("parse directive"))
63 .add_directive("h2=warn".parse().expect("parse directive"))
64 .add_directive("tower=warn".parse().expect("parse directive"))
65 .add_directive("trust_dns_resolver=warn".parse().expect("parse directive"))
66 .add_directive("trust_dns_proto=warn".parse().expect("parse directive"));
67 env_filter = if module.is_empty() {
68 env_filter.add_directive(tracing::Level::DEBUG.into())
69 } else {
70 let directive = format!("{}=debug", module).parse().map_err(|err| {
71 BuildEnvFilterError::CreateEnvFilter(err, format!("{}=debug", module))
72 })?;
73 env_filter.add_directive(directive)
74 };
75 }
76 Ok(env_filter)
77 }
78}
79
80pub fn make_env_filter(verbose: Option<&str>) -> Result<EnvFilter, BuildEnvFilterError> {
81 let env_filter = EnvFilterBuilder::from_env().verbose(verbose).finish()?;
82 let env_filter = if cfg!(feature = "sandbox") {
85 env_filter.add_directive("sandbox=debug".parse().unwrap())
86 } else {
87 env_filter
88 };
89 Ok(env_filter)
90}