Rust结构化日志库structured-logger的使用,高效记录和管理应用程序日志的Rust插件库
Rust结构化日志库structured-logger的使用,高效记录和管理应用程序日志的Rust插件库
概述
structured-logger是一个用于log crate的日志记录实现,可以同步或异步地记录结构化值,以JSON、CBOR或其他格式输出到文件、stderr、stdout或其他目的地。它受到了std-logger的启发。
示例代码
以下是内容中提供的简单示例:
use serde::Serialize;
use structured_logger::{async_json::new_writer, unix_ms, Builder};
#[tokio::main]
async fn main() {
// 初始化日志记录器
Builder::with_level("info")
.with_target_writer("*", new_writer(tokio::io::stdout()))
.init();
// 或者使用默认配置:
// structured_logger::init();
let kv = ContextLog {
uid: "user123".to_string(),
action: "upate_book".to_string(),
};
log::info!("hello world");
// 这个日志会输出到stdout:
// {"level":"INFO","message":"hello world","target":"simple","timestamp":1679745592127}
log::info!(target: "api",
method = "GET",
path = "/hello",
status = 200_u16,
start = unix_ms(),
elapsed = 10_u64,
kv:serde = kv;
"",
);
// 这个日志会输出到stdout:
// {"elapsed":10,"kv":{"uid":"user123","action":"upate_book"},"level":"INFO","message":"","method":"GET","path":"/hello","start":1679745592127,"status":200,"target":"api","timestamp":1679745592127}
}
#[derive(Serialize)]
struct ContextLog {
uid: String,
action: String,
}
完整示例
基于上述内容,这里提供一个更完整的示例:
use serde::Serialize;
use structured_logger::{async_json::new_writer, unix_ms, Builder};
use tokio::fs::File;
#[derive(Serialize)]
struct UserActivity {
user_id: String,
action: String,
duration_ms: u64,
}
#[tokio::main]
async fn main() {
// 初始化日志记录器,同时输出到stdout和文件
let log_file = File::create("app.log").await.unwrap();
Builder::with_level("info")
// 所有日志目标都输出到stdout
.with_target_writer("*", new_writer(tokio::io::stdout()))
// 仅api目标的日志输出到文件
.with_target_writer("api", new_writer(log_file))
.init();
// 模拟用户活动
let activity = UserActivity {
user_id: "user_789".to_string(),
action: "view_profile".to_string(),
duration_ms: 125,
};
// 普通日志消息
log::info!("Application started");
// 带有结构化数据的API访问日志
log::info!(
target: "api",
method = "POST",
path = "/api/user",
status = 201_u16,
processing_time = 45_u64,
user_activity:serde = activity;
"User profile accessed"
);
// 错误日志示例
log::error!(
target: "auth",
user_id = "user_789",
error_code = "AUTH_403",
ip = "192.168.1.100";
"Unauthorized access attempt"
);
}
特性
- 结构化日志记录:支持以结构化格式(如JSON)记录日志,便于后续处理和分析
- 多种输出目标:可以输出到stdout、stderr、文件或其他自定义目标
- 异步支持:提供异步日志记录能力,减少对应用程序性能的影响
- 灵活配置:可以根据日志目标(target)设置不同的输出方式和格式
- 自定义字段:支持添加任意数量的自定义字段到日志记录中
安装
将以下内容添加到你的Cargo.toml文件中:
[dependencies]
structured-logger = "1.0.4"
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
许可证
该项目采用双重许可证:
- MIT许可证
- Apache-2.0许可证
你可以根据需求选择其中一种。
1 回复
Rust结构化日志库structured-logger使用指南
介绍
structured-logger
是一个Rust的结构化日志记录库,它提供了高效、灵活的日志记录功能,特别适合需要结构化日志输出的应用程序。与传统的文本日志不同,结构化日志以键值对的形式记录数据,便于后续的日志分析和处理。
主要特性
- 支持结构化日志记录
- 高性能日志记录
- 可定制的日志格式
- 支持异步日志记录
- 多种日志级别控制
- 易于与现有日志系统集成
安装
在Cargo.toml中添加依赖:
[dependencies]
structured-logger = "0.4"
log = "0.4"
基本使用方法
1. 初始化日志记录器
use structured_logger::{async_json::new_writer, Builder};
use log::LevelFilter;
fn init_logger() {
// 使用Builder创建日志记录器,设置日志级别为Info
// 将所有目标的日志输出到标准输出(stdout)
Builder::with_level(LevelFilter::Info)
.with_target_writer("*", new_writer(std::io::stdout()))
.init();
}
2. 记录日志
use log::{info, warn, error};
fn main() {
// 初始化日志记录器
init_logger();
// 记录结构化日志
info!(target: "my_app",
event = "startup", // 自定义字段
version = env!("CARGO_PKG_VERSION"), // 获取Cargo版本号
"Application starting"); // 日志消息
// 记录警告日志
warn!(
user_id = 12345,
action = "login",
"User attempted login with expired token"
);
// 记录错误日志
error!(
error = "Database connection failed",
retry_count = 3,
"Critical operation failed"
);
}
3. 输出示例
上述代码会产生类似如下的结构化日志:
{
"timestamp": "2023-05-15T12:34:56.789Z",
"level": "INFO",
"target": "my_app",
"message": "Application starting",
"event": "startup",
"version": "1.0.0"
}
{
"timestamp": "2023-05-15T12:34:56.790Z",
"level": "WARN",
"message": "User attempted login with expired token",
"user_id": 12345,
"action": "login"
}
高级用法
自定义日志格式
use structured_logger::{Builder, unix_ms};
fn init_custom_logger() {
// 创建自定义格式的日志记录器
Builder::with_level("info")
.with_default_writer(|_| {
Box::new(|record| {
// 自定义日志格式:[时间戳][日志级别][目标] 键值对 - 消息
println!(
"[{}][{}][{}] {} - {}",
unix_ms(), // 获取当前UNIX时间戳(毫秒)
record.level(), // 日志级别
record.target(), // 日志目标
record.key_values(), // 键值对
record.args() // 日志消息
);
})
})
.init();
}
异步日志记录
use structured_logger::{async_json::new_writer, Builder};
use log::LevelFilter;
#[tokio::main]
async fn main() {
// 使用异步日志记录器,输出到标准输出
Builder::with_level(LevelFilter::Info)
.with_target_writer("*", new_writer(tokio::io::stdout()))
.init();
// 异步记录日志
log::info!("This log will be written asynchronously");
}
文件日志记录
use structured_logger::{async_json::new_writer, Builder};
use log::LevelFilter;
use std::fs::File;
fn init_file_logger() {
// 创建日志文件
let file = File::create("app.log").expect("Failed to create log file");
// 初始化文件日志记录器
Builder::with_level(LevelFilter::Info)
.with_target_writer("*", new_writer(file))
.init();
}
性能建议
- 对于高性能应用,使用异步日志记录
- 避免在日志宏中执行复杂计算
- 在生产环境中适当调整日志级别
- 考虑使用缓冲写入器减少I/O操作
与其他日志系统的集成
structured-logger
可以与log
生态系统中的其他工具一起使用:
use env_logger;
use structured_logger;
fn init_combined_logger() {
// 初始化env_logger用于开发环境
env_logger::init();
// 初始化structured_logger用于生产环境
structured_logger::Builder::with_level("info")
.with_default_writer(structured_logger::json::new_writer(std::io::stdout()))
.init_quiet();
}
完整示例Demo
下面是一个完整的应用程序示例,展示了如何使用structured-logger
记录不同类型的日志:
use structured_logger::{async_json::new_writer, Builder};
use log::{info, warn, error, debug};
use std::time::Duration;
use std::thread;
fn init_logger() {
// 初始化日志记录器,设置日志级别为Debug
Builder::with_level(log::LevelFilter::Debug)
.with_target_writer("*", new_writer(std::io::stdout()))
.init();
}
fn perform_operation(user_id: u64) -> Result<(), String> {
// 模拟一些业务逻辑
if user_id % 2 == 0 {
Ok(())
} else {
Err("Operation failed for odd user ID".to_string())
}
}
fn main() {
// 初始化日志系统
init_logger();
info!(
target: "app_startup",
version = env!("CARGO_PKG_VERSION"),
"Starting application"
);
// 模拟用户操作
for user_id in 1..=5 {
debug!(
user_id = user_id,
"Processing user request"
);
thread::sleep(Duration::from_millis(100));
match perform_operation(user_id) {
Ok(_) => info!(
user_id = user_id,
status = "success",
"Operation completed"
),
Err(e) => error!(
user_id = user_id,
status = "failed",
error = e,
"Operation failed"
),
}
}
warn!(
notice = "shutdown",
"Application shutting down"
);
}
输出示例:
{
"timestamp": "2023-05-15T12:34:56.789Z",
"level": "INFO",
"target": "app_startup",
"message": "Starting application",
"version": "1.0.0"
}
{
"timestamp": "2023-05-15T12:34:56.790Z",
"level": "DEBUG",
"message": "Processing user request",
"user_id": 1
}
{
"timestamp": "2023-05-15T12:34:56.890Z",
"level": "ERROR",
"message": "Operation failed",
"user_id": 1,
"status": "failed",
"error": "Operation failed for odd user ID"
}
{
"timestamp": "2023-05-15T12:34:56.890Z",
"level": "DEBUG",
"message": "Processing user request",
"user_id": 2
}
{
"timestamp": "2023-05-15T12:34:56.990Z",
"level": "INFO",
"message": "Operation completed",
"user_id": 2,
"status": "success"
}
{
"timestamp": "2023-05-15T12:34:57.090Z",
"level": "WARN",
"message": "Application shutting down",
"notice": "shutdown"
}
structured-logger
是一个强大而灵活的工具,特别适合需要结构化日志的现代应用程序。通过键值对的形式记录日志数据,可以大大简化日志分析和监控的复杂度。