charon_error/
panic_hook.rs1#[macro_export]
36macro_rules! setup_panic {
37 ($submit_error_report:ty, $check_if_known_error:ident) => {
38 if ::std::env::var("RUST_BACKTRACE").is_err() {
41 #[allow(unused_imports)]
42 use charon_error::prelude::panic_hook::*;
43 #[allow(unused_imports)]
44 use std::panic::{self, PanicHookInfo};
45
46 panic::set_hook(Box::new(move |info: &PanicHookInfo| {
47 let payload = info.payload();
48 let panic_message = if let Some(s) = payload.downcast_ref::<&str>() {
49 s.to_string()
50 } else if let Some(s) = payload.downcast_ref::<String>() {
51 s.clone()
52 } else if let Some(s) = payload.downcast_ref::<AnyhowError>() {
53 s.to_string()
54 } else if let Some(s) = payload.downcast_ref::<ErrorReport>() {
55 s.get_last_error_title()
56 } else {
57 String::new()
58 };
59 if let Some(message) = $check_if_known_error(&panic_message) {
60 eprintln!(
62 "{}: The application encountered an error it could not recover from.\n\
63 This is a known issue: {}\n\
64 Panic message: {}\n",
65 "PANIC".bright_red(),
66 message,
67 panic_message,
68 );
69 } else {
70 let panic_location: Option<SourceLocation> = match info.location() {
72 Some(location) => Some(SourceLocation::from_panic_location(location)),
73 None => None,
74 };
75
76 eprintln!(
77 "{}: A panic occurred during execution.\n\
78 * Message: '{}'\n\
79 * Path: '{}'",
80 "PANIC".bright_red(),
81 panic_message.bright_cyan().bold(),
82 panic_location.as_ref()
83 .map(|s| s.display_location(None))
84 .unwrap_or(String::from("Unknown location")),
85 );
86
87 let error_report: &ErrorReport = if let Some(s) = payload.downcast_ref::<&str>() {
88 &ErrorReport::from_error(StringError::new(s.to_string()))
89 } else if let Some(s) = payload.downcast_ref::<String>() {
90 &ErrorReport::from_error(StringError::new(s.to_string()))
91 } else if let Some(s) = payload.downcast_ref::<AnyhowError>() {
92 &ErrorReport::from_anyhow_error_ref(s)
93 } else if let Some(s) = payload.downcast_ref::<ErrorReport>() {
94 s
95 } else {
96 &ErrorReport::from_error(StringError::new(panic_message))
97 };
98
99 #[cfg(not(debug_assertions))]
102 {
103 let submit_report =
104 <$submit_error_report as SubmitErrorReport>::new(error_report);
105 eprintln!(
106 "{}: The application encountered an error it could not recover from.\n\
107 If you report this we might be able to fix this in the future.\n\
108 {title}\n\
109 {message}",
110 "PANIC".bright_red(),
111 title = submit_report.get_title(), message = submit_report.create_message().unwrap_or("Something went wrong while generating error report.".to_owned()),
113 );
114 let error_report_id = submit_report.get_error_report().get_unique_id();
116 let error_title = submit_report.get_title();
117 let panic_location_string = panic_location.as_ref()
118 .map(|s| s.display_location(Some(LinkDebugIde::NoLink)))
119 .unwrap_or(String::from("Unknown location"));
120 tracing::error!(
121 error_type = "PANIC",
122 error_report_id = error_report_id,
123 error_title = error_title,
124 panic_location = panic_location_string,
125 "The application encountered an error it could not recover from: {error_title}"
126 );
127 }
128
129 #[cfg(debug_assertions)]
132 {
133 let submit_report =
134 <$submit_error_report as SubmitErrorReport>::new(error_report);
135 let message = submit_report.error_report.stringify(ErrorFmtSettings::default());
136 let url = submit_report.create_submit_url_limited(2083).map(|s| s.to_string());
139
140 match (message, url) {
141 (Err(m_err), Err(u_err)) => {
142 eprintln!(
143 "PANIC: The application encountered an error it could not recover from.\n\
144 This error occurred while handling the Panic of an other error.\n\
145 Panic message while creating panic message: {m_err}\n\
146 Panic message while creating panic report URL: {u_err}\n"
147 );
148 }
149 (Err(m_err), Ok(_)) => {
150 eprintln!(
151 "PANIC: The application encountered an error it could not recover from.\n\
152 This error occurred while handling the Panic of an other error.\n\
153 Panic message while creating panic message: {m_err}"
154 );
155 }
156 (Ok(_), Err(u_err)) => {
157 eprintln!(
158 "PANIC: The application encountered an error it could not recover from.\n\
159 This error occurred while handling the Panic of an other error.\n\
160 Panic message while creating panic report URL: {u_err}"
161 );
162 }
163 (Ok(message), Ok(url)) => {
164 let mut report_link = "No report link available.".to_owned();
166 if !url.starts_with("data:text/plain,") {
167 report_link = format!("\
168 ┌──────────────────────────┐\n\
169 │ \x1b]8;;{url}\x1b\\\u{f296} Open/Submit Bug Report\x1b]8;;\x1b\\ │\n\
170 └──────────────────────────┘");
171 }
172 if !url.starts_with("data:text/plain,") && std::env::var("NO_COLOR").is_ok() {
173 report_link = format!("Report Link: {}", url);
174 }
175
176 eprintln!(
177 "{}: The application encountered an error it could not recover from.\n\
178 {message}\n\
179 {report_link}",
180 "PANIC".bright_red(),
181 );
182 }
183 }
184 let error_report_id = submit_report.get_error_report().get_unique_id();
186 let error_title = submit_report.get_title();
187 let panic_location_string = panic_location.as_ref()
188 .map(|s| s.display_location(Some(LinkDebugIde::NoLink)))
189 .unwrap_or(String::from("Unknown location"));
190 tracing::error!(
191 error_type = "PANIC",
192 error_report_id = error_report_id,
193 error_title = error_title,
194 panic_location = panic_location_string,
195 "The application encountered an error it could not recover from: {error_title}"
196 );
197 }
198 }
199 }));
200 }
201 };
202}
203
204#[macro_export]
210macro_rules! setup_panic_simple {
211 () => {{
212 #[allow(unused_imports)]
213 use charon_error::prelude::panic_hook::*;
214 #[allow(unused_imports)]
215 use std::panic::{self, PanicHookInfo};
216
217 panic::set_hook(Box::new(move |info: &PanicHookInfo| {
218 let payload = info.payload();
219 let panic_message = if let Some(s) = payload.downcast_ref::<&str>() {
220 s.to_string()
221 } else if let Some(s) = payload.downcast_ref::<String>() {
222 s.clone()
223 } else if let Some(s) = payload.downcast_ref::<AnyhowError>() {
224 s.to_string()
225 } else if let Some(s) = payload.downcast_ref::<ErrorReport>() {
226 s.get_last_error_title()
227 } else {
228 String::new()
229 };
230 let panic_location: Option<SourceLocation> = match info.location() {
231 Some(location) => Some(SourceLocation::from_panic_location(location)),
232 None => None,
233 };
234 eprintln!(
235 "PANIC: The application encountered an error it could not recover from.\n\
236 * Message: '{panic_message}'\n\
237 * Path: '{}'",
238 panic_location
239 .as_ref()
240 .map(|s| s.display_location(None))
241 .unwrap_or(String::from("Unknown location"))
242 );
243 let panic_title = panic_message;
245 let panic_location_string = panic_location
246 .as_ref()
247 .map(|s| s.display_location(Some(LinkDebugIde::NoLink)))
248 .unwrap_or(String::from("Unknown location"));
249 tracing::error!(
250 error_type = "PANIC",
251 panic_location = panic_location_string,
252 panic_title = panic_title,
253 "The application encountered an error it could not recover from: {panic_title}"
254 );
255 }));
256 }};
257}