Как вы видите след ошибки при использовании SNAFU? - PullRequest
1 голос
/ 31 марта 2020

Как мне заставить Backtrace работать с SNAFU? Я пытался, но я просто получаю пустые следы. Кажется, что документация скудна.

return Error::SampleError {
    msg: "foo".to_string(),
    backtrace: Backtrace::generate(),
};

print

SampleError { msg: "foo", backtrace: Backtrace(()) }

Это происходит из-за функции, которая находится очень глубоко в стеке вызовов.

1 Ответ

2 голосов
/ 31 марта 2020

Давайте начнем с этого минимального, воспроизводимого примера :

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 имеется несколько тестов для обратных трасс, на которые вы можете посмотреть:

...