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