https://github.com/chensoft/logkit
Super fast, structured, scalable logging library for Rust
https://github.com/chensoft/logkit
Last synced: 24 days ago
JSON representation
Super fast, structured, scalable logging library for Rust
- Host: GitHub
- URL: https://github.com/chensoft/logkit
- Owner: chensoft
- License: mit
- Created: 2024-01-11T11:59:45.000Z (over 2 years ago)
- Default Branch: dev
- Last Pushed: 2025-06-07T07:07:46.000Z (about 1 year ago)
- Last Synced: 2025-11-19T21:13:14.493Z (7 months ago)
- Language: Rust
- Homepage:
- Size: 101 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: HISTORY.md
- License: LICENSE
Awesome Lists containing this project
README
Logkit
==========================
Super fast, structured, scalable logging library for Rust
[![Crates.io][crates-badge]][crates-url]
[![MIT licensed][license-badge]][license-url]
[![Documentation][document-badge]][document-url]
[![Build Status][linux-badge]][linux-url]
[![Build Status][macos-badge]][macos-url]
[![Build Status][windows-badge]][windows-url]
[crates-badge]: https://img.shields.io/crates/v/logkit.svg
[crates-url]: https://crates.io/crates/logkit
[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg
[license-url]: https://github.com/chensoft/logkit?tab=MIT-1-ov-file
[document-badge]: https://docs.rs/logkit/badge.svg
[document-url]: https://docs.rs/logkit
[linux-badge]: https://github.com/chensoft/logkit/actions/workflows/linux.yml/badge.svg
[linux-url]: https://github.com/chensoft/logkit/actions/workflows/linux.yml
[macos-badge]: https://github.com/chensoft/logkit/actions/workflows/macos.yml/badge.svg
[macos-url]: https://github.com/chensoft/logkit/actions/workflows/macos.yml
[windows-badge]: https://github.com/chensoft/logkit/actions/workflows/windows.yml/badge.svg
[windows-url]: https://github.com/chensoft/logkit/actions/workflows/windows.yml
## Hello World
```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);
}
```
Output sample:
```json
{"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"}
```
## Basic Syntax
Five convenient macros are available for use: `trace`, `debug`, `info`, `warn`, and `error`.
These support the following log formats, and you can define custom macros if necessary.
```rust
#[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");
```
## Default Logger
For convenience, we have defined a default logger that outputs messages to stderr.
```rust
#[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");
```
## Custom Logger
```rust
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
}
```
## Custom Level
There are five built-in log levels: `TRACE`, `DEBUG`, `INFO`, `WARN` and `ERROR`. You can define your
own levels, as the type is simply an alias for i32, not an enum.
```rust
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");
```
## Custom Encoding
We support all scalar types and many std collections, if you want to encode your own type into
json, you can implement the Encode trait.
```rust
pub struct CustomStruct {
pub key1: i32,
pub key2: bool,
pub key3: String,
}
impl logkit::Encode for CustomStruct {
#[inline]
fn encode(&self, buf: &mut Vec) {
// format your struct into buf
unimplemented!()
}
}
```
## Logging Plugin
Plugins, also known as middleware, add hooks for `pre` and `post` steps. When a logger spawns a
record, the `pre` method is called before any fields are added to it. When the record is ready
to flush, the `post` method is invoked before outputting to targets. You can add any fields
to the record. If you decide not to continue handling the record, simply return `false` in
`pre` or `post`. The record will not be processed further if `false` is returned.
```rust
#[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");
}
```
```rust
#[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");
}
```
## Output Target
Upon completion, a record is routed to various targets, which define the methods of outputting
content. A record can be directed to multiple targets, and each target is simply required to
implement the `Target` trait.
```rust
#[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");
}
```
## Benchmark
- MacBook Air, Apple M2 24G, Sonoma 14.2.1
| Name | Time |
|:------------------|:-------------------------------:|
| empty_log | [22.526 ns 22.541 ns 22.560 ns] |
| level_off | [1.6941 ns 1.6989 ns 1.7050 ns] |
| msg_only | [63.166 ns 63.172 ns 63.177 ns] |
| msg_format | [63.238 ns 63.373 ns 63.548 ns] |
| fields_only | [96.944 ns 96.974 ns 97.005 ns] |
| fields_msg | [147.03 ns 147.26 ns 147.56 ns] |
| fields_msg_format | [146.44 ns 146.51 ns 146.58 ns] |
| fields_ten_fields | [395.31 ns 395.35 ns 395.40 ns] |
- AWS c5.2xlarge, 8C 16G, Ubuntu 22.04
| Name | Time |
|:------------------|:-------------------------------:|
| empty_log | [50.761 ns 50.764 ns 50.768 ns] |
| level_off | [4.1800 ns 4.1804 ns 4.1810 ns] |
| msg_only | [121.12 ns 121.14 ns 121.16 ns] |
| msg_format | [121.18 ns 121.20 ns 121.23 ns] |
| fields_only | [177.70 ns 177.74 ns 177.77 ns] |
| fields_msg | [264.25 ns 264.33 ns 264.45 ns] |
| fields_msg_format | [261.80 ns 261.89 ns 261.98 ns] |
| fields_ten_fields | [654.11 ns 654.31 ns 654.51 ns] |