mod anyhow; mod registration; mod reqwest; #[cfg(not(target_family = "wasm"))] mod tokio; #[cfg(not(target_family = "wasm"))] mod websocket; // Re-export for macro use. #[doc(hidden)] pub use inventory::submit; pub use self::anyhow::AnyhowErrorExt; pub use registration::{ErrorRegistration, RegisteredError}; pub use registration::register_error; /// The `target` that is set by log entries from this module. pub const LOG_TARGET: &str = "errors::report_error"; /// Reports an error encountered during execution. /// /// This checks whether or not the error is actionable, and logs an error or /// warning accordingly. (Logs at the Error level get reported back to us, so /// we don't want to log anything at Error level that we aren't able to act /// upon.) #[macro_export] macro_rules! report_error { ($err:expr) => {{ #[allow(unused_imports)] use $crate::errors::{AnyhowErrorExt as _, ErrorExt as _, LOG_TARGET}; let err = $err; let log_level = if err.is_actionable() { err.report_error(); log::Level::Error } else { log::Level::Warn }; log::log!(target: LOG_TARGET, log_level, "{:#}", err); }}; } pub use report_error; /// Reports an error if the provided [`Result`] is [`Err`]. /// /// This checks whether or not the error is actionable, and logs an error or /// warning accordingly. (Logs at the Error level get reported back to us, so /// we don't want to log anything at Error level that we aren't able to act /// upon.) #[macro_export] macro_rules! report_if_error { ($result:expr) => {{ if let Err(error) = &$result { $crate::report_error!(error); } }}; } pub use report_if_error; /// Returns whether or not a log entry with the given metadata should be /// ignored by Sentry. #[cfg(feature = "crash_reporting")] pub fn should_ignore_log_for_sentry(md: &log::Metadata) -> bool { // Filter out any Error-level log entries generated by report_error!(). // report_error!() utilizes capture_anyhow() to report structured errors // instead of simple string error messages, and we don't want to _also_ // report the Error-level log line to Sentry. md.target() == LOG_TARGET && md.level() == log::Level::Error } pub trait ErrorExt: RegisteredError + std::error::Error { /// Returns whether or not an error is something that is actionable by our /// engineering team. fn is_actionable(&self) -> bool; fn report_error(&self) { #[cfg(feature = "crash_reporting")] sentry::capture_error(self); } }