Rust 的高效易用日志库 — tklog


很多人习惯于python,go等语言基础工具库的简单易用;在使用rust时,可能感觉比较麻烦,类似日志库这样的基础性工具库。tklog提供用法上,非常类似python等Logger的日志库用法,用法简洁;基于rust的高效性和一些优化策略,tklog的性能非常好,在压测中,可以达到 3-4 µs/op (微妙/次),这个效率比go最高的性能时候都高一些;在相同的环境下,对go进行无格式日志输出压测,可以达到 3-4µs/op,如果是格式化日志输出,则为4µs/op以上。(可以参考《 高性能日志库go-logger v2.0.3》中对各日志库的压测数据)。
在异步场景中,tklog提供了对应的方法,支持异步调用。异步方法最大的好处并非在性能上,而是它不会阻塞所在线程。但是由于 tklog的常规日志方法默认使用延迟策略,实际上也不会阻塞所在线程,或者准确说影响非常小,可以忽略不计。所以,异步场景一般也可以直接使用常规日志打印方法。

相关连接

  • 项目源码
  • 官网
  • 仓库

项目引入

[dependencies]
tklog = "0.0.2" #使用时的实际最新版本;当前0.0.2版本

tklog是rust高性能结构化日志库

易用,高效,结构化,控制台日志,文件日志,文件切割,文件压缩,同步打印,异步打印


功能

  • 功能支持:控制台日志,文件日志,同步日志,异步日志
  • 日志级别设置:提供与标准库同级别日志打印: trace,debug,info,warn,error,fatal
  • 格式化输出:支持自定义日志的输出格式,包括日志级别标识、格式化时间、日志文件位置 等元素,并支持自定义格式调整。
  • 按时间文件切割:按小时,天,月份切割日志文件
  • 按大小文件切割:按指定大小切割日志文件
  • 文件数回滚:指定最大备份文件数,支持自动删除旧日志文件,并防止日志文件数过多。
  • 文件压缩:支持压缩归档备份日志文件。

使用方法简述

最简单常用的方法:直接调用

use tklog::{trace,debug, error, fatal, info,warn}
fn testlog() {
trace!("trace>>>>", "aaaaaaaaa", 1, 2, 3, 4);
debug!("debug>>>>", "bbbbbbbbb", 1, 2, 3, 5);
info!("info>>>>", "ccccccccc", 1, 2, 3, 5);
warn!("warn>>>>", "dddddddddd", 1, 2, 3, 6);
error!("error>>>>", "eeeeeeee", 1, 2, 3, 7);
fatal!("fatal>>>>", "ffffffff", 1, 2, 3, 8);
}

说明:默认打开控制台日志,没有写日志文件。打印结果:

[TRACE] 2024-05-26 11:47:22 testlog.rs 27:trace>>>>,aaaaaaaaa,1,2,3,4
[DEBUG] 2024-05-26 11:47:22 testlog.rs 28:debug>>>>,bbbbbbbbb,1,2,3,5
[INFO] 2024-05-26 11:47:22 testlog.rs 29:info>>>>,ccccccccc,1,2,3,5
[WARN] 2024-05-26 11:47:22 testlog.rs 30:warn>>>>,dddddddddd,1,2,3,6
[ERROR] 2024-05-26 11:47:22 testlog.rs 31:error>>>>,eeeeeeee,1,2,3,7
[FATAL] 2024-05-26 11:47:22 testlog.rs 32:fatal>>>>,ffffffff,1,2,3,8

说明:直接调用 debug!等宏进行打印,默认调用全局静态LOG对象。LOG对象支持初始化。

use tklog::{
sync::Logger,
LEVEL, LOG,
Format,MODE,
};

fn log_init() {
LOG.set_console(true)//设置控制台日志
.set_level(LEVEL::Info)//日志级别,默认Debug
.set_format(Format::LevelFlag | Format::Time | Format::ShortFileName)//结构化日志,定义输出的日志信息
.set_cutmode_by_size("tklogsize.txt", 1<<20, 10, true)//日志文件切割模式为文件大小,每1M文件切分一次,保留10个备份日志文件,并压缩备份日志
.set_formatter("{level}{time} {file}:{message}") //自定义日志输出格式。默认:{level}{time} {file}:{message}
}

fn testlog() {
log_init()//调用初始化方法
trace!("trace>>>>", "aaaaaaaaa", 1, 2, 3, 4); //track日志级别小于设置的LEVEL::Info ,故无输出
info!("info>>>>", "ccccccccc", 1, 2, 3, 5);
}

以上是全局单实例打印的示例。tklog支持自定义多实例打印。多实例一般应用在系统要求不同打印结构的场景中。

多实例打印

use tklog::{
debugs, errors, fatals, infos,
sync::Logger,
LEVEL, LOG,
traces, warns, Format, MODE,
};
fn testmutlilog() {
let mut log = Logger::new();
log.set_console(true)
.set_level(LEVEL::Debug) //定义日志级别为Debug
.set_cutmode_by_time("tklogs.log", MODE::DAY, 10, true) //分割日志文件的方式为按天分割,保留最多10个备份,并压缩备份文件
.set_formatter("{message} | {time} {file}{level}") //自定义日志结构信息的输入顺序与附加内容

let mut logger = Arc::clone(&Arc::new(Mutex::new(log)));
let log = logger.borrow_mut();
traces!(log, "traces>>>>", "AAAAAAAAA", 1, 2, 3, 4);
debugs!(log, "debugs>>>>", "BBBBBBBBB", 1, 2, 3, 5);
infos!(log, "infos>>>>", "CCCCCCCCC", 1, 2, 3, 5);
warns!(log, "warns>>>>", "DDDDDDDDDD", 1, 2, 3, 6);
errors!(log, "errors>>>>", "EEEEEEEE", 1, 2, 3, 7);
fatals!(log, "fatals>>>>", "FFFFFFFF", 1, 2, 3, 8);

thread::sleep(Duration::from_secs(1))
}

执行结果:

debugs>>>>,BBBBBBBBB,1,2,3,5 | 2024-05-26 14:13:25 testlog.rs 70[DEBUG]
infos>>>>,CCCCCCCCC,1,2,3,5 | 2024-05-26 14:13:25 testlog.rs 71[INFO]
warns>>>>,DDDDDDDDDD,1,2,3,6 | 2024-05-26 14:13:25 testlog.rs 72[WARN]
errors>>>>,EEEEEEEE,1,2,3,7 | 2024-05-26 14:13:25 testlog.rs 73[ERROR]
fatals>>>>,FFFFFFFF,1,2,3,8 | 2024-05-26 14:13:25 testlog.rs 74[FATAL]

注意:以上输入结构化信息由 "{message} | {time} {file}{level} " formatter决定。formatter中除了关键标识 {message}  {time}  {file}  {level} 外,其他内容原样输出,如 | , 空格,换行  等。


tklog使用详细说明

1. 日志级别 : Trace < Debug < Info < Warn < Error < Fatal

示例:

LOG.set_level(LEVEL::Info)//日志级别,设置为Info

2. 控制台日志

调用 .set_console(bool) 函数

LOG.set_console(false) // false表示不打印控制台日志。默认为true

3. 日志格式

  • Format::Nano                            无格式
  • Format::Date                             输出日期 :2024-05-26
  • Format::Time                             输出时间,精确到秒:14:13:25
  • Format::Microseconds              输出时间,精确到微妙:18:09:17.462245    
  • Format::LongFileName             长文件信息+行号:tests estlog.rs 25
  • Format::ShortFileName             短文件信息+行号:testlog.rs 25
  • Format::LevelFlag                      日志级别信息: [Debug]
LOG.set_format(Format::LevelFlag | Format::Time | Format::ShortFileName)

4.自定义格式输出

默认:"{level}{time} {file}:{message} "

  • {level}            日志级别信息:如[Debug]
  • {time}            日志时间信息
  • {file}               文件位置行号信息
  • {message}      日志内容
LOG.set_formatter("{message} | {time} {file}{level}");//自定义日志结构信息的输入顺序与附加内容

说明:除了关键标识 {message}  {time}  {file}  {level} 外,其他内容原样输出,如 | , 空格,换行  等。

5.按时间分割日志文件

时间标识:MODE::HOUR,MODE::DAY,MODE::MONTH

分别是:小时,天,月份

调用 .set_cutmode_by_time() 函数,参数:

  1. 文件路径
  2. 时间模式
  3. 最大备份日志文件数
  4. 是否压缩备份的日志文件

示例

let mut log = Logger::new();
log.set_cutmode_by_time("/usr/local/tklogs.log", MODE::DAY, 0, false)

说明:备份文件路径为: /usr/local/tklogs.log  ,时间模式为:按天备份,参数0表示不限制备份文件数,false表示不压缩备份的日志文件

备份的文件格式:

  1. 按天备份日期文件,如:
    • tklogs_20240521.log
    • tklogs_20240522.log
  2. 按小时备份日志文件,如:
    • tklogs_2024052110.log
    • tklogs_2024052211.log
  3. 按月份备份日志文件,如:
    • tklogs_202403.log
    • tklogs_202404.log

6.按大小分割日志文件

调用 .set_cutmode_by_size() 函数,参数:

  1. 文件路径
  2. 指定文件滚动大小
  3. 最大备份日志文件数
  4. 是否压缩备份的日志文件

示例

let mut log = Logger::new();
log.set_cutmode_by_time("tklogs.log", 100<<20, 10, true)

说明:备份文件路径为:tklogs.log  ,按100M大小备份文件,参数10表示只保留最新10个备份文件,true表示压缩备份的日志文件

备份的文件格式:

  • tklogs_1.log.gz
  • tklogs_2.log.gz
  • tklogs_3.log.gz

tklog提供常规日志打印 方法为:

  • 全局单例打印
    1. trace!
    2. debug!
    3. info!
    4. warn!
    5. error!
    6. fatal!
  • 多实例打印
    1. traces!
    2. debugs!
    3. infos!
    4. warns!
    5. errors!
    6. fatals!

异步日志

  • 全局异步单例打印
    1. async_trace!
    2. async_debug!
    3. async_info!
    4. async_warn!
    5. async_error!
    6. async_fatal!
  • 多实例异步打印
    1. async_traces!
    2. async_debugs!
    3. async_infos!
    4. async_warns!
    5. async_errors!
    6. async_fatals!

异步方法使用示例

全局单例异步调用

use tklog::{
async_debug,async_error,async_fatal,async_info,async_trace,async_warn,LEVEL, Format, ASYNC_LOG
 };

async fn async_log_init() {
// 全局单例设置参数
 ASYNC_LOG
.set_console(false) //控制台
.set_level(LEVEL::Trace)//日志级别
.set_format(Format::LevelFlag | Format::Time | Format::ShortFileName)//结构化日志,定义输出的日志信息
.set_cutmode_by_size("tklog_async.txt", 10000, 10, false).await;//日志文件切割模式为文件大小,每10000字节切割一次,保留10个备份日志文件

#[tokio::test]
async fn testlog() {
async_log_init().await;//参数设置
async_trace!("trace>>>>", "aaaaaaa", 1, 2, 3);
async_debug!("debug>>>>", "aaaaaaa", 1, 2, 3);
async_info!("info>>>>", "bbbbbbbbb", 1, 2, 3);
async_warn!("warn>>>>", "cccccccccc", 1, 2, 3);
async_error!("error>>>>", "ddddddddddddd", 1, 2, 3);
async_fatal("fatal>>>>", "eeeeeeeeeeeeee", 1, 2, 3);
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
}

输出结果:

[TRACE] 20:03:32 testasynclog.rs 20:trace>>>>,aaaaaaa,1,2,3
[DEBUG] 20:03:32 testasynclog.rs 21:debug>>>>,aaaaaaa,1,2,3
[INFO] 20:03:32 testasynclog.rs 22:info>>>>,bbbbbbbbb,1,2,3
[WARN] 20:03:32 testasynclog.rs 23:warn>>>>,cccccccccc,1,2,3
[ERROR] 20:03:32 testasynclog.rs 24:error>>>>,ddddddddddddd,1,2,3
[FATAL] 20:03:32 testasynclog.rs 25:fatal>>>>,eeeeeeeeeeeeee,1,2,3

多实例异步

use std::sync::Arc;

use tklog::{
 async_debugs,async_errors,async_fatals,async_infos,async_traces,async_warns, LEVEL, Format, ASYNC_LOG, MODE
};
#[tokio::test]
async fn testmultilogs() {
//新建 Async::Logger 对象
let mut log = tklog::Async::Logger::new();
log.set_console(false)
.set_level(LEVEL::Debug)
.set_cutmode_by_time("tklogasync.log", MODE::DAY, 10, true) 
.await
.set_formatter("{message} | {time} {file}{level}");

let mut logger = Arc::clone(&Arc::new(Mutex::new(log)));
let log = logger.borrow_mut();
async_traces!(log, "async_traces>>>>", "AAAAAAAAAA", 1, 2, 3);
async_debugs!(log, "async_debugs>>>>", "BBBBBBBBBB", 1, 2, 3);
async_infos!(log, "async_infos>>>>", "CCCCCCCCCC", 1, 2, 3);
async_warns!(log, "async_warns>>>>", "DDDDDDDDDD", 1, 2, 3);
async_errors!(log, "async_errors>>>>", "EEEEEEEEEEE", 1, 2, 3);
async_fatals!(log, "async_fatals>>>>", "FFFFFFFFFFFF", 1, 2, 3);
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
}

输出结果:

async_debugs>>>>,BBBBBBBBBB,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 45[DEBUG]
async_infos>>>>,CCCCCCCCCC,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 46[INFO]
async_warns>>>>,DDDDDDDDDD,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 47[WARN]
async_errors>>>>,EEEEEEEEEEE,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 48[ERROR]
async_fatals>>>>,FFFFFFFFFFFF,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 49[FATAL]

基准压力测试

test_debugtime: [3.3747 µs 3.4599 µs 3.5367 µs]
change: [-69.185% -68.009% -66.664%] (p = 0.00 < 0.05)
Performance has improved.
Found 9 outliers among 100 measurements (9.00%)
6 (6.00%) high mild
3 (3.00%) high severe

说明:时间范围给出了三个数据点,分别代表了测试执行时间的最小值(3.3747微秒)、平均值附近的值(3.4599微秒)、以及最大值(3.5367微秒)

test_debugtime: [3.8377 µs 3.8881 µs 3.9408 µs]
change: [-66.044% -65.200% -64.363%] (p = 0.00 < 0.05)
Performance has improved.
Found 2 outliers among 100 measurements (2.00%)
2 (2.00%) high mild

说明:测试运行的时间范围是从3.8377微秒到3.9408微秒,覆盖了一个大概的分布情况,其中3.8881微秒大约是这段时间内的平均或中位数执行时间

结论:日志打印函数性能:3 µs/op — 4 µs/op   (微妙/次)


相關推薦

2024-08-27

tklog是rust高性能结构化日志库 易用,高效,结构化,控制台日志,文件日志,文件切割,文件压缩,同步打印,异步打印 功能 功能支持:控制台日志,文件日志,同步日志,异步日志 日志级别设置:提供与标准库同级

2024-06-04

tklog是rust高性能结构化日志库,支持同步日志,异步日志,支持自定义日志的输出格式,支持按时间,按文件大小分割日志文件,支持日志文件压缩备份,支持官方日志库标准API tklog 0.0.3版本主要更新 tklog实现了官方Log接

2024-06-22

tklog是rust高性能结构化日志库,支持同步日志,异步日志,支持自定义日志的输出格式,支持按时间,按文件大小分割日志文件,支持日志文件压缩备份,支持官方日志库标准API,支持mod独立参数设置 tklog相关信息 官网

2024-08-12

似于 nginx 的反向代理,基于 pingora 构建,简单而高效,支持文件与 WEB 界面的两种配置形式,10 分钟即可完成 https 站点服务配置。最新版本支持了更多的插件,提供了10多组prometheus性能指标,以及提供了基于opentelemtry的

2022-09-15

试框架(unitest) go-style 协程 基于协程的网络编程框架 高效 JSON 库 基于 JSON 的 RPC 框架 面向玄学编程 原子操作(atomic) 随机数生成器(random) 高效字符流(fastream) 高效字符串(fastring) 字符串操作(str) 时间库(time) 线程

2023-10-17

SQL数据库高可用解决方案 随着PostgreSQL的日益普及,对于高效、稳定和易用的数据库管理软件的需求也日渐增加。我们很高兴地宣布,经过多年精心设计与开发,中启乘数科技所推出的CLup软件已正式发布开源版本!中启乘数基

2022-09-15

台。通过积累DevOps持续交付认证的经验,研发出来的一套高效灵活,功能全面,简单易用的持续集成工具。     EazyBuilder 致力于帮助您创建,管理,监控持续集成流水线。本平台聚焦多团队多工程统一编译、构建、扫描

2023-12-15

er 接口,无需任何复杂语言只是,轻松实现中间件。灵活高效。 - 内置表单处理,强大的提取器,轻松反序列请求数据到结构体。 - 支持 WebSocket, WebTransport - 对 OpenAPI 最完美的支持,且内置多种开源 OpenAPI 展示界面 - 支持 Acme

2023-11-18

建 PostgreSQL 数据库集群的功能,助力企业轻松构建稳定、高效的数据库集群环境。 数据库集群高可用功能:对于任何业务来说,数据库的稳定性都是至关重要的。OpenCLup 软件的高可用功能保证了数据库集群在遇到故障时,可

2024-08-10

go-logger  是一个轻量级的日志库,提供了灵活的日志记录功能,方便在应用程序中实现不同级别的日志输出. 特点: 简单易用:go-logger 提供了一个简单直观的 API,使得开发者能够快速上手并集成到现有项目中。

2023-10-25

建 PostgreSQL 数据库集群的功能,助力企业轻松构建稳定、高效的数据库集群环境。 数据库集群高可用功能:对于任何业务来说,数据库的稳定性都是至关重要的。OpenCLup 软件的高可用功能保证了数据库集群在遇到故障时,可

2023-11-09

MM2019论文成果)的测试方法,严格保障了协议一致性。 易用性:TQUIC易于使用,支持灵活的配置和丰富的可观察性;TQUIC提供了Rust/C/C++多语言接口,未来计划进一步提供Kotlin/Swift等语言接口。 基于RUST:TQUIC基于内存安全语言

2022-10-10

它提供了更简化的配置,并行的多节点部署支持并改进了易用性。它基于 Golang 编写,可直接下载https://github.com/hstreamdb/deployment-tool/releases 使用,基本用法如下: 通过 hdt init 生成部署模板 根据实际环境修改部署配置 globa

2023-06-30

者在两个月或更短的时间内使用 Rust 变得与其他语言一样高效。四个月内,这一数字增加到 50% 以上。 2. Rust 编译器速度并没有想象的那么快 谷歌证实了此说法。 他们表示,到目前为止,构建速度慢是开发者在使用 Rust 时遇