Rust日记纪录 - tracing [复制链接]
发表于 前天 07:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
tracing 是 Rust 生态中用于布局化日记纪录与分布式追踪的今世化框架,由 Tokio 团队开发维护,扩展了传统日记功能,提供了关于时序性因果关系的额外信息。
添加依赖
  1. cargo add tracing             # 核心框架
  2. cargo add tracing-subscriber --features env-filter,fmt # 日志订阅与处理
  3. cargo add tracing-appender    # 文件输出与轮转
复制代码
常用特性分析:

  • env-filter:通过环境变量设置日记过滤规则
  • fmt:提供格式化输出(文本 / JSON)
  • json:支持 JSON 格式输出
  • chrono:使用更友爱的时间格式
初始化 Subscriber

Subscriber 是 tracing 的日记处置惩罚器,负责网络和输出日记数据。你可以把它明白为日记的"输出目的地"。常见的 Subscriber 包罗将日记写入标准输出、生存到文件、发送到日记网络体系如 ELK Stack 或 Jaeger。
Subscriber 负责格式化 Span 和 Event 数据,并决定哪些日记应该被纪录(根据日记级别过滤)。
示例,默认初始化:
  1. use tracing::Level;
  2. use tracing_subscriber;
  3. fn main() {
  4.     // 初始化 Subscriber,输出到 stdout,
  5.     // 从RUST_LOG 环境变量读取日志过滤级别,如未设置,默认为 ERROR 级别
  6.     tracing_subscriber::fmt::init();
  7. }
复制代码
示例,纪录日记到文件,按日轮转,同时也输出到控制台。
  1. use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
  2. fn main() {
  3.         let _guard = init_logging()
  4.     // 测试记录
  5.     tracing::info!("系统启动,开始记录日志到文件...");
  6.     for i in 0..5 {
  7.         tracing::debug!(id = i, "正在处理任务");
  8.     }
  9. }
  10. fn init_logging() -> tracing_appender::non_blocking::WorkerGuard {
  11.     // 1. 设置日志文件存放目录和文件名前缀
  12.     let directory = "logs";
  13.     let file_name_prefix = "app.log";
  14.     // 2. 配置每日滚动 (Daily Rotation)
  15.     let file_appender = tracing_appender::rolling::daily(directory, file_name_prefix);
  16.     // 3. 构造非阻塞写入器 (Non-blocking writer)
  17.     // guard 必须在 main 中持有,如果它被丢弃,日志缓冲区的内容可能无法写入文件
  18.     let (non_blocking_writer, guard) = tracing_appender::non_blocking(file_appender);
  19.     // 4. 将文件输出与控制台输出结合
  20.     tracing_subscriber::registry()
  21.         // 过滤器:从环境变量 RUST_LOG 读取,默认为 info
  22.         .with(EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")))
  23.         // 终端输出层
  24.         .with(fmt::layer().with_writer(std::io::stdout))
  25.         // 文件输出层(这里可以设置是否需要 ANSI 颜色,存文件建议关掉)
  26.         .with(
  27.             fmt::layer()
  28.                 .with_ansi(false)
  29.                 .with_writer(non_blocking_writer)
  30.         )
  31.         .init();
  32.     return guard;
  33. }
复制代码
纪录Event

Event 代表一个具体的时间点变乱。使用 event! 宏纪录变乱。
  1. use tracing::{event, Level};
  2. event!(Level::INFO, "something has happened!");
复制代码
tracing提供了一组与event!雷同但已指定了Level 参数的宏,与 log 库中的宏同名:
  1. trace!("跟踪信息:变量 x = {}", x);
  2. debug!("调试信息:计算结果 = {}", result);
  3. info!("普通信息:处理请求 {}", request_id);
  4. warn!("警告信息:缓存命中率较低");
  5. error!("错误信息:数据库连接失败");
复制代码
布局化日记(Structured Logging)

tracing 的强大之处在于你可以像写 JSON 一样纪录变量,而不是拼接字符串。这对于后期在 ELK 或 Datadog 中检索极其方便。
  1. let user = "Alice";
  2. let user_id = 42;
  3. // 推荐做法:使用字段名
  4. info!(user = %user, id = ?user_id, "用户登录成功");
  5. // 注释:
  6. // % 表示调用 Display 格式化
  7. // ? 表示调用 Debug 格式化
复制代码
创建Span

在异步代码中,相干的变乱和日记行会相互肴杂,使得追踪逻辑流程变得困难。为此,tracing 引入了 span 的概念。与代表一个时间点的日记行差别,span 代表一个有开始和竣事的时间段。span 内的 Event将关联到此 span,使得变乱可以追溯到其产生的上下文环境。
  1. use tracing::{info, span, Level};
  2. use tracing_subscriber;
  3. fn main() {
  4.     // 1. 初始化默认订阅者
  5.     tracing_subscriber::fmt()
  6.         .with_max_level(Level::INFO)
  7.         .init();
  8.     // 3. 创建并进入一个 Span
  9.     let main_span = span!(Level::INFO, "my_span");
  10.     let _enter = main_span.enter(); // 进入 Span,在此之后的日志都会带上该 Span 的信息
  11.     info!("这条日志是在 Span 内部产生的");
  12. } // _enter 离开作用域,Span 自动关闭
复制代码
#[instrument]

#[instrument] 是 tracing 提供的一个过程宏,可以主动为函数创建 Span。使用这个宏,你无需手动编写 Span 的创建和进入代码。
  1. use tracing::{info, instrument};
  2. #[instrument] // 自动创建一个名为 "calculate" 的 Span,并记录 a 和 b 的值
  3. async fn calculate(a: u32, b: u32) -> u32 {
  4.     info!("计算中...");
  5.     a + b
  6. }
  7. #[tokio::main]
  8. async fn main() {
  9.     tracing_subscriber::fmt::init();
  10.     calculate(10, 20).await;
  11. }
复制代码
#[instrument] 常用参数:

  • level:设置 span 级别(默认 INFO)
  • name:自界说 span 名称
  • skip/skip_all:跳过某些参数纪录
  • fields:添加额外布局化字段
  • ret:纪录函数返回值

免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金.
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表