#backtrace #tracing #error-handling

no-std trasy

一个具有跟踪和回溯支持的错误处理库

5个版本

0.1.4 2024年5月3日
0.1.3 2024年5月2日
0.1.2 2024年5月2日
0.1.1 2024年5月2日
0.1.0 2024年5月2日

调试中排名第456

Download history 334/week @ 2024-04-27 67/week @ 2024-05-04 9/week @ 2024-05-11 25/week @ 2024-05-18 98/week @ 2024-05-25 26/week @ 2024-06-01 57/week @ 2024-06-08 67/week @ 2024-06-15 56/week @ 2024-06-22 43/week @ 2024-06-29 27/week @ 2024-07-06 23/week @ 2024-07-13 1/week @ 2024-07-20 10/week @ 2024-07-27

每月下载量61

Apache-2.0

17KB
115 代码行

Trasy

Trasy是一个Rust库,旨在通过将跟踪错误与回溯集成来简化丰富的错误处理。它在需要详细上下文和错误起源跟踪以进行调试和错误解决的应用程序中特别有用。

特性

  • 跟踪错误:与tracing_error::SpanTrace集成,以捕获和显示错误的上下文。
  • 回溯支持:可选地将回溯附加到错误,以便在发生错误时提供详细的堆栈跟踪。
  • 宏以简化操作:包括宏error!bail!,以简化错误创建和传播。

安装

Trasy添加到你的Cargo.toml

[dependencies]
trasy = "0.1.0"  # Use the latest version

环境设置和配置

启用回溯

要充分利用Rust中的回溯功能,您需要设置RUST_BACKTRACE环境变量。这可以通过将变量设置为1来运行您的应用程序来完成

RUST_BACKTRACE=1 cargo run

此设置告诉Rust在发生错误时捕获详细的回溯。

使用Tracing中的#[instrument]

为了增强Rust应用程序的诊断功能,请使用来自tracingcrate的#[instrument]属性。此属性会自动对函数进行配置,记录调用的进入和退出,并捕获函数的参数

use tracing::instrument;

#[instrument]
fn compute_value(x: i32, y: i32) -> i32 {
    x + y
}

使用#[instrument]可以提供有关函数调用的宝贵见解,可以与错误处理结合使用,以更有效地跟踪错误源。

用户结果

使用 TrasyError,开发者可以同时获取和读取范围跟踪和回溯,提供双层错误上下文,增强调试能力。错误发生时的输出将类似于以下内容

错误上下文

An error occurred:
Error Context:
   0: tracing::foo
             at src/main.rs:158
   1: tracing::bar
           with hoge="hoge"
             at src/main.rs:153

回溯

Backtrace:
Backtrace [{ fn: "tracing::foo::{{closure}}", file: "./src/main.rs", line: 163 }, { fn: "tracing::foo", file: "./src/main.rs", line: 158 }, { fn: "tracing::bar", file: "./src/main.rs", line: 155 }, ...]

使用方法

基本使用

要使用 Trasy,首先导入它及其宏

use trasy::{TrasyError, error, bail};

使用 error! 宏轻松创建和传播错误

fn example_function() -> Result<(), TrasyError<String>> {
    let some_result = some_error_prone_operation();

    some_result.map_err(|e| error!(e))
}

使用回溯

要将回溯附加到错误,只需在将回溯捕获的上下文中使用错误即可

fn example_function() -> Result<(), TrasyError<String>> {
    let some_result = another_error_prone_operation();
    some_result.map_err(|e| bail!(e))
}

实现自定义错误类型

Trasy 可以包装任何实现了 std::fmt::Debugstd::fmt::Display 的错误类型。以下是如何为自定义错误类型实现它的示例

#[derive(Debug)]
enum MyError {
    Io(std::io::Error),
    Num(std::num::ParseIntError),
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            MyError::Io(ref err) => write!(f, "IO error: {}", err),
            MyError::Num(ref err) => write!(f, "Parse error: {}", err),
        }
    }
}

impl Error for MyError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match *self {
            MyError::Io(ref err) => Some(err),
            MyError::Num(ref err) => Some(err),
        }
    }
}

使用 thiserror 实现

use thiserror::Error;

use trasy::TrasyError;
use trasy::bail;

#[derive(Error, Debug)]
pub enum AppError {
    #[error("Failed to perform operation")]
    OperationError,

    #[error("IO error occurred: {0}")]
    IoError(#[from] std::io::Error),
}

trait AppErrorExt {
    fn new(error: AppError) -> Self;
}

impl AppErrorExt for TrasyError<AppError> {
    fn new(error: AppError) -> Self {
        TrasyError::new(error)
    }
}

fn might_fail(flag: bool) -> Result<(), TrasyError<AppError>> {
    if flag {
        bail!(AppError::OperationError)
    } else {
        Ok(())
    }
}

fn main() {
    match might_fail(true) {
        Ok(_) => println!("Success!"),
        Err(e) => println!("Error: {}", e),
    }
}

OpenTelemetry 集成

Trasy 支持 OpenTelemetry,允许您跟踪应用程序并将遥测数据导出到您选择的后端(例如,Jaeger、Zipkin)。本节描述了如何在应用程序中配置和使用 OpenTelemetry。

配置

要使用 OpenTelemetry 与 TrasyError,您首先需要设置遥测配置。以下是配置和启用遥测的方法

1. 定义配置

使用 TelemetryConfig 结构体配置遥测设置。您可以指定服务名称、端点、是否使用批处理或简单范围处理,以及可选的定制范围导出器。

use trasy_error::TelemetryConfig;

let config = TelemetryConfig {
    service_name: "my-awesome-service".to_string(),
    endpoint: "http://my-telemetry-collector:4318".to_string(),
    use_batch: true,
    oltp_exporter: None, // Use default OTLP exporter
};

2. 设置 OpenTelemetry

将配置传递给 setup_opentelemetry 函数以初始化遥测。此函数设置跟踪层,然后您可以使用 tracing 订阅者使用它。

use trasy_error::setup_opentelemetry;

let telemetry_layer = setup_opentelemetry(config).await.expect("Failed to set up OpenTelemetry");

// Now you can use `telemetry_layer` with your tracing subscriber setup

示例:使用跟踪订阅者完整设置

以下是一个完整示例,展示了如何使用 trasy_errortracing_subscriber 来设置跟踪。

use trasy_error::{TelemetryConfig, setup_opentelemetry};
use tracing_subscriber::{layer::SubscriberExt, Registry};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = TelemetryConfig::default().with_oltp_exporter(
        opentelemetry_otlp::new_exporter().http().with_endpoint("https://127.0.0.1:4318")
    );

    let telemetry_layer = setup_opentelemetry(config).await?;

    let subscriber = Registry::default()
        .with(telemetry_layer)
        .with(tracing_subscriber::fmt::layer());

    tracing::subscriber::set_global_default(subscriber)?;

    // Your application code here
    tracing::info!("Application started");

    Ok(())
}

自定义导出器

如果您需要使用自定义导出器,请将其作为 TelemetryConfig 部分进行配置

let custom_exporter = opentelemetry_otlp::new_exporter()
    .grpc()
    .with_endpoint("my-custom-endpoint:4317");

let config = TelemetryConfig {
    service_name: "my-service".to_string(),
    use_batch: false,
    oltp_exporter: Some(custom_exporter.into()),
    ..Default::default()
};

注意

  • 请确保您的 OpenTelemetry 收集器或后端已正确配置,以便接收来自应用程序的遥测数据。
  • 根据您的特定环境和 OpenTelemetry SDK 文档调整 OpenTelemetry 设置。

此集成使 TrasyError 成为一种强大的工具,不仅可以处理错误,还可以在分布式系统中观察和诊断它们。

当然!要将您的 Docker 设置与 Jaeger 的使用纳入 README.md,您可以为如何使用 Docker 运行 Jaeger 实例以及如何将其与应用程序连接提供详细的指南。以下是可以添加到您的 README.md 中的部分以涵盖此内容


将 Jaeger 集成到跟踪可视化中

Trasy 已配置为与分布式跟踪系统 Jaeger 无缝协作。通过使用提供的 Docker 配置,您可以轻松设置一个 Jaeger 实例来可视化从应用程序收集的跟踪。以下是开始的方法

使用 Docker 设置 Jaeger

要启动收集和可视化您应用程序跟踪数据的 Jaeger 容器,请按照以下步骤操作

  1. 确保您的系统上已安装 Docker 和 Docker Compose。有关安装说明,请参阅 DockerDocker Compose

  2. 创建一个 docker-compose.yml 文件,其内容如下

    version: '3.8'
    
    services:
      jaeger:
        image: jaegertracing/all-in-one:1.56
        container_name: jaeger
        ports:
          - "6831:6831/udp"   # Jaeger Thrift Compact Protocol
          - "6832:6832/udp"   # Jaeger Thrift Binary Protocol
          - "16686:16686"     # Jaeger UI
          - "14268:14268"     # Jaeger HTTP collector
          - "4317:4317"       # OTLP gRPC port
          - "4318:4318"       # OTLP gRPC http port
        environment:
          - COLLECTOR_OTLP_ENABLED=true
    
  3. 在您的 docker-compose.yml 文件所在目录中运行以下命令

    docker-compose up -d
    

    此命令将下载 Jaeger 图像并启动 Jaeger 服务。

将您的应用程序连接到 Jaeger

要将应用程序的跟踪发送到 Jaeger,请将 TelemetryConfig 配置为使用正确的端点。以下是一个使用 Docker 配置中提供的默认设置的示例

let config = TelemetryConfig {
    service_name: "my-awesome-service".to_string(),
    endpoint: "https://127.0.0.1:4318",
    use_batch: true,
    oltp_exporter: None, // This will use the default OTLP HTTP exporter
};

let telemetry_layer = setup_opentelemetry(config).await.expect("Failed to set up OpenTelemetry");

在 Jaeger 中查看跟踪

运行配置为将跟踪发送到 Jaeger 的应用程序后,您可以通过以下方式查看这些跟踪:

  1. 打开网页浏览器。
  2. 导航到 https://127.0.0.1:16686

此 URL 是 Jaeger UI,您可以在其中查询和可视化从您的应用程序收集的跟踪。

注意

  • 请确保 Jaeger 的 Docker 设置中的端口号与您的应用程序的遥测配置中预期的端口号匹配。
  • 如果在不同 Docker 网络或不同机器上运行,请确保应用程序和 Jaeger 服务之间的网络连接。

此设置提供了一种强大的方式来可视化和调试分布式应用程序的行为。

贡献

Trasy 欢迎贡献!以下是一些您可以贡献的方式

  • 报告错误
  • 建议改进
  • 添加更多集成和功能
  • 改进文档

请随时 fork 存储库并提交拉取请求。

依赖项

~14–30MB
~420K SLoC