#错误报告 #报告 #回溯 #应用 #惯用 #可定制 #对象

eyre

基于 std::error::Error 并具有可定制报告的灵活具体错误报告类型

31 个版本

0.6.12 2024 年 1 月 31 日
0.6.11 2023 年 12 月 13 日
0.6.9 2023 年 11 月 17 日
0.6.8 2022 年 4 月 4 日
0.3.5 2020 年 3 月 6 日

#20 in Rust 模式

Download history 278440/week @ 2024-04-22 256396/week @ 2024-04-29 248602/week @ 2024-05-06 268450/week @ 2024-05-13 274773/week @ 2024-05-20 264206/week @ 2024-05-27 270044/week @ 2024-06-03 273283/week @ 2024-06-10 260470/week @ 2024-06-17 275557/week @ 2024-06-24 268213/week @ 2024-07-01 288844/week @ 2024-07-08 286953/week @ 2024-07-15 316372/week @ 2024-07-22 292893/week @ 2024-07-29 300785/week @ 2024-08-05

1,216,972 每月下载
1,829 个crate中(723 个直接使用)

MIT/Apache

115KB
1.5K SLoC

eyre

Build Status Latest Version Rust Documentation Discord chat

此库提供了 eyre::Report,这是一个基于 trait object 的错误处理类型,用于在 Rust 应用程序中轻松进行惯用错误处理和报告。

这个crate是anyhow的分支,支持自定义错误报告。有关定制的更多信息,请参阅eyre::EyreHandler上的文档。

自定义报告处理器

此crate的核心功能是能够替换处理器类型,以更改错误附带的信息以及如何格式化最终报告。此crate旨在与自定义其行为的辅助crate一起使用。以下是已知导出eyre报告处理器的crate列表及其提供的功能简述。

  • stable-eyre:将回溯类型从 std 的转换为 backtrace-rs 的,以便在稳定版中捕获。报告格式与 DefaultHandler 的报告格式相同。
  • color-eyre:捕获 backtrace::Backtracetracing_error::SpanTrace。提供 Help trait,用于将警告和建议附加到错误报告中。然后使用 color-backtracecolor-spantraceansi_term 进行美观打印。有关报告格式的详细信息,请参阅 color-eyre 的 README。
  • simple-eyre:一个最小化的 EyreHandler,不捕获任何额外的信息,当您不想捕获错误的 Backtrace 时使用。
  • jane-eyre:一个仅为了玩笑而存在的报告处理库。目前仅重新导出 color-eyre

使用建议和稳定性考虑

我们建议用户不要将此库的类型重新导出作为他们自己的公共 API 的一部分,特别是对于有外部用户的库。 主要原因是,如果我们将来在 eyre 上提升主版本号,而您的用户在您升级自己的 eyre 依赖版本之前升级了他们应用代码中的 eyre 版本,这将使您的库 API 破坏。

然而,即使在 API 稳定性风险之外,还有其他很好的理由避免将 eyre::Report 作为您的公共错误类型。

  • 您导出了一个未记录的错误接口,该接口仍然可以通过向下转换访问,这使得用户难以对特定错误做出反应,同时阻止他们依赖于您无意中使其成为公共 API 一部分的细节。
    • 这反过来使得您使用的所有库的错误类型也成为您的公共 API 的一部分,并使得更改这些库成为不可检测的运行时破坏。
  • 如果您的大多数错误都是来自字符串的,您鼓励用户使用字符串比较来对特定错误做出反应,这很脆弱,并且将更新错误消息变成可能无法检测的运行时破坏。

详细信息

  • 使用 Result<T, eyre::Report>,或等价地 eyre::Result<T>,作为任何易出错函数的返回类型。

    在函数内部,使用 ? 可以轻松传播任何实现了 std::error::Error 特质的错误。

    use eyre::Result;
    
    fn get_cluster_info() -> Result<ClusterMap> {
        let config = std::fs::read_to_string("cluster.json")?;
        let map: ClusterMap = serde_json::from_str(&config)?;
        Ok(map)
    }
    
  • 使用由消息创建的新错误包装低级错误,以帮助调试人员理解发生的失败链。例如,一个低级错误“没有找到文件或目录”在没有更多关于应用程序在哪个高级步骤中的信息的情况下可能很难调试。

    use eyre::{WrapErr, Result};
    
    fn main() -> Result<()> {
        ...
        it.detach().wrap_err("Failed to detach the important thing")?;
    
        let content = std::fs::read(path)
            .wrap_err_with(|| format!("Failed to read instrs from {}", path))?;
        ...
    }
    
    Error: Failed to read instrs from ./path/to/instrs.json
    
    Caused by:
        No such file or directory (os error 2)
    
  • 支持向下转换,可以根据需要按值、共享引用或可变引用进行。

    // If the error was caused by redaction, then return a
    // tombstone instead of the content.
    match root_cause.downcast_ref::<DataStoreError>() {
        Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
        None => Err(error),
    }
    
  • 如果使用 nightly 频道,如果底层错误类型没有提供自己的,则会捕获并打印错误时的回溯。要查看回溯,必须通过 std::backtrace 中描述的环境变量启用。

    • 如果您希望恐慌和错误都具有回溯,请设置 RUST_BACKTRACE=1;
    • 如果您只想让错误具有回溯,请设置 RUST_LIB_BACKTRACE=1;
    • 如果您只想让恐慌具有回溯,请设置 RUST_BACKTRACE=1RUST_LIB_BACKTRACE=0

    此功能的跟踪问题是 rust-lang/rust#53487

  • Eyre可以与任何具有std::error::Error实现类型的错误类型一起工作,包括在您的crate中定义的错误类型。我们未捆绑derive(Error)宏,但您可以自己编写实现或使用像thiserror这样的独立宏。

    use thiserror::Error;
    
    #[derive(Error, Debug)]
    pub enum FormatError {
        #[error("Invalid header (expected {expected:?}, got {found:?})")]
        InvalidHeader {
            expected: String,
            found: String,
        },
        #[error("Missing attribute: {0}")]
        MissingAttribute(String),
    }
    
  • 可以使用eyre!宏来构造一次性错误消息,该宏支持字符串插值并生成一个eyre::Report

    return Err(eyre!("Missing attribute: {}", missing));
    
  • 在编译器的较新版本(例如1.58及以后)中,此宏还支持格式化参数捕获。

    return Err(eyre!("Missing attribute: {missing}"));
    

无标准支持

由于未解决的上游破坏,无标准支持在2020年被移除[提交608a16a]。[提交608a16a]: https://github.com/eyre-rs/eyre/pull/29/commits/608a16aa2c2c27eca6c88001cc94c6973c18f1d5

与failure的比较

eyre::Report类型类似于failure::Error,但与failure不同,我们的类型是基于标准库的std::error::Error特质而不是单独的特质failure::Fail构建的。标准库已经通过RFC 2504采纳了必要的改进,使得这成为可能。

与thiserror的比较

如果您认为您不会对错误做任何事情,只是报告它,那么请使用eyre。这在应用程序代码中很常见。如果您认为您需要一个可以通过match或报告来处理的错误类型,请使用thiserror。这在不知道用户将如何处理您的错误的情况下,在库crate中很常见。

anyhow的兼容性

此crate尽最大努力与anyhow兼容,反之亦然,通过re-exporting所有重命名的API,并使用anyhow中使用的名称,尽管仍然存在一些差异。

ContextOption

作为将Context重命名为WrapErr的一部分,我们还故意没有为Option实现WrapErr。这个决定是因为wrap_err意味着您正在创建一个新错误,该错误将其旧错误作为其source保存。在Option中,没有要包装的源错误,因此wrap_err最终变得有些没有意义。

相反,eyre提供了OptionExt::ok_or_eyre,用于从None生成静态错误,并打算让用户使用由std提供的组合函数,将Option转换为Result,用于动态错误。因此,您会像使用anyhow一样编写此代码

use anyhow::Context;

let opt: Option<()> = None;
let result_static = opt.context("static error message");
let result_dynamic = opt.with_context(|| format!("{} error message", "dynamic"));

使用eyre,我们希望用户编写

use eyre::{eyre, OptionExt, Result};

let opt: Option<()> = None;
let result_static: Result<()> = opt.ok_or_eyre("static error message");
let result_dynamic: Result<()> = opt.ok_or_else(|| eyre!("{} error message", "dynamic"));

注意:然而,为了帮助移植,我们确实提供了一个ContextCompat特质,它实现了context,你可以导入它来让现有的.context调用能够编译。

[^1]:故障示例和解释 https://github.com/eyre-rs/eyre/issues/30#issuecomment-647650361

许可证

根据您的选择,在Apache License, Version 2.0MIT license下获得许可。
除非您明确说明,否则根据Apache-2.0许可证的定义,您提交的任何旨在包含在此crate中的贡献,都将按上述方式双重许可,而不附加任何额外的条款或条件。

依赖项

~0–5.5MB
~15K SLoC