Secra Logger
一个生产级的 Rust 日志系统库,基于 tracing 生态系统构建。
特性
- ✅ 基于 tracing 生态,支持结构化日志
- ✅ JSON 格式输出(基于 tracing-subscriber)
- ✅ 支持控制台、文件、或同时输出
- ✅ 可配置的控制台彩色输出
- ✅ 线程安全
- ✅ 支持 log crate 桥接
- ✅ 支持 actix-web 集成
- ✅ 高性能异步写入
- ✅ 字段规范化支持(遵循 OpenTelemetry 语义约定)
- ✅ Request ID 注入支持
- ✅ Logrotate 配置生成支持
- ✅ Vector 日志收集器配置支持
安装
在 Cargo.toml 中添加依赖:
[]
= "2.0"
✨ 便捷特性:安装 secra-logger 后,您可以直接使用 tracing,无需单独添加 tracing 依赖!
// 方式1:通过 secra_logger 使用 tracing(推荐)
use ;
use ;
// 方式2:直接使用 tracing 宏(如果您的项目也添加了 tracing 依赖)
use ;
使用 tracing(无需单独添加依赖)
secra-logger 已经重新导出了 tracing,您可以直接使用:
use ;
use ;
如果需要直接使用 tracing(可选)
如果您希望直接使用 tracing crate(而不是通过 secra_logger::tracing),可以添加依赖:
使用 cargo add:
手动在 Cargo.toml 中添加:
[]
= "2.0"
= "0.1.40" # 可选:如果需要直接使用 tracing
版本说明:
secra-logger使用tracing = "^0.1.40"(兼容 0.1.x 版本)- 如果您的项目也添加了
tracing依赖,Cargo 会自动解析版本冲突,选择满足所有约束的版本 - 建议使用相同的版本约束(如
^0.1.40或0.1.40)以确保版本一致性
快速开始
基本使用
use ;
// 方式1:使用 secra_logger 重新导出的 tracing(推荐,无需单独添加 tracing 依赖)
use ;
// 方式2:如果您的项目也添加了 tracing 依赖,也可以直接使用
// use tracing::{info, error, warn, debug};
使用默认配置
use ;
use info; // 使用 secra_logger 重新导出的 tracing
结构化日志
secra-logger 完全支持 tracing 的结构化日志功能:
use ;
use info; // 使用 secra_logger 重新导出的 tracing
输出示例(JSON 格式):
错误处理
use ;
多线程使用
secra-logger 是线程安全的,可以在多线程环境中安全使用:
use ;
use thread;
use info; // 使用 secra_logger 重新导出的 tracing
Actix-Web 集成
use ;
use ;
use info; // 使用 secra_logger 重新导出的 tracing
async
使用 log crate 兼容接口
如果你需要使用传统的 log crate API,secra-logger 也提供了桥接支持:
use ;
use ;
配置说明
LoggingConfig
LoggingConfig 是日志系统的核心配置结构:
创建配置
使用 LoggingConfig::default() 创建默认配置:
let config = default;
或者手动创建配置:
use ;
let config = LoggingConfig ;
配置验证
配置对象提供了 validate() 方法用于验证配置的有效性:
let config = LoggingConfig ;
if let Err = config.validate
OutputMode
OutputMode 枚举定义了日志的输出模式:
OutputMode::File- 仅输出到文件(适合生产环境)OutputMode::Console- 仅输出到控制台(适合开发环境)OutputMode::Both- 同时输出到文件和控制台(适合需要同时查看和保存的场景)
LogFileConfig
文件输出配置:
LogConsoleConfig
控制台输出配置:
LogFieldsConfig
字段规范化配置:
字段规范化遵循 OpenTelemetry 语义约定:
- HTTP 请求:
http.method,http.path,http.status_code - 数据库:
db.system,db.name,db.operation - 服务:
service.name,service.version - 请求追踪:
trace_id,span_id,request_id - 用户:
user.id,user.email
LogrotateConfig
Logrotate 配置用于生成 logrotate 配置文件,以便系统自动管理日志文件。
注意:使用 logrotate 功能前,需要先在系统上安装 logrotate 工具。详细安装教程请参考 Logrotate 安装指南。
LogrotateConfig 配置选项说明
轮转策略:
rotate: 轮转周期(daily/weekly/monthly/yearly/size)size: 文件大小限制,当日志文件达到此大小时进行轮转minsize: 最小文件大小,小于此大小的文件不进行轮转rotate_count: 保留的日志文件数量maxage: 最大保留天数,超过此天数的旧日志将被删除start: 起始轮转编号(默认从 1 开始)
压缩选项:
compress: 是否压缩旧日志文件delaycompress: 压缩延迟(轮转后 N 个周期再压缩)compresscmd: 压缩命令(默认 gzip)uncompresscmd: 解压缩命令(默认 gunzip)compressext: 压缩文件扩展名(默认 .gz)compressoptions: 压缩选项(如 -9 表示最高压缩级别)nocompress: 是否不压缩(与 compress 相反)
文件创建:
create: 是否在轮转时创建新文件create_mode: 新文件的权限(八进制格式,如 0644)create_owner: 新文件的所有者(user:group)copy: 是否使用 copy 模式(复制原文件后截断)copytruncate: 是否使用 copytruncate 模式(复制后截断原文件)
脚本执行:
prerotate/prerotate_script: 轮转前执行的脚本postrotate/postrotate_script: 轮转后执行的脚本firstaction/firstaction_script: 第一次轮转前执行的脚本lastaction/lastaction_script: 最后一次轮转后执行的脚本sharedscripts: 是否共享脚本(多个日志文件共享一个脚本)su: 以指定用户身份运行脚本(user:group)
文件处理:
missingok: 是否忽略缺失的日志文件notifempty: 是否在日志文件为空时不轮转ifempty: 是否即使文件为空也轮转(与 notifempty 相反)olddir: 旧日志文件目录(用于将旧日志移动到指定目录)noolddir: 是否不使用 olddirextension: 压缩文件扩展名tabooext: 禁止的扩展名列表(这些扩展名的文件不会被轮转)
日期格式:
dateext: 是否使用日期扩展名(默认使用数字扩展名 .1, .2, ...)dateformat: 日期扩展名格式(默认 %Y%m%d,如 .20260114)
邮件通知:
mail: 是否发送邮件通知mailfirst: 邮件地址(轮转前发送)maillast: 是否在轮转后发送邮件nomail: 是否不发送邮件
其他选项:
include: 包含其他配置文件shred/shredcycles: 是否安全删除文件(使用 shred 命令)
VectorConfig
Vector 日志收集器配置用于生成 Vector 配置文件,以便将日志发送到各种目标(Loki、Elasticsearch、S3 等):
日志级别
支持的日志级别(从低到高):
"trace"- 最详细的调试信息"debug"- 调试信息"info"- 一般信息(推荐用于生产环境)"warn"- 警告信息"error"- 错误信息
只有等于或高于配置级别的日志才会被记录。例如,如果配置为 "info",则 "trace" 和 "debug" 级别的日志不会被记录。
也可以通过环境变量 RUST_LOG 来设置日志级别:
RUST_LOG=debug
API 参考
LoggingModule
日志模块,负责初始化日志系统。
方法
new() -> Self
创建新的 LoggingModule 实例。
init(config: Option<LoggingConfig>) -> Result<()>
初始化日志系统。
参数:
config: Option<LoggingConfig>- 日志配置,如果为None则使用默认配置
返回值:
Ok(())- 初始化成功Err(anyhow::Error)- 初始化失败
说明:
- 此方法会设置全局 tracing subscriber
- 如果全局 subscriber 已经设置(例如在测试中),会记录警告但继续执行
- 文件写入器的
WorkerGuard会被保存,确保日志能够正确刷新
shutdown()
关闭日志系统,清理资源。
Logger
Logger 组件,用于标识日志系统已初始化。
;
在实际使用中,通过 tracing 宏直接记录日志,无需通过 Logger 组件。此组件主要用于标识日志系统已初始化。
运行示例
项目提供了多个示例来演示不同的使用场景:
# 运行基本示例(展示基本日志记录功能)
# 运行文件滚动测试示例(测试文件滚动机制)
# 运行路径测试示例(测试目录和文件路径配置)
# 运行目录路径测试示例
# 运行 span 和 event 示例
# 运行 actix-web 集成示例(需要 actix-web 依赖)
运行示例后,可以在 ./logs/ 目录下查看生成的日志文件。
最佳实践
1. 日志级别选择
- 开发环境:使用
"debug"或"trace"获取详细调试信息 - 生产环境:使用
"info"或"warn",避免过多日志影响性能 - 关键服务:使用
"warn",只记录警告和错误
2. 输出模式选择
- 开发环境:使用
OutputMode::Console或OutputMode::Both,方便查看日志 - 生产环境:使用
OutputMode::File,避免控制台输出影响性能 - 容器环境:使用
OutputMode::Both,文件用于持久化,stdout 用于容器日志收集
3. 结构化日志
充分利用结构化日志的优势:
// 好的做法:使用结构化字段
info!;
// 避免:只使用格式化字符串
info!;
4. 错误处理
始终处理初始化错误:
match logging_module.init
5. 多线程环境
secra-logger 是线程安全的,可以在多线程环境中直接使用,无需额外同步:
use thread;
// 多个线程可以安全地同时记录日志
for i in 0..10
6. Request ID 注入
启用 enable_request_id 后,可以在日志中自动注入 Request ID,方便追踪请求链路。
7. 字段规范化
启用字段规范化后,日志字段会遵循 OpenTelemetry 语义约定,便于日志分析和监控系统集成。
性能考虑
- 异步写入:日志写入是异步的,不会阻塞主线程
- 批量刷新:日志会批量刷新到磁盘,提高性能
- 线程安全:使用高性能锁(
parking_lot),多线程环境下性能优秀 - JSON 序列化:使用高效的 JSON 序列化库,性能开销小
常见问题
Q: 为什么日志文件没有创建?
A: 确保日志路径的父目录存在且有写权限。如果父目录不存在,日志系统会尝试创建,但需要相应的权限。
Q: 如何更改日志级别?
A: 可以在配置中设置 level 字段,或者通过环境变量 RUST_LOG 来设置。环境变量的优先级更高。
Q: 可以在运行时更改日志级别吗?
A: 当前版本不支持运行时更改配置。需要在初始化时设置好日志级别。如果需要动态调整,可以考虑使用 tracing-subscriber 的 EnvFilter。
Q: 日志格式可以自定义吗?
A: 当前版本使用固定的 JSON 格式。如果需要自定义格式,可以修改 module.rs 中的格式化逻辑。
Q: 如何集成到现有的 tracing 系统中?
A: secra-logger 使用标准的 tracing-subscriber,可以与其他 subscriber 组合使用。但需要注意,多次调用 init 可能会失败(如果全局 subscriber 已经设置)。
Q: 如何使用 Logrotate 配置?
A: 在 LogFileConfig 中设置 logrotate 字段,配置相应的参数。然后可以使用生成的 logrotate 配置文件来管理日志文件。
安装 logrotate:如果系统上尚未安装 logrotate,请参考 Logrotate 安装指南 进行安装。支持在线安装和离线安装两种方式。
Q: 如何使用 Vector 配置?
A: 在 LoggingConfig 中设置 vector 字段,配置相应的源、转换和目标。然后可以使用生成的 Vector 配置文件来收集和转发日志。
依赖
主要依赖:
tracing- 结构化日志框架tracing-subscriber- 订阅者实现tracing-log- log crate 桥接tracing-appender- 异步日志写入parking_lot- 高性能锁实现chrono/chrono-tz- 日期时间处理once_cell- 全局初始化状态管理serde/serde_json- 序列化支持anyhow- 错误处理thiserror- 错误类型定义
版本历史
1.0.4
- 优化依赖管理,将仅用于开发和示例的依赖移动到
dev-dependencies - 减少生产依赖大小
1.0.3
- 优化文件滚动逻辑
- 改进错误处理
- 添加
span_event示例
1.0.2
- 修复 let chains 语法以兼容 Rust 2021 edition
1.0.1
- 发布稳定版本,标志着项目进入生产就绪状态
0.3.0
- 大幅简化代码结构
- 重构日志写入架构
- 优化文件写入性能
贡献
欢迎提交 Issue 和 Pull Request!
许可证
MIT License
Copyright (c) 2024 Secra Team
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.