Rust日志集成库sentry-slog的使用:通过slog适配器实现与Sentry错误监控系统的无缝对接
Rust日志集成库sentry-slog的使用:通过slog适配器实现与Sentry错误监控系统的无缝对接
Sentry slog 集成库。
主要提供 SentryDrain
,它包装另一个 slog::Drain
并可以配置为将 slog::Record
转发到 Sentry。 SentryDrain
可用于创建 slog::Logger
。
该集成还支持 slog::KV
键值对。它们将分别被添加到面包屑的 data
或事件的 extra
属性中。
示例
use sentry_slog::SentryDrain;
let _sentry = sentry::init(());
let drain = SentryDrain::new(slog::Discard);
let root = slog::Logger::root(draft, slog::o!("global_kv" => 1234));
slog::info!(root, "recorded as breadcrumb"; "breadcrumb_kv" => Some("breadcrumb"));
slog::warn!(root, "recorded as regular event"; "event_kv" => "event");
let breadcrumb = &captured_event.bbreadcrumbs.as_ref()[0];
assert_eq!(
breadcrumb.message.as_deref(),
Some("recorded as breadcrumb")
);
assert_eq!(breadcrumb.data["breadcrumb_kv"], "breadcrumb");
assert_eq!(breadcrumb.data["global_kv"], 1234);
assert_eq!(
captured_event.message.as_deref(),
Some("recorded as regular event")
);
assert_eq!(captured_event.extra["event_kv"], "event");
assert_eq!(captured_event.extra["global_kv"], 1234);
slog::crit!(root, "recorded as exception event");
assert_eq!(
captured_event.message.as_deref(),
Some("recorded as exception event")
);
Drain 还可以通过 filter
和 mapper
进行定制:
use sentry_slog::{exception_from_record, LevelFilter, RecordMapping, SentryDrain};
let drain = SentryDrain::new(slog::Discard)
.filter(|level| match level {
slog::Level::Critical | slog::Level::Error => LevelFilter::Event,
_ => LevelFilter::Ignore,
})
.mapper(|record, kv| match record.level() {
slog::Level::Critical | slog::Level::Error => {
RecordMapping::Event(exception_from_record(record, kv))
}
_ => RecordMapping::Ignore,
});
当指定 mapper
时,也应提供相应的 filter
。
完整示例代码
use sentry_slog::{exception_from_record, LevelFilter, RecordMapping, SentryDrain};
use slog::{o, Discard, Logger};
use std::sync::Mutex;
fn main() {
// 初始化Sentry
let _sentry = sentry::init((
"https://your-public-key@sentry.io/your-project-id",
sentry::ClientOptions {
release: sentry::release_name!(),
..Default::default()
},
));
// 创建带过滤器和映射器的SentryDrain
let drain = SentryDrain::new(Discard)
.filter(|level| match level {
slog::Level::Critical | slog::Level::Error => LevelFilter::Event,
slog::Level::Warning => LevelFilter::Breadcrumb,
_ => LevelFilter::Ignore,
})
.mapper(|record, kv| match record.level() {
slog::Level::Critical | slog::Level::Error => {
RecordMapping::Event(exception_from_record(record, kv))
}
slog::Level::Warning => RecordMapping::Breadcrumb,
_ => RecordMapping::Ignore,
});
// 创建日志记录器
let root = Logger::root(
Mutex::new(drain).fuse(),
o!("version" => env!("CARGO_PKG_VERSION")),
);
// 记录不同级别的日志
slog::info!(root, "This is an info message"; "key" => "value");
slog::warn!(root, "This is a warning message"; "warning_key" => 42);
slog::error!(root, "This is an error message"; "error_key" => true);
slog::crit!(root, "This is a critical message"; "critical_key" => "important");
// 确保所有事件都发送到Sentry
sentry::flush(std::time::Duration::from_secs(2));
}
许可证: MIT
1 回复
Rust日志集成库sentry-slog的使用指南
sentry-slog
是一个将Rust的slog
日志系统与Sentry错误监控平台无缝集成的适配器库。它允许开发者通过现有的slog
日志基础设施将错误和日志发送到Sentry。
主要特性
- 将
slog
日志记录转发到Sentry - 支持Sentry的上下文信息(tags, extra data等)
- 与现有
slog
日志系统无缝集成 - 支持错误堆栈跟踪
使用方法
1. 添加依赖
首先,在Cargo.toml
中添加依赖:
[dependencies]
slog = "2.7"
sentry = "0.30"
sentry-slog = "0.30"
2. 基本集成示例
use slog::{info, o, Drain, Logger};
use sentry::ClientOptions;
use sentry_slog::SentryDrain;
fn main() {
// 初始化Sentry
let _sentry = sentry::init(ClientOptions {
dsn: Some("https://your-public-key@sentry.io/your-project-id".parse().unwrap()),
..Default::default()
});
// 创建slog日志记录器
let drain = SentryDrain::new(slog::Discard);
let logger = Logger::root(drain.fuse(), o!("version" => "1.0.0"));
// 记录日志
info!(logger, "Application started"; "module" => "init");
// 模拟错误
match some_operation() {
Ok(_) => info!(logger, "Operation succeeded"),
Err(e) => {
error!(logger, "Operation failed"; "error" => e.to_string());
}
}
}
fn some_operation() -> Result<(), Box<dyn std::error::Error>> {
Err("Something went wrong".into())
}
3. 高级配置
use sentry_slog::LevelFilter;
// 创建自定义的SentryDrain,只记录Warn及以上级别的日志
let sentry_drain = SentryDrain::new(slog::Discard)
.filter(|record| record.level().is_at_least(slog::Level::Warning))
.ignore_crates(&["tokio", "hyper"]); // 忽略特定crate的日志
let logger = Logger::root(sentry_drain.fuse(), o!());
4. 添加上下文信息
use sentry::configure_scope;
configure_scope(|scope| {
scope.set_tag("environment", "production");
scope.set_extra("hostname", "server-1".into());
});
info!(logger, "Processing request";
"user_id" => 42,
"request_id" => "abc123");
最佳实践
- 日志级别过滤:建议只将Warn及以上级别的日志发送到Sentry,避免产生过多噪音
- 敏感信息:不要在日志中包含敏感信息,Sentry会永久存储这些数据
- 上下文丰富:尽量为错误添加上下文信息,便于调试
- 错误分类:使用tags对错误进行分类,便于在Sentry中筛选
错误处理
sentry-slog
会自动将slog
记录的错误转换为Sentry事件。对于Rust错误类型,它会自动捕获堆栈跟踪(如果启用了backtrace)。
error!(logger, "Database operation failed";
"error" => err.to_string(),
"query" => query);
这将在Sentry中创建一个包含错误详情、堆栈跟踪和额外上下文信息的事件。
性能考虑
sentry-slog
设计为非阻塞,日志记录不会阻塞应用程序主线程。所有Sentry通信都在后台线程中处理。
通过合理配置日志级别过滤和忽略规则,可以最小化性能影响。
完整示例demo
以下是一个完整的示例,展示了如何使用sentry-slog
进行日志记录和错误监控:
use slog::{error, info, o, Drain, Logger};
use sentry::{ClientOptions, types::Dsn};
use sentry_slog::SentryDrain;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
// 1. 初始化Sentry
let dsn: Dsn = "https://your-public-key@sentry.io/your-project-id".parse()?;
let _sentry = sentry::init(ClientOptions {
dsn: Some(dsn),
release: Some("myapp@1.0.0".into()),
..Default::default()
});
// 2. 配置Sentry上下文
sentry::configure_scope(|scope| {
scope.set_tag("environment", "production");
scope.set_extra("hostname", "server-1".into());
});
// 3. 创建slog日志记录器
let base_drain = slog::Discard; // 基础drain,可以是任何slog兼容的drain
let sentry_drain = SentryDrain::new(base_drain)
.filter(|record| record.level().is_at_least(slog::Level::Warning)) // 只记录Warning及以上级别
.ignore_crates(&["tokio"]); // 忽略tokio的日志
let logger = Logger::root(
sentry_drain.fuse(),
o!("version" => "1.0.0", "service" => "myapp")
);
// 4. 记录不同级别的日志
info!(logger, "Application starting"; "module" => "init");
// 5. 模拟业务操作和错误处理
match process_request(&logger, 42) {
Ok(_) => info!(logger, "Request processed successfully"),
Err(e) => {
error!(logger, "Request processing failed";
"error" => e.to_string(),
"user_id" => 42
);
}
}
Ok(())
}
fn process_request(logger: &Logger, user_id: u64) -> Result<(), Box<dyn Error>> {
info!(logger, "Processing request"; "user_id" => user_id);
// 模拟可能失败的操作
if user_id % 2 == 0 {
Ok(())
} else {
Err("Invalid user ID".into())
}
}
这个完整示例展示了:
- Sentry的初始化和配置
- 上下文字段的设置
- slog记录器的创建和配置
- 不同级别的日志记录
- 业务操作中的错误处理和日志记录
- 结构化日志字段的使用
注意在实际使用时,需要替换Sentry DSN为你自己的项目DSN。