10 个版本
0.3.7 | 2024 年 7 月 13 日 |
---|---|
0.3.6 | 2024 年 7 月 12 日 |
0.3.5 | 2024 年 5 月 18 日 |
0.3.4 | 2024 年 3 月 13 日 |
0.1.0 | 2024 年 1 月 24 日 |
#150 in 调试
537 每月下载量
用于 fibra
44KB
548 代码行
Logkit
为 Rust 提供的超级快速、结构化、可扩展的日志库
你好世界
#[macro_use] extern crate logkit;
fn main() {
let mut logger = logkit::Logger::new(Some(&logkit::StdoutTarget));
logger.mount(logkit::TimePlugin::from_millis());
logger.mount(logkit::LevelPlugin);
logger.mount(logkit::SourcePlugin::new());
logkit::set_default_logger(logger);
trace!("hello, this is a trace log");
debug!("hello, this is a debug log");
info!(version = "0.1.0", commit = "3291cc60"; "this is a log with two string fields");
warn!(address = "127.0.0.1", port = 3000; "this is a log with a string and a numeric field");
error!("this is a log with a 'println' style string {}:{}", "127.0.0.1", 3000.0);
}
输出示例
{"time":"2024-06-30T14:43:33.236+08:00","level":"trace","msg":"hello, this is a trace log","src":"examples/hello_world.rs:10"}
{"time":"2024-06-30T14:43:33.236+08:00","level":"debug","msg":"hello, this is a debug log","src":"examples/hello_world.rs:11"}
{"time":"2024-06-30T14:43:33.236+08:00","level":"info","msg":"this is a log with two string fields","version":"0.1.0","commit":"3291cc60","src":"examples/hello_world.rs:12"}
{"time":"2024-06-30T14:43:33.236+08:00","level":"warn","msg":"this is a log with a string and a numeric field","address":"127.0.0.1","port":3000,"src":"examples/hello_world.rs:13"}
{"time":"2024-06-30T14:43:33.236+08:00","level":"error","msg":"this is a log with a 'println' style string 127.0.0.1:3000","src":"examples/hello_world.rs:14"}
基本语法
提供五个方便的宏供使用: trace
、debug
、info
、warn
和 error
。这些支持以下日志格式,并在必要时可以定义自定义宏。
#[macro_use] extern crate logkit;
trace!(); // outputs just a linebreak
trace!("plain message");
trace!("println-like message {} {}!", "Hello", "World");
trace!(name = "Alice", age = 20); // outputs only fields, no message
trace!(name = "Alice", age = 20; "separate fields and messages with semicolon");
trace!(name = "Alice", age = 20; "println-like message {} {}! with fields", "Hello", "World");
默认日志记录器
为了方便,我们已经定义了一个默认的日志记录器,该记录器将消息输出到 stderr。
#[macro_use] extern crate logkit;
assert_eq!(logkit::default_logger().level(), logkit::LEVEL_TRACE);
trace!("hello, this is a trace log");
debug!("hello, this is a debug log");
自定义日志记录器
fn main() {
let mut logger = logkit::Logger::new(None);
logger.mount(logkit::LevelPlugin); // you can add your own plugin
logger.route(logkit::StderrTarget); // and add your custom target
// replace the default logger
logkit::set_default_logger(logger);
// or use it directly like built-in macros
}
自定义级别
有五个内置的日志级别: TRACE
、DEBUG
、INFO
、WARN
和 ERROR
。您可以定义自己的级别,因为该类型只是 i32 的别名,而不是枚举。
pub const LEVEL_CUSTOM : logkit::Level = 10; // use any number distinct from the built-ins
#[macro_export]
macro_rules! custom {
($($arg:tt)*) => {{
logkit::record!(logkit::default_logger(), LEVEL_CUSTOM, $($arg)*)
}};
}
custom!("this is a custom log level");
自定义编码
我们支持所有标量类型和许多 std 集合,如果您想将自定义类型编码到 json 中,可以实现 Encode 特性。
pub struct CustomStruct {
pub key1: i32,
pub key2: bool,
pub key3: String,
}
impl logkit::Encode for CustomStruct {
#[inline]
fn encode(&self, buf: &mut Vec<u8>) {
// format your struct into buf
unimplemented!()
}
}
日志插件
插件也称为中间件,为 pre
和 post
步骤添加钩子。当日志记录器创建一个记录时,在添加任何字段之前会调用 pre
方法。当记录准备好刷新时,在输出到目标之前会调用 post
方法。您可以向记录中添加任何字段。如果您决定不继续处理记录,只需在 pre
或 post
中返回 false
即可。如果返回 false
,则记录将不再进一步处理。
#[macro_use] extern crate logkit;
// custom plugin to add 'pid' to record
pub struct PidPlugin { pub pid: u32 }
impl logkit::Plugin for PidPlugin {
#[inline]
fn post(&self, record: &mut logkit::Record) -> bool {
record.append("pid", &self.pid);
true
}
}
fn main() {
let mut logger = logkit::Logger::new(Some(&logkit::StderrTarget));
logger.mount(PidPlugin { pid: std::process::id() });
logkit::set_default_logger(logger);
info!("you will see this log with a process id");
}
#[macro_use] extern crate logkit;
// custom plugin to filter all levels below 'info'
pub struct LimitPlugin;
impl logkit::Plugin for LimitPlugin {
#[inline]
fn pre(&self, record: &mut logkit::Record) -> bool {
record.level() >= logkit::LEVEL_INFO
}
}
fn main() {
let mut logger = logkit::Logger::new(Some(&logkit::StderrTarget));
logger.mount(LimitPlugin);
logkit::set_default_logger(logger);
debug!("this log is ignored");
info!("you can see this log");
}
输出目标
完成后,记录将路由到各种目标,这些目标定义了输出内容的方法。记录可以指向多个目标,每个目标只需要实现 Target
特性。
#[macro_use] extern crate logkit;
pub struct CustomTarget;
impl logkit::Target for CustomTarget {
#[inline]
fn write(&self, buf: &[u8]) {
use std::io::Write;
let _ = std::io::stdout().write_all(buf);
}
}
fn main() {
let mut logger = logkit::Logger::new(Some(&logkit::StderrTarget));
logger.route(CustomTarget);
logkit::set_default_logger(logger);
info!("record will be output to both stderr and stdout now");
}
基准测试
- MacBook Air,Apple M2 24G,Sonoma 14.2.1
名称 | 时间 |
---|---|
empty_log | [22.526 纳秒 22.541 纳秒 22.560 纳秒] |
关闭级别 | [1.6941 纳秒 1.6989 纳秒 1.7050 纳秒] |
仅消息 | [63.166 纳秒 63.172 纳秒 63.177 纳秒] |
消息格式 | [63.238 纳秒 63.373 纳秒 63.548 纳秒] |
仅字段 | [96.944 纳秒 96.974 纳秒 97.005 纳秒] |
字段消息 | [147.03 纳秒 147.26 纳秒 147.56 纳秒] |
字段消息格式 | [146.44 纳秒 146.51 纳秒 146.58 纳秒] |
字段十字段 | [395.31 纳秒 395.35 纳秒 395.40 纳秒] |
- AWS c5.2xlarge, 8C 16G, Ubuntu 22.04
名称 | 时间 |
---|---|
empty_log | [50.761 纳秒 50.764 纳秒 50.768 纳秒] |
关闭级别 | [4.1800 纳秒 4.1804 纳秒 4.1810 纳秒] |
仅消息 | [121.12 纳秒 121.14 纳秒 121.16 纳秒] |
消息格式 | [121.18 纳秒 121.20 纳秒 121.23 纳秒] |
仅字段 | [177.70 纳秒 177.74 纳秒 177.77 纳秒] |
字段消息 | [264.25 纳秒 264.33 纳秒 264.45 纳秒] |
字段消息格式 | [261.80 纳秒 261.89 纳秒 261.98 纳秒] |
字段十字段 | [654.11 纳秒 654.31 纳秒 654.51 纳秒] |
依赖关系
~11MB
~211K SLoC