diff --git a/bin/src/main.rs b/bin/src/main.rs index 8b7df62e7..a89982074 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -4,8 +4,9 @@ use tokio::sync::Mutex; use tracing::info; #[cfg(not(windows))] use tracing::{debug, trace, warn}; - -use tracing_subscriber::{filter::LevelFilter, EnvFilter, FmtSubscriber}; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::Registry; +use tracing_subscriber::{filter::LevelFilter, EnvFilter}; mod _main; #[cfg(feature = "dep_audit")] @@ -35,10 +36,10 @@ fn main() -> anyhow::Result<()> { let log_level_env_filter = EnvFilter::builder() .with_default_directive(LevelFilter::INFO.into()) .from_env_lossy(); - let subscriber = FmtSubscriber::builder() - .with_env_filter(log_level_env_filter) - .with_writer(std::io::stderr) - .finish(); + let log_level_layer = tracing_subscriber::fmt::layer().with_writer(std::io::stderr); + let subscriber = Registry::default() + .with(log_level_env_filter) + .with(log_level_layer); tracing::subscriber::set_global_default(subscriber).expect("failied to set subscriber"); diff --git a/common/fs/src/cache/mod.rs b/common/fs/src/cache/mod.rs index da3aad762..47a2a6fd0 100644 --- a/common/fs/src/cache/mod.rs +++ b/common/fs/src/cache/mod.rs @@ -6,7 +6,7 @@ use crate::lookback::Lookback; use crate::rule::{RuleDef, Rules, Status}; use metrics::Metrics; -use notify_stream::{Event as WatchEvent, RecursiveMode, Watcher}; +use notify_stream::{ContextError, Event as WatchEvent, RecursiveMode, Watcher}; use state::{FileId, Span, SpanVec}; use std::borrow::Cow; @@ -57,7 +57,7 @@ const TAIL_WARN_THRESHOLD_B: u64 = 3000000; #[derive(Debug, Error)] pub enum Error { #[error("error watching: {0:?} {1:?}")] - Watch(Option, notify_stream::Error), + Watch(Option, ContextError), #[error("error need to rescan")] Rescan, #[error("got event for untracked watch descriptor: {0:?}")] @@ -671,7 +671,7 @@ impl FileSystem { "There was an error mapping a file change: {:?} ({:?})", e, p ); - Err(Error::Watch(p.clone(), e.clone())) + Err(Error::Watch(p.clone(), ContextError::new(e.clone()))) } WatchEvent::Rescan => Err(Error::Rescan), }; diff --git a/common/notify_stream/src/lib.rs b/common/notify_stream/src/lib.rs index 3ed493715..39bc6f8a3 100644 --- a/common/notify_stream/src/lib.rs +++ b/common/notify_stream/src/lib.rs @@ -3,6 +3,7 @@ extern crate notify; use futures::{stream, Stream}; use notify::event::{CreateKind, DataChange, ModifyKind, RemoveKind, RenameMode}; use notify::{Config, ErrorKind, EventKind, Watcher as NotifyWatcher}; +use std::backtrace::Backtrace; use std::path::Path; use std::rc::Rc; use time::OffsetDateTime; @@ -83,6 +84,22 @@ pub enum Error { MaxFilesWatch, } +#[derive(Debug)] +pub struct ContextError { + error: Error, + #[allow(dead_code)] + context: Backtrace, +} + +impl ContextError { + pub fn new(error: Error) -> Self { + Self { + error, + context: Backtrace::capture(), + } + } +} + #[derive(Debug)] pub enum RecursiveMode { Recursive, @@ -123,14 +140,14 @@ impl Watcher { /// Adds a new directory or file to watch #[instrument(level = "trace")] - pub fn watch(&mut self, path: &Path, mode: RecursiveMode) -> Result<(), Error> { + pub fn watch(&mut self, path: &Path, mode: RecursiveMode) -> Result<(), ContextError> { trace!("watching {:?}", path); self.watcher.watch(path, mode.into()).map_err(|e| e.into()) } #[instrument(level = "trace")] /// Removes a file or directory - pub fn unwatch(&mut self, path: &Path) -> Result<(), Error> { + pub fn unwatch(&mut self, path: &Path) -> Result<(), ContextError> { trace!("unwatching {:?}", path); self.watcher.unwatch(path).map_err(|e| e.into()) } @@ -139,11 +156,16 @@ impl Watcher { /// /// Returns Ok(true) when watch was found and removed. #[instrument(level = "trace")] - pub fn unwatch_if_exists(&mut self, path: &Path) -> Result { + pub fn unwatch_if_exists(&mut self, path: &Path) -> Result { trace!("unwatching {:?} if it exists", path); - match self.watcher.unwatch(path).map_err(|e| e.into()) { + #[allow(clippy::redundant_closure)] + match self + .watcher + .unwatch(path) + .map_err(|e| >::into(e)) + { Ok(_) => Ok(true), - Err(e) => match e { + Err(e) => match e.error { // Ignore watch not found Error::WatchNotFound => Ok(false), _ => Err(e), @@ -235,15 +257,15 @@ impl Default for Watcher { } } -impl From for Error { - fn from(e: notify::Error) -> Error { +impl From for ContextError { + fn from(e: notify::Error) -> ContextError { match e.kind { - ErrorKind::Generic(s) => Error::Generic(s), - ErrorKind::Io(err) => Error::Io(format!("{}", err)), - ErrorKind::PathNotFound => Error::PathNotFound, - ErrorKind::WatchNotFound => Error::WatchNotFound, - ErrorKind::InvalidConfig(c) => Error::InvalidConfig(c), - ErrorKind::MaxFilesWatch => Error::MaxFilesWatch, + ErrorKind::Generic(s) => ContextError::new(Error::Generic(s)), + ErrorKind::Io(err) => ContextError::new(Error::Io(format!("{}", err))), + ErrorKind::PathNotFound => ContextError::new(Error::PathNotFound), + ErrorKind::WatchNotFound => ContextError::new(Error::WatchNotFound), + ErrorKind::InvalidConfig(c) => ContextError::new(Error::InvalidConfig(c)), + ErrorKind::MaxFilesWatch => ContextError::new(Error::MaxFilesWatch), } } } @@ -263,6 +285,7 @@ mod tests { use futures::StreamExt; use pin_utils::pin_mut; + use std::backtrace::BacktraceStatus; use std::fs::{self, File}; use std::io::{self, Write}; use std::time::Duration; @@ -324,6 +347,16 @@ mod tests { }; } + #[tokio::test] + async fn test_context_error_type() { + let context_error = ContextError::new(Error::Generic("test-trace".to_string())); + assert_eq!(context_error.context.status(), BacktraceStatus::Captured); + assert_eq!( + context_error.error, + Error::Generic(String::from("test-trace")) + ); + } + #[tokio::test] #[cfg(unix)] async fn test_unwatch_if_exists() {