scion_sdk_utils/panic_hook.rs
1// Copyright 2026 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Copyright 2026 Anapaya Systems
16//! Panic hook that logs full panic details via the tracing framework.
17
18/// Installs a panic hook that logs the full panic location and message via
19/// [`tracing::error!`].
20///
21/// The previous hook is preserved and called after logging, so the default
22/// Rust behaviour (print to stderr, optionally abort) is retained.
23pub fn install_panic_hook() {
24 let prev = std::panic::take_hook();
25 std::panic::set_hook(Box::new(move |info| {
26 log_panic(info);
27 prev(info);
28 }));
29}
30
31fn log_panic(info: &std::panic::PanicHookInfo<'_>) {
32 let location = info
33 .location()
34 .map(|l| format!("{}:{}:{}", l.file(), l.line(), l.column()));
35 let location = location.as_deref().unwrap_or("<unknown location>");
36
37 let payload = info.payload();
38 let msg = if let Some(s) = payload.downcast_ref::<&str>() {
39 *s
40 } else if let Some(s) = payload.downcast_ref::<String>() {
41 s.as_str()
42 } else {
43 "<non-string panic payload>"
44 };
45
46 tracing::error!(location, message = msg, "Unexpected panic occurred");
47}