如何使用跟踪库?



我这里有一个非常简单的代码示例,它只想获取我传入的列表的第一项。我一直在尝试使用跟踪来检测代码以帮助调试应用程序,但坦率地说,文档太复杂了,我无法完全理解。

use std::fmt::Debug;
use tracing::{span, Level, event};
fn main() {
pub fn calculate<T: Debug, const N: usize>(data_set: [T; N]) -> (i32, i32) {
// Tracing BoilerPlate
event!(Level::INFO, "something happened");
let span = span!(Level::INFO, "my_span");
let _guard = span.enter();

// Key Code 
let _var = data_set.get(0);
println!("Output_1: {:?}", data_set.get(0)); 

event!(Level::DEBUG, "something happened inside my_span");

// Ignore
return (0, 0)
}
let data = [1509, 1857, 1736, 1815, 1576];
let _result = calculate(data);
}

特别是在这里,我不明白在哪里可以查看event!日志。它们似乎不会打印到任何窗口或文件或任何东西。

有人可以指导我在哪里可以找到这些调试日志或为我提供有关如何使用跟踪 crate 的简化说明吗?

这是tracing的基本实现,它使用名为tracing-subscriber的合作伙伴 crate 将信息输出到日志文件(debug.log 在存储库根目录中)和/或stdout(包含更多代码)

要找到这些如何将tracingtracing-subscriber结合在一起的切实示例,您必须非常深入地研究文档:转到tracing-subscriber箱,然后转到Layer特征,然后转到Module level documentation。这是一个替代链接。

坦率地说,文档太复杂了,我无法完全理解。

我认为,要记录这两个板条箱,还有很多工作要做。客观地说,初学者并不容易理解正在发生的事情。文档用高度复杂的语言描述了板条箱,但未能正确地教给新手基础知识。需要创建有关此主题的更完整的资源或快速入门指南。

可以使用更简单的调试工具,这些工具可以正确地教您如何使用它的板条箱Flexi-logger提供了一个代码示例文档页面,其中熟练地解释了如何使用板条箱。Flexi-loggerLog箱协同工作,以输出log files以及stdoutstderr

Here is the Tracing Implementation


use tracing_subscriber::{filter, prelude::*};
use std::{fs::File, sync::Arc};
// A layer that logs events to stdout using the human-readable "pretty"
// format.
fn main() {
let stdout_log = tracing_subscriber::fmt::layer()
.pretty();
// A layer that logs events to a file.
let file = File::create("debug.log");
let file = match file  {Ok(file) => file,Err(error) => panic!("Error: {:?}",error),};
let debug_log = tracing_subscriber::fmt::layer()
.with_writer(Arc::new(file));
// A layer that collects metrics using specific events.
let metrics_layer = /* ... */ filter::LevelFilter::INFO;
tracing_subscriber::registry()
.with(
stdout_log
// Add an `INFO` filter to the stdout logging layer
.with_filter(filter::LevelFilter::INFO)
// Combine the filtered `stdout_log` layer with the
// `debug_log` layer, producing a new `Layered` layer.
.and_then(debug_log)
// Add a filter to *both* layers that rejects spans and
// events whose targets start with `metrics`.
.with_filter(filter::filter_fn(|metadata| {
!metadata.target().starts_with("metrics")
}))
)
.with(
// Add a filter to the metrics label that *only* enables
// events whose targets start with `metrics`.
metrics_layer.with_filter(filter::filter_fn(|metadata| {
metadata.target().starts_with("metrics")
}))
)
.init();
// This event will *only* be recorded by the metrics layer.
tracing::info!(target: "metrics::cool_stuff_count", value = 42);
// This event will only be seen by the debug log file layer:
tracing::debug!("this is a message, and part of a system of messages");
// This event will be seen by both the stdout log layer *and*
// the debug log file layer, but not by the metrics layer.
tracing::warn!("the message is a warning about danger!");
}

跟踪库本身不显示任何输出或写入任何文件。它只是一个外观,旨在允许开发人员以不可知的方式触发分组到跨度中的事件,这与这些事件和跨度的处理方式不同。该库很复杂,因为有多种方法可以跟踪跨度和使用事件,并且需要在轻量级基础结构中支持它们。

但是,作为用户,您无需真正担心这些。您需要做的就是使用trace!debug!info!warn!error!#[instrument]宏来描述您的代码正在做什么。然后,如果您正在编写一个应该对这些事件和跨度执行某些操作的程序,则应设置一个Subscriber

启动并运行打印到控制台的日志的最简单方法是使用跟踪订阅者 crate 中的基本格式订阅者,然后您将看到记录到控制台的事件:

use tracing::{info, debug};
#[tracing::instrument(ret)]
fn calculate(data_set: &[i32]) -> i32 {
info!("starting calculations");
let first = data_set.first();
debug!("received {:?} as first element", first);

let last = data_set.last();
debug!("received {:?} as last element", last);
first.unwrap_or(&0) + last.unwrap_or(&0)
}
fn main() {
tracing_subscriber::fmt().init();
// start running your code
calculate(&[1509, 1857, 1736, 1815, 1576]);
}
2022-09-15T16:11:47.830218Z  INFO calculate{data_set=[1509, 1857, 1736, 1815, 1576]}: mycrate: starting calculations
2022-09-15T16:11:47.830545Z  INFO calculate{data_set=[1509, 1857, 1736, 1815, 1576]}: mycrate: return=3085

因此,fmt().init()可以让你匆忙行事;它完成了创建具有一堆合理默认值的Subscriber的工作,并将自己注册为全局订阅者。它也非常灵活,您可能会注意到上面的输出不包括debug!事件,并且您可能不关心在每条消息中显示板条箱名称。可以配置:

tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.with_target(false)
.init();
2022-09-15T16:18:51.316695Z  INFO calculate{data_set=[1509, 1857, 1736, 1815, 1576]}: starting calculations
2022-09-15T16:18:51.316970Z DEBUG calculate{data_set=[1509, 1857, 1736, 1815, 1576]}: received Some(1509) as first element
2022-09-15T16:18:51.317214Z DEBUG calculate{data_set=[1509, 1857, 1736, 1815, 1576]}: received Some(1576) as last element
2022-09-15T16:18:51.317381Z  INFO calculate{data_set=[1509, 1857, 1736, 1815, 1576]}: return=3085

一切都设计得很灵活:如果您想发送到文件而不是标准输出,则有.with_writer()。如果要将日志发送到多个位置,可以使用Registry编写多个订阅者。如果您只想根据级别、源或内容过滤某些事件,则.with_filter.如果要以 JSON 格式而不是人类可读的文本登录,可以使用.json()

常见的下一步是设置EnvFilter,这将允许您根据环境变量配置要记录的事件,而不是尝试在代码中配置它。设置最高级别可以像"info"/"trace"一样简单,也可以像"warn,mycrate=debug"一样复杂(从我的 crate 中记录调试事件,只记录其他任何内容的警告)。

除此之外,您可能正在寻找更专注的东西。就像您需要以特定格式登录一样。或者,您需要将事件直接发送到外部提供程序。或者,您只是在寻找一种不同的方法来查看数据。在跟踪的相关板条箱部分查找其他有望满足您的需求的Subscriber

最新更新