1 个不稳定版本
0.1.0 | 2019年3月1日 |
---|
#499 in 调试
84KB
2K SLoC
Astrolog
Astrolog是一个易于使用、简洁且灵活的Rust日志系统。
Astrolog的主要目的是在应用程序中使用,而不是在crate或库中使用。它注重简洁,而不是最大效率。性能不可忽视,但在开发过程中,易用性具有更高的优先级。
如何使用
Astrolog可以通过两种方式使用:全局日志记录器可以从应用程序的任何地方静态调用,如果您需要具有不同配置的一个或多个实例,则可以分别实例化它们,并将相关的实例传递给应用程序的组件。
全局日志记录器
如果您正在构建一个小型应用程序且/或不想将日志记录器注入到可能使用它的函数或对象中,则此方法特别有用。如果您熟悉默认的rust log
功能或提供日志宏的crate,如 slog
,则此方法将看起来很熟悉,但使用静态调用而不是宏。
fn main() {
astrolog::config(|logger| {
logger
.set_global("OS", env::consts::OS)
.push_handler(ConsoleHandler::new().with_levels_range(Level::Info, Level::Emergency));
});
normal_function();
function_with_error(42);
}
fn normal_function() {
astrolog::debug("A debug message");
}
fn function_with_error(i: i32) {
astrolog::with("i", i)
.with("line", line!())
.with("file", file!())
.error("An error with some debug info");
}
常规日志记录器
如果您想为应用程序的不同部分使用不同的日志记录器,或者您想通过依赖注入、服务定位器或DIC(或使用单例)传递日志记录器,则此方法很有用。
fn main() {
let logger1 = Logger::new()
.with_global("OS", env::consts::OS)
.with_handler(ConsoleHandler::new().with_levels_range(Level::Trace, Level::Info));
let logger2 = Logger::new()
.with_global("OS", env::consts::OS)
.with_handler(ConsoleHandler::new().with_levels_range(Level::Info, Level::Emergency));
normal_function(&logger1);
function_with_parameter(42, &logger2);
}
fn normal_function(logger: &Logger) {
logger.debug("A debug message");
}
fn function_with_parameter(i: i32, logger: &Logger) {
logger
.with("i", i)
.with("line", line!())
.with("file", file!())
.error("An error with some debug info");
}
语法和配置
Astrolog通过允许用户构建日志条目并将它们传递给处理程序来实现。每个日志记录器可以有一个或多个处理程序,每个处理程序可以单独配置以仅接受某些日志级别。
例如,您可能希望有一个 ConsoleHandler
(或用于彩色输出的 TermHandler
)来处理 trace
、debug
和 info
级别,同时您还想将所有级别的消息保存到文件中,并将所有级别为 warning
或更高的消息发送到外部日志聚合器。
通过隐式构建模式构建条目,并在调用适当的级别函数时将它们发送到处理程序。
让我们用一个例子来简化它
fn main() {
logger.info("Some informative message")
}
这将构建条目并立即将其发送到处理程序。
使用 with
将会开始构建条目
fn main() {
logger.with("some key", 42).info("Some informative message")
}
这将创建一个条目,将其中的键值对("some key"
和 42
)存储在其中,并最终将其发送到处理器。
在调用级别方法之前,可以多次调用 with
(或 with_multi
或 with_error
)进行链式调用。
可用级别
Astrolog 使用的级别比普通记录器多。以下是按严重程度排序的完整列表
- 跟踪
- 性能分析
- 调试
- 信息
- 注意
- 警告
- 错误
- 严重
- 警报
- 紧急
在 Logger
上的函数名称相应地命名(.trace()
、.profile()
等)。还有一个接受 Level
作为第一个参数的 .log()
函数,以便在运行时程序化地决定。
从 debug
到 emergency
的级别模仿 Unix/Linux 的 syslog 级别。
其他日志系统往往将所有调试、性能分析和跟踪信息混淆到 debug
中,而 Astrolog 建议只将 debug 用于无用的“占位符”消息。
profile
旨在记录性能分析信息(执行时间、函数或循环迭代的调用次数等),而 trace
旨在跟踪程序执行(例如调试时)
这允许更好地过滤调试信息并将它们发送到特定的处理器。例如,您可能希望将 profile
信息发送到 Prometheus 处理器,将 debug
、info
和 notice
发送到 STDOUT,将 trace
发送到文件以便更容易分析,以及将所有 warning
和以上级别的信息发送到 STDERR。
示例
要运行示例,请使用
cargo run --example simple
cargo run --example global
cargo run --example passing
cargo run --example errors
cargo run --example multithread
每个示例展示了使用 Astrolog 的不同方法。
simple
展示了如何创建专用记录器并通过方法调用使用它,有无额外参数。
global
展示了如何通过静态调用配置和使用全局记录器。
passing
展示了如何创建专用记录器并通过引用或 Rc
传递它。
errors
展示了如何将 Rust 错误传递到日志函数并打印错误跟踪。
multithread
展示了如何轻松地在多线程应用程序中使用 Astrolog。
处理器
Astrolog 核心crate提供了一些基本处理器,而其他处理器可以在单独的crate中实现。
控制台处理器
控制台处理器简单地将所有消息打印到控制台,每行一个,具有可配置的格式(稍后将在 [格式化程序] 中介绍)。
此处理器可以配置为使用 stdout
或 stderr
打印消息,但由于 Astrolog 的模块化,可以为不同的日志级别注册两个 ConsoleHandler,以便将消息发送到不同的输出。
此处理器不提供输出着色(有关着色,请参阅 [astrolog-term] crate)。
示例
fn main() {
let logger = Logger::new()
.with_handler(ConsoleHandler::new()
.with_stdout()
.with_levels_range(Level::Debug, Level::Notice)
)
.with_handler(ConsoleHandler::new()
.with_stderr()
.with_levels_range(Level::Warning, Level::Emergency)
);
}
Vec 处理器
此处理程序简单地将所有消息收集到一个 Vec
中,以便稍后处理。例如,它有助于调试新的格式化程序或批量处理消息。
由于Rust的所有权规则,使用它需要在设置时做更多的工作。
fn main() {
let handler = VecHandler::new();
let logs_store = handler.get_store();
let logger = Logger::new()
.with_handler(handler);
logger.info("A new message");
let logs = logs_store.take();
// logs is now a Vec<Record> over which you can iterate
}
空处理程序
此处理程序是Astrolog的 /dev/null
。它简单地丢弃接收到的任何消息。
它可以用于在运行时决定不记录任何内容,同时具有最小的处理成本,保持记录器实例就位。
fn main() {
let logger = Logger::new()
.with_handler(
NullHandler::new()
);
}
格式化程序
格式化程序允许以不同的方式格式化日志记录,具体取决于用户的偏好或处理程序所需的格式。
例如,将日志记录到文件最好使用 LineFormatter
,而在网页上打印错误则可能受益于 HtmlFormatter
,而通过REST API发送则需要 JsonFormatter
。
然后,每个记录格式化程序可以使用不同的“子格式化程序”来格式化级别指示器、日期和上下文(与记录相关联的值)。
LineFormatter
这是Astrolog基本crate中提供最简单且最有用的格式化程序。它简单地以模板格式返回单个行中的日志记录信息。模板支持占位符,可以在输出中插入记录或上下文的各个部分。
fn main() {
let logger = Logger::new()
.with_handler(ConsoleHandler::new()
.with_formatter(LineFormatter::new()
.with_template("{{ [datetime]+ }}{{ level }}: {{ message }}{{ +context? }}")
)
);
}
此示例显示了 ConsoleHandler
的默认配置,因此不需要,但它可以提供如何配置格式化程序及其模板的示例。
支持的占位符有:
datetime
:插入记录的日期和时间,根据配置的日期时间格式化程序(见下文)level
:插入记录的级别,根据配置的级别格式化程序(见下文)message
:插入记录的消息context
:插入上下文,根据配置的上下文格式化程序(见下文)
任何其他占位符都视为上下文中的变量名称,并支持JSON指针来访问嵌套信息。
所有占位符(除了 message
以避免循环)都可以用于消息本身,以将上下文变量添加到消息中。例如
fn main() {
logger
.with("user", json!({"name": "Alex", "login": { "username": "dummy123" } }))
.debug("Logged in as {{ /user/login/username }}");
}
HtmlFormatter
此格式化程序与 LineFormatter 非常相似,新增了自动转义消息和值中的字符串的功能,以便将 &
、<
和 >
正确编码为实体并显示在页面上。
JsonFormatter
此格式化程序将记录转换为JSON对象并将其作为字符串返回。
默认情况下,顶级字段名称为 time
、level
、message
和 context
,但它们可以通过 .set_field_names()
或 .with_field_names()
进行自定义。
日志部分格式化程序
日志消息的部分可以用不同的方式进行格式化。有时处理程序需要特定的格式,例如日期,而有时只是个人偏好的问题。
日期格式化
formatter::date::Format
是一个枚举,支持多种预定义的格式,并能够根据 [chrono] 的格式使用自定义格式。
级别格式化
formatter::level::Format
是一个枚举,支持日志级别的长(全称)和短(4字符)表示,可以是小写、大写或标题大小写。
上下文格式化
此模块在核心crate中提供了两种格式化与日志记录关联的上下文的方式:JSON 和 JSON5。
虽然 JSON 在将日志传输到其他服务或应用程序时很有用(甚至必不可少),但 JSON5 在人类可读性方面更好,因此特别适用于控制台、文件和syslog日志(它是默认格式)。
字段命名
一个特殊情况是 formatter::fields::Names
,因为它用于定义某些格式器(如 JSON)中的主要字段名称,允许自定义最终表示的外观。
示例
fn main() {
let logger = Logger::new()
.with_handler(ConsoleHandler::new()
.with_formatter(LineFormatter::new()
.with_date_format(DateFormat::Email)
.with_level_format(LevelFormat::LowerShort)
)
);
}
许可证
作为说明,当使用 Astrolog 作为 Rust crate 时,crate 被视为动态库,因此 LGPL 允许你在封闭源代码项目或具有不同开源许可证的项目中使用它,而任何对 Astrolog 本身的修改都必须在 LGPL 2.1 许可证下发布。
依赖项
~6MB
~121K SLoC