Давайте начнем с этого минимального, воспроизводимого примера :
use snafu::Snafu;
#[derive(Debug, Snafu)]
enum Error {
SampleError { msg: String },
}
type Result<T, E = Error> = std::result::Result<T, E>;
fn alpha() -> Result<()> {
beta()
}
fn beta() -> Result<()> {
gamma()
}
fn gamma() -> Result<()> {
SampleError { msg: "foo" }.fail()
}
Обратите внимание, что вместо него используется селектор контекста SampleError
и метод fail
непосредственного использования варианта enum для создания ошибки.
Теперь мы импортируем snafu::Backtrace
и добавляем его к нашей ошибке, называя его backtrace
(см. управление обратными трассами , если вы должны вызвать его что-то еще).
use snafu::{Snafu, Backtrace};
#[derive(Debug, Snafu)]
enum Error {
SampleError { msg: String, backtrace: Backtrace },
}
Если бы это была библиотека, это то, где вы должны остановиться. Ваша ошибка теперь будет опционально , если включена обратная трассировка, если binary решит, что обратные трассы того стоят. Это сделано, поскольку обратные трассировки еще не стабилизированы в Rust, поэтому SNAFU должен быть совместим с несколькими возможными реализациями.
Если вы управляете двоичным файлом, вам необходимо решить, как будут реализованы обратные трассировки. Существует три основных реализации, выбранных с помощью флага функции:
backtraces
- обеспечивает непрозрачный Backtrace
тип backtraces-impl-backtrace-crate
- использует стороннюю обратную трассировку ящик. snafu::Backtrace
это просто псевдоним backtrace::Backtrace
. unstable-backtraces-impl-std
- используется нестабильная стандартная библиотека Backtrace
. snafu::Backtrace
это просто псевдоним std::backtrace::Backtrace
.
После того, как вы выбрали флаг реализации, добавьте его в свой автомобиль go .toml:
[dependencies]
snafu = { version = "0.6.3", features = ["backtraces"] }
Затем вам нужно будет обработать ошибку где-то высоко в вашей программе, получить обратную трассировку и распечатать ее. При этом используется черта ErrorCompat
, которую я рекомендую использовать более подробно, чтобы ее было легче удалить позже, когда она стабилизируется в стандартной библиотеке:
use snafu::ErrorCompat;
fn main() {
if let Err(e) = alpha() {
if let Some(bt) = ErrorCompat::backtrace(&e) {
println!("{:?}", bt);
}
}
}
0: backtrace::backtrace::trace_unsynchronized
1: backtrace::backtrace::trace
2: backtrace::capture::Backtrace::create
3: backtrace::capture::Backtrace::new
4: <backtrace::capture::Backtrace as snafu::GenerateBacktrace>::generate
5: so::SampleError<__T0>::fail
6: so::gamma
7: so::beta
8: so::alpha
9: so::main
10: std::rt::lang_start::{{closure}}
11: std::panicking::try::do_call
12: __rust_maybe_catch_panic
13: std::rt::lang_start_internal
14: std::rt::lang_start
15: main
Отказ от ответственности Я - основной автор SNAFU.
Вы правы, что это не было подробно описано в руководстве пользователя , и я создал проблема, чтобы улучшить это . Наиболее релевантным является раздел, посвященный флагам функций .
. В репозитории SNAFU имеется несколько тестов для обратных трасс, на которые вы можете посмотреть: