use std::error::Error; use std::{panic, thread}; use backtrace::Backtrace; use bevy::prelude::*; pub fn error_handler(In(result): In>>) { if let Err(e) = result { error!("{}", e); } } fn init_panic_handler() { panic::set_hook(Box::new(|info| { let backtrace = Backtrace::default(); let thread = thread::current(); let thread = thread.name().unwrap_or(""); let msg = match info.payload().downcast_ref::<&'static str>() { Some(s) => *s, None => match info.payload().downcast_ref::() { Some(s) => &**s, None => "Box", }, }; match info.location() { Some(location) => { error!( target: "panic", "thread '{}' panicked at '{}': {}:{}{:?}", thread, msg, location.file(), location.line(), backtrace ); } None => error!( target: "panic", "thread '{}' panicked at '{}'{:?}", thread, msg, backtrace ), } })); } #[derive(Clone, Debug, Default)] pub struct ErrorConfig { pub sentry_dsn: Option, pub version: Option, } pub struct ErrorPlugin; impl Plugin for ErrorPlugin { fn build(&self, app: &mut App) { if !cfg!(debug_assertions) { init_panic_handler(); } if let Some(config) = app.world.get_resource::() { if let Some(dsn) = &config.sentry_dsn { let release = config.version.clone().unwrap_or_else(|| "".to_string()); let guard = sentry::init(( dsn.as_str(), sentry::ClientOptions { release: Some(release.into()), ..Default::default() }, )); app.insert_resource(guard); } } } }