Rust日志追踪库tracing-gum的使用:高效灵活的日志记录与诊断工具
Rust日志追踪库tracing-gum的使用:高效灵活的日志记录与诊断工具
tracing-gum简介
tracing-gum是一个将tracing::{warn,info,..}
和mick-jaeger
粘合在一起的库,可以零代码修改地在Grafana中实现交叉引用。
使用场景
在Grafana Loki和Tempo中交叉引用span和日志时,需要一个共享的traceID
或TraceIdentifier
。所有日志都必须标注这样的元信息。
在大多数情况下,CandidateHash
是jaeger::Span
的主要标识符,因此也是traceID
的来源。对于它不是主要标识符的情况,会添加一个名为traceID
的辅助标签(已作为便利措施存在)。
决策原因
为了避免在每个包含candidate_hash
的tracing行上添加大约2行代码来从中派生TraceIdentifier
,并将其作为tracing::*
宏的键值部分打印出来,引入了一个proc-macro来抽象化这个过程。
使用方式
在使用日志宏(warn!
、info!
等)时,只需将CandidateHash
命名为candidate_hash
即可。为了区分,使用前缀gum::
。
示例代码
use tracing_gum::{gum, info};
fn main() {
// 初始化tracing subscriber
tracing_subscriber::fmt().init();
let candidate_hash = "abc123".to_string();
// 使用gum宏记录日志
gum::info!(
candidate_hash = candidate_hash,
"Processing candidate with hash"
);
// 也可以使用标准tracing语法
info!(
candidate_hash = candidate_hash,
"Another log message with candidate hash"
);
// 带额外字段的日志
gum::warn!(
candidate_hash = candidate_hash,
duration_ms = 42,
"Operation took longer than expected"
);
}
完整示例
use tracing_gum::{gum, info, warn, debug};
use tracing_subscriber::{fmt, EnvFilter};
fn process_data(candidate_hash: String) {
// 模拟数据处理
gum::debug!(
candidate_hash = candidate_hash,
"Starting data processing"
);
// 模拟耗时操作
std::thread::sleep(std::time::Duration::from_millis(50));
// 记录处理结果
gum::info!(
candidate_hash = candidate_hash,
processed_items = 42,
"Successfully processed data"
);
}
fn main() {
// 设置日志过滤器,只显示info及以上级别的日志
fmt()
.with_env_filter(EnvFilter::from_default_env()
.add_directive("info".parse().unwrap()))
.init();
let candidates = vec![
"hash1".to_string(),
"hash2".to_string(),
"hash3".to_string()
];
for hash in candidates {
process_data(hash);
}
// 模拟错误情况
gum::error!(
candidate_hash = "special_hash".to_string(),
error_code = 500,
"Failed to process special candidate"
);
}
注意事项
- 需要在Cargo.toml中添加依赖:
[dependencies]
tracing-gum = "21.0.0"
tracing-subscriber = "0.3"
-
该库需要在整个代码库中一致使用才能正常工作
-
不追求与
tracing::{warn!,..}
完全相同的功能,更注重一致性 -
所有当前使用的功能在gum中也都支持
Rust日志追踪库tracing-gum的使用:高效灵活的日志记录与诊断工具
介绍
tracing-gum
是一个基于Rust tracing
生态系统的日志记录库,它提供了更简洁、更灵活的API来记录结构化日志。这个库特别适合需要详细诊断信息的应用程序,同时保持了高性能和低开销的特点。
完整示例demo
下面是一个结合了tracing-gum各个功能的完整示例:
// 引入必要的模块
use tracing_gum::{Gum, info, warn, error, debug, trace, instrument};
use std::error::Error;
// 定义一个用户结构体
#[derive(Debug)]
struct User {
id: u64,
name: String,
email: String,
}
// 带有instrument宏的函数
#[instrument]
fn register_user(name: &str, email: &str) -> Result<User, Box<dyn Error>> {
debug!("开始注册用户");
if name.is_empty() {
warn!("用户名不能为空");
return Err("无效用户名".into());
}
if !email.contains('@') {
warn!("无效的邮箱格式");
return Err("无效邮箱".into());
}
let user = User {
id: 1,
name: name.to_string(),
email: email.to_string(),
};
info!(
user_id = user.id,
user_name = %user.name,
"用户注册成功",
details = ?user
);
Ok(user)
}
// 敏感操作函数
#[instrument(skip(password))]
fn login(username: &str, password: &str) -> bool {
debug!("尝试登录");
username == "admin" && password == "123456"
}
fn main() -> Result<(), Box<dyn Error>> {
// 初始化日志收集器
Gum::builder()
.with_level(tracing::Level::DEBUG)
.with_ansi(true)
.init();
// 处理用户注册
match register_user("张三", "zhangsan@example.com") {
Ok(user) => {
info!("主函数中收到用户: {:?}", user);
}
Err(e) => {
error!(error = %e, "用户注册失败");
}
}
// 模拟登录
if login("admin", "123456") {
info!("管理员登录成功");
} else {
warn!("登录失败");
}
// 性能敏感场景
debug!(
result = %tracing::field::debug(expensive_operation()),
"调试信息"
);
Ok(())
}
// 耗时的操作
fn expensive_operation() -> String {
std::thread::sleep(std::time::Duration::from_millis(100));
"expensive result".to_string()
}
#[cfg(test)]
mod tests {
use super::*;
use tracing_gum::Gum;
use tracing_gum::test_helpers::*;
#[test]
fn test_register_user() {
let _guard = Gum::test_init();
let result = register_user("test", "test@example.com");
assert!(result.is_ok());
assert_logged!("开始注册用户");
assert_logged_with_level!(tracing::Level::INFO, "用户注册成功");
}
}
示例说明
-
初始化配置:
- 使用
Gum::builder()
自定义日志级别和ANSI彩色输出
- 使用
-
结构化日志:
User
结构体使用Debug
派生,可以方便地记录整个结构体- 使用
info!
宏记录结构化的用户信息
-
跨函数追踪:
register_user
函数使用#[instrument]
宏自动记录调用信息login
函数使用skip
参数跳过敏感字段的记录
-
错误处理:
- 使用
error!
宏记录错误信息 - 结合Rust的错误处理机制
- 使用
-
性能优化:
expensive_operation
使用延迟评估,避免不必要的计算
-
测试集成:
- 测试中使用
Gum::test_init()
捕获日志 - 使用
assert_logged!
宏验证日志输出
- 测试中使用
这个示例展示了tracing-gum在真实场景中的典型用法,包括初始化、结构化日志、跨函数追踪、错误处理和测试集成等功能。