Rust slog库详解-结构化日志的“艺术家”
Rust slog库详解-结构化日志的“艺术家”
- 一、Rust slog库详解-结构化日志的“艺术家”
- 1、`slog` 的核心设计理念
- 2、核心组件
- 2.1、 记录器(Logger)
- 2.2、 键值对(Key-Value Pairs)
- 2.3、 排水口(Drain)
- 3、常用生态系统
- 4、基础使用示例
- 5、高级用法
- 5.1、自定义 Drain
- 5.2、日志过滤
- 6、与现有生态集成
- 6.1、集成 `log` 兼容层
- 6.2、Web 框架集成
- 7、性能建议
- 8、总结
- 二、示例
- 1、示例一
- 2、示例二

一、Rust slog库详解-结构化日志的“艺术家”
slog 是一个结构化、可组合的异步日志库,相较于传统的 log 库,它在灵活性、性能和结构化日志方面更具优势。
1、slog 的核心设计理念
-
结构化日志
支持键值对(Key-Value)形式的日志数据,便于后续的过滤、聚合和分析。
例如:info!(logger, "用户登录成功"; "user_id" => 123, "ip" => "192.168.1.1"); -
记录器(Logger)组合
通过嵌套记录器实现日志的层级继承,避免重复传递上下文信息。 -
异步与高性能
默认采用异步方式处理日志,减少对主线程的性能影响。
2、核心组件
2.1、 记录器(Logger)
日志的入口点,通过 Logger 结构体创建:
use slog::{o, Logger, Drain};
let logger = Logger::root(drain, o!("version" => "1.0"));
2.2、 键值对(Key-Value Pairs)
使用 o! 宏定义静态字段,kv! 宏定义动态字段:
let dyn_logger = logger.new(o!("request_id" => uuid));
2.3、 排水口(Drain)
负责日志的输出处理,支持组合多个 Drain:
use slog_term::{CompactFormat, TermDecorator};
use slog_async::Async;
let decorator = TermDecorator::new().build();
let drain = CompactFormat::new(decorator).build().fuse();
let async_drain = Async::new(drain).build().fuse();
3、常用生态系统
| 组件 | 功能描述 |
|---|---|
slog-term | 终端输出(支持颜色和格式) |
slog-json | JSON 格式输出 |
slog-async | 异步日志处理 |
slog-systemd | systemd 日志集成 |
slog-gelf | Graylog 格式输出 |
4、基础使用示例
use slog::{info, o, Logger, Drain};
use slog_async;
use slog_term;
fn main() {
// 创建终端输出的 Drain
let decorator = slog_term::TermDecorator::new().build();
let drain = slog_term::CompactFormat::new(decorator).build().fuse();
let drain = slog_async::Async::new(drain).build().fuse();
// 创建根记录器
let logger = Logger::root(drain, o!("app" => "demo"));
// 记录结构化日志
info!(logger, "服务启动"; "port" => 8080);
}

5、高级用法
5.1、自定义 Drain
实现 Drain trait 以支持数据库、网络等输出:
struct CustomDrain;
impl Drain for CustomDrain {
fn log(&self, record: &Record, _values: &OwnedKV) -> io::Result<()> {
println!("自定义输出: {}", record.msg());
Ok(())
}
}
5.2、日志过滤
通过组合 Drain 实现级别过滤:
let filtered_drain = drain.filter_level(slog::Level::Info).fuse();
6、与现有生态集成
6.1、集成 log 兼容层
通过 slog-stdlog 桥接传统 log! 宏:
slog_stdlog::init().unwrap();
log::info!("传统日志将转发至 slog");
6.2、Web 框架集成
例如在 actix-web 中使用:
App::new()
.data(logger.clone())
.wrap(middleware::Logger::new());
7、性能建议
- 使用
slog-async避免阻塞主线程。 - 惰性求值:通过闭包延迟昂贵操作的计算:
debug!(logger, "数据统计"; || { kv!("avg" => calculate_avg()) });
8、总结
slog 通过结构化日志、异步处理和可组合设计解决了传统日志库的痛点,尤其适合大型分布式系统。其学习曲线较陡峭,但带来的灵活性和可扩展性值得投入。
二、示例
1、示例一
#[macro_use]
extern crate slog;
extern crate slog_term;
use std::sync::Mutex;
use slog::Drain;
struct Persion{
name: String,
age: u32
}
impl slog::Value for Persion {
fn serialize(
&self,
record: &slog::Record<'_>,
key: slog::Key,
serializer: &mut dyn slog::Serializer,
) -> slog::Result {
serializer.emit_arguments(key, &format_args!("name: {}, age: {}", self.name, self.age))
}
}
fn main() {
let decorator = slog_term::TermDecorator::new().build();
let drain = Mutex::new(slog_term::FullFormat::new(decorator).build()).fuse();
let log = slog::Logger::root(drain, o!("version" => env!("CARGO_PKG_VERSION")));
let p = Persion{
name: "John".to_string(),
age: 30
};
trace!(log, "logging a trace message");
debug!(log, "debug values"; "x" => 1, "y" => -1);
info!(log, "some interesting info"; "where" => "right here");
warn!(log, "be cautious!"; "why" => "you never know...");
error!(log, "wrong {}", "foobar"; "type" => "unknown");
crit!(log, "abandoning test");
debug!(log, "persion p"; "p" => p);
}

2、示例二
main.rs
use slog::{o, Drain, Logger, info, warn, error};
use slog_async::{Async, OverflowStrategy};
use slog_json::Json;
use slog_term::{FullFormat, TermDecorator};
use std::sync::Mutex;
use std::thread;
use std::sync::{Arc};
// 自定义数据结构
struct AppState {
request_count: Mutex<u32>,
}
fn main() {
// 创建终端输出(带颜色)
let term_decorator = TermDecorator::new().build();
let term_drain = FullFormat::new(term_decorator).build().fuse();
// 创建JSON文件输出
let json_drain = Json::new(std::io::stdout())
.add_default_keys()
.build()
.fuse();
// 组合多个输出渠道
let composite_drain = slog::Duplicate::new(term_drain, json_drain).fuse();
// 添加异步处理(避免阻塞主线程)
let async_drain = Async::new(composite_drain)
.overflow_strategy(OverflowStrategy::Block)
.build()
.fuse();
// 创建根记录器
let root_log = Logger::root(async_drain.fuse(), o!(
"version" => env!("CARGO_PKG_VERSION"),
"service" => "my_app"
));
// 创建子记录器(带额外上下文)
let request_log = root_log.new(o!("module" => "request_handler"));
// 模拟应用状态
let app_state = Arc::new(AppState {
request_count: Mutex::new(0),
});
// 模拟多线程请求处理
let handles: Vec<_> = (0..5).map(|i| {
let log = request_log.clone();
let state = app_state.clone();
thread::spawn(move || {
// 增加请求计数
let mut count = state.request_count.lock().unwrap();
*count += 1;
// 记录不同级别的日志
info!(log, "处理请求"; "request_id" => i);
warn!(log, "资源消耗较高"; "memory_usage" => "75%");
if i % 3 == 0 {
error!(log, "模拟错误"; "error_code" => "E102");
}
})
}).collect();
// 等待所有线程完成
for handle in handles {
handle.join().unwrap();
}
// 记录最终状态
info!(root_log, "服务关闭";
"total_requests" => *app_state.request_count.lock().unwrap(),
"status" => "clean_exit"
);
}
Cargo.toml
[package]
name = "tttRust"
version = "0.1.0"
edition = "2024"
[dependencies]
slog = "2.8.2"
slog-async = "2.8.0"
slog-json = "2.6.1"
slog-term = "2.9.2"
运行结果:
PS G:LearningRust ttRust> cargo run
Compiling tttRust v0.1.0 (G:LearningRust ttRust)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.57s
Running `targetdebug ttRust.exe`
Jan 23 09:31:02.032 INFO 处理请求, request_id: 1, module: request_handler, service: my_app, version: 0.1.0
{"msg":"处理请求","level":"INFO","ts":"2026-01-23T01:31:02.0348948Z","module":"request_handler","service":"my_app","version":"0.1.0","request_id":1}
Jan 23 09:31:02.035 WARN 资源消耗较高, memory_usage: 75%, module: request_handler, service: my_app, version: 0.1.0
{"msg":"资源消耗较高","level":"WARN","ts":"2026-01-23T01:31:02.0364423Z","module":"request_handler","service":"my_app","version":"0.1.0","memory_usage":"75%"}
Jan 23 09:31:02.036 INFO 处理请求, request_id: 0, module: request_handler, service: my_app, version: 0.1.0
{"msg":"处理请求","level":"INFO","ts":"2026-01-23T01:31:02.0379105Z","module":"request_handler","service":"my_app","version":"0.1.0","request_id":0}
Jan 23 09:31:02.037 WARN 资源消耗较高, memory_usage: 75%, module: request_handler, service: my_app, version: 0.1.0
{"msg":"资源消耗较高","level":"WARN","ts":"2026-01-23T01:31:02.0392461Z","module":"request_handler","service":"my_app","version":"0.1.0","memory_usage":"75%"}
Jan 23 09:31:02.039 ERRO 模拟错误, error_code: E102, module: request_handler, service: my_app, version: 0.1.0
{"msg":"模拟错误","level":"ERRO","ts":"2026-01-23T01:31:02.040559Z","module":"request_handler","service":"my_app","version":"0.1.0","error_code":"E102"}
Jan 23 09:31:02.040 INFO 处理请求, request_id: 2, module: request_handler, service: my_app, version: 0.1.0
{"msg":"处理请求","level":"INFO","ts":"2026-01-23T01:31:02.0420781Z","module":"request_handler","service":"my_app","version":"0.1.0","request_id":2}
Jan 23 09:31:02.042 WARN 资源消耗较高, memory_usage: 75%, module: request_handler, service: my_app, version: 0.1.0
{"msg":"资源消耗较高","level":"WARN","ts":"2026-01-23T01:31:02.043441Z","module":"request_handler","service":"my_app","version":"0.1.0","memory_usage":"75%"}
Jan 23 09:31:02.043 INFO 处理请求, request_id: 4, module: request_handler, service: my_app, version: 0.1.0
{"msg":"处理请求","level":"INFO","ts":"2026-01-23T01:31:02.0447079Z","module":"request_handler","service":"my_app","version":"0.1.0","request_id":4}
Jan 23 09:31:02.044 WARN 资源消耗较高, memory_usage: 75%, module: request_handler, service: my_app, version: 0.1.0
{"msg":"资源消耗较高","level":"WARN","ts":"2026-01-23T01:31:02.0459608Z","module":"request_handler","service":"my_app","version":"0.1.0","memory_usage":"75%"}
Jan 23 09:31:02.046 INFO 处理请求, request_id: 3, module: request_handler, service: my_app, version: 0.1.0
{"msg":"处理请求","level":"INFO","ts":"2026-01-23T01:31:02.047184Z","module":"request_handler","service":"my_app","version":"0.1.0","request_id":3}
Jan 23 09:31:02.047 WARN 资源消耗较高, memory_usage: 75%, module: request_handler, service: my_app, version: 0.1.0
{"msg":"资源消耗较高","level":"WARN","ts":"2026-01-23T01:31:02.0484788Z","module":"request_handler","service":"my_app","version":"0.1.0","memory_usage":"75%"}
Jan 23 09:31:02.048 ERRO 模拟错误, error_code: E102, module: request_handler, service: my_app, version: 0.1.0
{"msg":"模拟错误","level":"ERRO","ts":"2026-01-23T01:31:02.0498065Z","module":"request_handler","service":"my_app","version":"0.1.0","error_code":"E102"}
Jan 23 09:31:02.049 INFO 服务关闭, status: clean_exit, total_requests: 5, service: my_app, version: 0.1.0
{"msg":"服务关闭","level":"INFO","ts":"2026-01-23T01:31:02.0513959Z","service":"my_app","version":"0.1.0","status":"clean_exit","total_requests":5}

功能说明:
-
多输出渠道:
- 终端彩色输出(人类可读)
- JSON格式输出(机器可处理)
-
异步记录:
- 使用
slog_async避免日志写入阻塞主线程 - 设置溢出策略为阻塞(保证日志完整性)
- 使用
-
结构化日志:
- 包含版本号、服务名等全局字段
- 动态添加线程ID、请求ID等上下文
- 支持数值、字符串等多种数据类型
-
多线程支持:
- 通过
Arc安全传递日志记录器 - 线程安全的计数器实现
- 通过
-
日志分级:
info!用于常规信息warn!用于警告error!用于错误记录









