跳到主要内容

日志框架

问题

Rust 常用的日志方案有哪些?logtracing 有什么区别?

答案

log:简单日志

log 是 Rust 的日志门面(facade),类似 Java 的 SLF4J。

use log::{info, warn, error, debug, trace};

fn main() {
env_logger::init(); // 初始化后端

info!("服务启动,端口: {}", 8080);
warn!("配置未找到,使用默认值");
error!("数据库连接失败: {}", "timeout");
debug!("请求详情: {:?}", request);
}

tracing:结构化可观测

tracinglog 的演进,支持结构化日志 + 分布式追踪,是 async Rust 的首选方案。

use tracing::{info, warn, instrument, span, Level};
use tracing_subscriber;

// #[instrument] 自动创建 span,记录函数参数
#[instrument(skip(password))] // 跳过敏感字段
async fn login(username: &str, password: &str) -> Result<String, Error> {
info!(username, "开始登录");

let user = db::find_user(username).await?;
info!(user_id = user.id, "登录成功");

Ok(user.token)
}

fn main() {
// 初始化订阅者
tracing_subscriber::fmt()
.with_max_level(Level::DEBUG)
.with_target(false)
.json() // JSON 格式输出
.init();
}

log vs tracing

特性logtracing
结构化日志✅ 原生支持
Span(跨度)✅ 追踪请求链路
async 支持基础✅ 原生支持
性能快(零成本 span)
生态成熟快速增长
推荐场景简单 CLI、库Web 服务、微服务
选择建议
  • 写库:用 log(更轻量,兼容 tracing)
  • 写应用:用 tracing(功能更强,支持 OpenTelemetry)

常见面试问题

Q1: tracing 的 span 有什么用?

答案

Span 表示一个逻辑操作的持续时间,可以嵌套形成树形结构。在 async 环境中,span 会跟随 Future 跨线程传播,实现分布式追踪。搭配 tracing-opentelemetry 可将 span 导出到 Jaeger/Zipkin。

Q2: 如何在生产环境配置日志?

答案

use tracing_subscriber::{fmt, EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};

tracing_subscriber::registry()
.with(EnvFilter::from_default_env()) // RUST_LOG 环境变量控制级别
.with(fmt::layer().json()) // JSON 格式
.init();

通过 RUST_LOG=my_app=debug,tower=warn 精细控制各模块日志级别。

相关链接