1 个不稳定版本

0.1.0 2022年11月7日

#17 in #aptos

Apache-2.0

110KB
2.5K SLoC

这个crate提供日志记录的API。

使用日志进行监测

使用日志的基本监测

提供一组日志宏(info!error!warn!debug!trace!),用于以不同级别发出日志。所有这些宏都支持添加结构化数据以及格式化文本消息。有关使用哪个级别的指南,请参阅编码指南

以下示例不进行结构化日志字段的类型检查,而是直接序列化所提供的内容。

use aptos_logger::info;

let world = "world!";

// Formatted message, similar to `printf!`
info!("hello {}", world);
// => '{"level":"info", "message": "hello world!"}'

// Structured data can be logged using the format 'key = value'
// where value implements Serialize.  This can be used for indexing and search later.
let value1 = 5;
info!(key1 = value1);
// => '{"level":"info", "data": {"key1": 5}}'

// You can even set multiple key/value pairs and a format message together
let value2 = false;
info!(key1 = value1, key2 = value2, "hello {}", world);
// => '{"level":"info", "data": {"key1": 5, "key2": false}, "message": "hello world!"}'

// Structured data can also use `Display` or `Debug` outputs instead.
// Using the sigil `?` for debug and `%` for display.
let value1 = 5;
info!(debug_key = ?value1, display_key = %value1);
// => '{"level":"info", "data": {"display_key": 5, "debug_key": 5}}'

注意

在格式化消息中使用的参数不会被捕获并作为结构化数据包括在内。例如,在格式字符串字面量之后的全部内容(如"hello {}")仅用于格式字符串。

首选的日志监测方式(带类型结构的Schema)

可以使用Schema trait来实现带类型结构的日志模式。这可以通过手动实现或使用Schema derive proc-macro实现,为结构实现Schema trait并提供所有字段的setter。

use aptos_logger::{info, Schema};

#[derive(Schema)]
struct LogSchema<'a> {
    // Log using this type's Serialize impl
    a: usize,
    // Log using this type's Debug impl
    #[schema(debug)]
    b: Option<Vec<bool>>,
    // Log using this type's Display impl
    #[schema(display)]
    c: Option<&'a str>,
}

let log = LogSchema { a: 5, b: None, c: None };

// Automatic setters are named based on the field names, and handle `Option`
// None fields will be ignored
info!(log.c("radiant"));
// => '{"level":"info", "data": { "a": 5, "c": "radiant"}}'


#[derive(Schema)]
struct OtherSchema<'a> {
  val: Option<&'a str>
}

let log = LogSchema { a: 5, b: None, c: None };
let other = OtherSchema { val: None };

// Schemas can be combined
info!(
  other.val("awesome"), // First schema
  log // Second schema has fields added to it all
);
// => '{"level":"info", "data": { "a": 5, "val":"awesome"}}'

let log = LogSchema { a: 5, b: None, c: None };
let other = OtherSchema { val: None };

// Schemas can be combined with one off fields and messages like above
info!(
   other.val("awesome"), // First schema
   log, // Second schema has fields added to it all
   new_field = "new", // Basic structured fields
   "Message: {}", // Format messages
   "Some message" // Format message fields (not added to indexed fields)
);
// => {"level":"info", "message": "Message: Some message",
//     "data": { "a": 5, "val":"awesome", "new_field": "new"}}'

日志采样

有时记录大量数据是非常昂贵的。为了只记录部分时间的信息,我们添加了一个可配置执行代码频率的sample!宏。

SampleRate确定采样语句发生的频率。

use aptos_logger::{info, sample, sample::{SampleRate, Sampling}};
use std::time::Duration;

// Sampled based on frequency of events, log only every 2 logs
sample!(SampleRate::Frequency(2), info!("Long log"));

// Sampled based on time passed, log at most once a minute
sample!(SampleRate::Duration(Duration::from_secs(60)), info!("Long log"));

配置

为了捕获和发出日志,需要实例化Logger。这可以通过使用Logger类型来实现。

use aptos_logger::{Level, Logger};

Logger::builder().level(Level::Info).build();

依赖项

~10–22MB
~298K SLoC