0.2.7 2022年8月16日
0.2.6 2022年8月13日
0.2.2 2022年7月22日
0.1.7 2022年7月9日
0.1.0 2022年5月26日

#aptos 中排名第 74

每月下载量 30
88 个crate中使用了(其中 53 个直接使用)

Apache-2.0

95KB
2K 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 trait来实现带类型的日志记录模式。这可以通过手动实现或使用 Schema derive proc-macro来实现,为结构实现 Schema trait,并为所有字段提供设置器。

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();

依赖

~9–23MB
~292K SLoC