use color_eyre::eyre;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum WaypointError {
#[error("Configuration error: {0}")]
Config(#[from] crate::config::ConfigError),
#[error("Database error: {0}")]
Database(#[from] crate::database::Error),
#[error("Redis error: {0}")]
Redis(#[from] crate::redis::error::Error),
#[error("Hub error: {0}")]
Hub(#[from] crate::hub::error::Error),
#[error("Processing error: {0}")]
Processing(String),
#[error("IO error: {0}")]
IO(#[from] std::io::Error),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("Network error: {0}")]
Network(String),
#[error("Unknown error: {0}")]
Unknown(String),
}
pub type Result<T> = std::result::Result<T, WaypointError>;
pub fn install_error_handlers() -> eyre::Result<()> {
color_eyre::install()?;
std::panic::set_hook(Box::new(|panic_info| {
if let Some(location) = panic_info.location() {
tracing::error!(
message = %panic_info,
panic.file = location.file(),
panic.line = location.line(),
panic.column = location.column(),
"Application panic"
);
} else {
tracing::error!(message = %panic_info, "Application panic");
}
if std::env::var_os("RUST_TEST").is_some() {
return;
}
eprintln!("💥 The application panicked! This is a bug and should be reported.");
if let Some(location) = panic_info.location() {
eprintln!(
"Panic occurred at {}:{}:{}",
location.file(),
location.line(),
location.column()
);
}
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
eprintln!("Panic message: {}", s);
} else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
eprintln!("Panic message: {}", s);
}
eprintln!("Stack trace:");
let backtrace = std::backtrace::Backtrace::force_capture();
eprintln!("{}", backtrace);
}));
Ok(())
}
pub trait IntoWaypointError<T> {
fn into_waypoint_err(self, context: &str) -> Result<T>;
}
impl<T, E: std::fmt::Display> IntoWaypointError<T> for std::result::Result<T, E> {
fn into_waypoint_err(self, context: &str) -> Result<T> {
self.map_err(|e| WaypointError::Unknown(format!("{}: {}", context, e)))
}
}
pub trait IntoWaypointErrorFromEyre<T> {
fn into_waypoint_err(self, context: &str) -> Result<T>;
}
impl<T> IntoWaypointErrorFromEyre<T> for eyre::Result<T> {
fn into_waypoint_err(self, context: &str) -> Result<T> {
self.map_err(|e| WaypointError::Unknown(format!("{}: {}", context, e)))
}
}