#log-level #log #logging #color-themes #color

swing

使用此日志crate的日志实现,让日志就像1978年一样

1个不稳定版本

0.1.0 2022年11月27日

#314 in 调试

MIT/Apache

475KB
817

swing logo

swing

使用此log crate的日志实现,让日志就像1978年一样。彩色主题、可插拔格式化,我们应有尽有!

multi-line-gradient

安装

将以下内容添加到Cargo.toml

[dependencies]
swing = "0.1"
log = "0.4"

快速入门

创建并初始化一个Logger,然后使用log crate宏来记录消息

use swing::Logger;

fn main() {
    // setup logger
    Logger::new().init().unwrap();

    // log away!
    log::trace!("foo");
    log::debug!("bar");
    log::info!("baz");
    log::warn!("spam");
    log::error!("eggs");
}

注意,使用::new()创建的默认Logger具有info日志级别过滤器,因此在此示例中,只有"baz""spam""eggs"将被打印到控制台。

Logger配置选项

为了更好地控制,可以通过Logger::with_config使用Config结构创建Logger

use swing::{Config, Logger};
use log::LevelFilter;

fn main() {
    let config = Config {
        level: LevelFilter::Trace,
        ..Default::default()
    };

    Logger::with_config(config).init().unwrap();
}

默认配置使用以下设置

use swing::{Config, ColorFormat, RecordFormat, theme};
use log::LevelFilter;

Config {
    level: LevelFilter::Info,
    record_format: RecordFormat::Simple,
    color_format: Some(ColorFormat::Solid),
    theme: Box::new(theme::Spectral {}),
    use_stderr: true,
};

每个设置都在其自己的子部分中解释

level

level设置控制哪些日志记录被处理,哪些被忽略。在Config中使用LevelFilter枚举直接来自log crate。它定义了以下变体

  • Off
  • Trace
  • Debug
  • Info
  • Warn
  • Error

只有记录在或高于所选严重性的日志记录会被输出到stdout/stderr。例如

use swing::Config;
use log::LevelFilter;

// --snip--

let config = Config {
    level: LevelFilter::Info,
    ..Default::default()
};

// --snip--

// trace and debug logs will be ignored, only info, warn, and error messages will print to the screen
log::trace!("foo");
log::debug!("bar");
log::info!("baz");
log::warn!("spam");
log::error!("eggs");

record_format

record_format 设置控制日志记录在显示时的(结构化)格式化方式。每次调用 log 包的宏(如 trace!info! 等)都会生成一个日志 记录。然后,这些记录将通过这个包使用 RecordFormat 枚举中的一个变体进行格式化。

  • Json
  • 简单
  • 自定义

记录格式由以下导入和使用

use swing::{Config, Logger, RecordFormat};
use log::LevelFilter;

fn main() {
    let config = Config {
        level: LevelFilter::Trace,
        record_format: RecordFormat::Simple,
        ..Default::default()
    };
    Logger::with_config(config).init().unwrap();
}

简单格式

这是默认的记录格式,将生成如下格式的日志行

2022-07-31T20:25:31.108560826Z [main] TRACE - foo
2022-07-31T20:25:31.108623041Z [main] DEBUG - bar
2022-07-31T20:25:31.108645580Z [main] INFO - baz
2022-07-31T20:25:31.108667634Z [main] WARN - spam
2022-07-31T20:25:31.108736790Z [main] ERROR - eggs

注意,时间总是以 ISO 8601 格式,UTC 时间表示。

Json 格式

此记录格式将生成以 JSON 格式的日志行

{"time":"2022-07-31T20:28:11.863634602Z","level":"TRACE","target":"main","message":"foo"}
{"time":"2022-07-31T20:28:11.864114090Z","level":"DEBUG","target":"main","message":"bar"}
{"time":"2022-07-31T20:28:11.864201937Z","level":"INFO","target":"main","message":"baz"}
{"time":"2022-07-31T20:28:11.864269093Z","level":"WARN","target":"main","message":"spam"}
{"time":"2022-07-31T20:28:11.864372619Z","level":"ERROR","target":"main","message":"eggs"}

注意,时间总是以 ISO 8601 格式,UTC 时间表示。

自定义格式

如果您不喜欢上述任何格式,可以使用 Custom 格式注入自己的自定义记录格式化。

use swing::{Config, Logger, RecordFormat};
use log::{LevelFilter, Record};

fn main() {
    let fmt_rec = Box::new(|r: &Record| -> String {
        format!("{} - {}", r.level(), r.args())
    });

    let config = Config {
        level: LevelFilter::Trace,
        record_format: RecordFormat::Custom(fmt_rec),
        ..Default::default()
    };
    Logger::with_config(config).init().unwrap();

    // log away!
    log::trace!("foo");
    log::debug!("bar");
    log::info!("baz");
    log::warn!("spam");
    log::error!("eggs");
}

上述示例格式将生成如下格式的日志行

TRACE - foo
DEBUG - bar
INFO - baz
WARN - spam
ERROR - eggs

有关在自定义格式闭包中使用的可用记录字段/方法,请参阅 日志包 "Record" 结构

作为参考,以下 Simple 记录格式可以用以下 Custom 记录格式重现

use time::format_description::well_known::Iso8601;
use time::OffsetDateTime;
use log::Record;

// --snip--

let fmt_rec = Box::new(|r: &Record| -> String {
    let now = OffsetDateTime::now_utc()
        .format(&Iso8601::DEFAULT)
        .expect("Failed to format time as ISO 8601");

    format!("{} [{}] {} - {}", now, r.target(), r.level(), r.args())
});

color_format

color_format 设置控制日志记录在显示时的着色方式(特别是应用主题的方式)。日志记录将通过此包使用 ColorFormat 枚举中的一个变体或 None 进行格式化。

  • 实心
  • 内联渐变(<步数>)
  • 多行渐变(<步数>)

颜色格式由以下导入和使用

use swing::{Config, Logger, ColorFormat};
use log::LevelFilter;

fn main() {
    let config = Config {
        level: LevelFilter::Trace,
        color_format: Some(ColorFormat::Solid),
        ..Default::default()
    };
    Logger::with_config(config).init().unwrap();
}

无格式

如果提供 None 作为 color_format,则日志记录将不会着色(警告和错误仍将加粗显示)。

实心格式

这将生成每个日志行都有固定颜色的日志行,颜色由日志级别确定。以下截图使用 Spectral 主题和以下颜色格式

use swing::ColorFormat;

// --snip--

let color_format = Some(ColorFormat::Solid);

solid color format

内联渐变格式

这将生成从左到右的重复线性渐变着色的日志行,颜色由日志级别确定。以下截图使用 Spectral 主题和以下颜色格式

use swing::ColorFormat;

// --snip--

let color_format = Some(ColorFormat::InlineGradient(60));

inline gradient color format

此颜色格式接受一个 usize 参数,表示每个级别的颜色渐变从起始颜色到结束颜色所需的步数。渐变将以交替的升序和降序遍历。在上面的示例中,将从每行的起始颜色到结束颜色需要 60 个字符,然后再需要 60 个字符回到起始颜色。

请注意,此颜色格式在大量日志记录的情况下将产生相当大的性能影响。如果您有很多日志并且正在尝试打破下一个速度记录,那么您可能不应该使用此颜色格式。

多行渐变格式

这将生成每个日志行都有固定颜色的日志行,颜色由级别确定。每个级别内的行将逐步改变颜色,通过相关的日志级别确定的颜色线性渐变进行。以下截图使用 Spectral 主题和以下颜色格式

use swing::ColorFormat;

// --snip--

let color_format = Some(ColorFormat::MultiLineGradient(30));

multi-line gradient

这种颜色格式需要一个代表每个级别颜色渐变从起始颜色到结束颜色所需步骤数量的 usize 参数。渐变将以交替升序和降序的方式遍历。在上面的例子中,从每个级别的起始颜色到结束颜色需要 30 行,然后再用 30 行返回到起始颜色。

theme

theme 设置决定了应用颜色格式时使用的调色板。它是通过提供一个实现了 Theme 特性的实例来设置的。

use swing::theme::Spectral;

// --snip--

let theme = Box::new(Spectral {});

这个crate提供了一些预设的主题,但你也可以实现自己的,或者使用他人制作的主题。

光谱

Spectral 主题提供了一个调色板,该调色板通过5个部分移动到颜色光谱。

spectral theme

简单

Simple 主题提供了一个相对平缓的调色板,使用5种主要颜色的深浅版本。

simple theme

创建自定义主题

任何实现了 Theme 特性的东西都可以用作主题。要创建自己的主题,你只需为结构体实现此特性,然后将 Configtheme 成员设置为该结构体的boxed实例。有关自定义主题实现的示例,请参阅 examples/custom-theme.rs

use_stderr

use_stderr 设置决定了日志记录是同时在 stdoutstderr 之间分割还是不分割。当此字段为false时,所有日志记录都将写入 stdout。当此字段为true时,级别为 tracedebuginfo 的记录将写入 stdout,而级别为 warnerror 的记录将写入 stderr

示例

请参阅 examples 目录,以获取各种使用示例。你可以运行这些示例中的任何一个:

$ cargo run --example <example name>

Linux中的流重定向技巧

use_stderr 设置为true时,你必须重定向两个流以捕获所有输出。

将所有日志记录重定向到文件

$ ./example &> foo.log

将所有日志重定向到文件,同时监控输出

# write all log data to foo.log and stdout simultaneously
$ ./example 2>&1 | tee foo.log

当使用 RecordFormat::Json 时,你可以添加 jq 以进行美化打印。

$ ./example 2>&1 | tee foo.log | jq

贡献

欢迎贡献,并非常感谢。有关一些一般性指南,请参阅 CONTRIBUTING

许可证

根据您的选择,许可协议为 Apache License, Version 2.0MIT license

除非您明确声明,否则任何有意提交以包含在 swing 中的贡献,如 Apache-2.0 许可证中定义的,将如上所述双重许可,不附加任何额外条款或条件。

依赖项

~2–12MB
~97K SLoC