【Rust.Crate之tracing 诊断系统】

Rust.Crate之tracing 诊断系统

  • 前言
  • diagnostics system
  • tracing
  • 标签 #[tracing::instrument]
  • 异步函数中span
  • Instrument中的?
  • tracing_subscriber
  • tracing 的原生Subscribers
  • 总结

前言

日志对于每一个开发者来说并不陌生,开发者通常希望在程序代码中的一些需要做记录的地方加上日志,亦或在调试期间加的打印,随着需求的展开和经验的不断丰富,单纯的日志往往无法让开发者第一时间定位到问题,一般的,日志记录都是文本格式,且针对特定的数据并没有一个舒适的格式便于人类阅读,即便有时间戳等的信息,没有上下文的记录,开发者依然需要还原现场才能够排查到具体的问题原因,这对于快速迭代的日常开发和服务器线上问题的解决并不友好。

diagnostics system

诊断系统是目前主流的信息记录手段,通常情况下,使用诊断信息可以做到log日志能够做的一切,并再此基础上,诊断系统可以记录程序运行期间的主要问题场景,从begining 到ending,整个时间跨度都可以记录下来,这对日常问题排查就很有友好了,加之诊断系统一般可轻松的将信息格式化的存储落盘,尤其是在服务器的请求响应模式下,每一条的请求都将格式化记录,这也适合第三方软件对日志关键内容的提取变得十分方便。

tracing

tracing 是Rust crate。

A scoped, structured logging and diagnostics system.
tracing是一个范围明确的结构化日志的诊断系统。

先来看一段代码:

use std::io;
use tracing::*;
use tracing_subscriber;
fn test_trace(n: i32) {event!(Level::INFO, "something happened");let span = span!(Level::TRACE, "my_span");let _guard = span.enter();trace!(answer = n, "trace1: test_trace");event!(Level::INFO, "this is a test_trace ");inner_trace();
}fn inner_trace() {trace!("trace2: inner_trace");event!(Level::INFO, "this is a inner_trace ");
}fn main() {tracing_subscriber::fmt().with_max_level(Level::TRACE).with_writer(io::stdout).init();test_trace(33);
}

对上述代码进行分解:

let span = span!(Level::TRACE, "my_span");let _guard = span.enter();

span指一个跨度,即在其enter的作用域内,在enter被析构前,所有的下游跨度都会被当作当前跨度的子跨度,编译器跟踪他的生命周期,在他离开作用域时候析构。
什么是他的下游跨度?
依上述代码中:

fn test_trace(n: i32) {let span = span!(Level::TRACE, "my_span");let _guard = span.enter();trace!(answer = n, "trace1: test_trace");inner_trace();//<--- 这就是子跨度,在输出的信息中也可以证实
}

程序运行输出的信息:

2024-11-08T07:00:41.891102Z TRACE my_span: log: trace1: test_trace answer=33
2024-11-08T07:00:41.891346Z TRACE my_span: log: trace2: inner_trace

标签 #[tracing::instrument]

此标签可以直接向函数添加跨度,在每次调用此函数时都会创建带有其名称的跨度,从而实现更好的追踪。

代码示例:

use std::io;
use tracing::*;
use tracing_subscriber;
#[tracing::instrument]
fn test_span() {error!("error_my_instrument");let _ = std::time::Duration::from_secs(1);
}#[tracing::instrument]
fn test_span1() {trace!("trace_my_instrument");let _ = std::time::Duration::from_secs(1);
}fn main() {tracing_subscriber::fmt().with_max_level(Level::TRACE).with_writer(io::stdout).init();test_span();test_span1();
}

程序输出:

2024-11-08T07:38:25.875136Z ERROR test_span: log: error_my_instrument
2024-11-08T07:38:25.875266Z TRACE test_span1: log: trace_my_instrument

异步函数中span

在异步程序中,异步函数都会返回一个Future,Future又会通过poll的不断轮询推进函数执行进度,具体的可参考
Rust异步编程
而在trcing crate中的Instrument(区别于macros),Instrument是一个用于扩展future的trait,它以span为参数,每当future被轮询的时候,都会enter当前跨度,每当当前future被挂起时,都会退出当前跨度,所以再此基础上可以一直追踪future。

代码示例:

use std::io;
use tracing::*;
use tracing_subscriber;async fn test_span1() {trace!("this is a tracing");let _ = std::time::Duration::from_secs(1);
}
#[tokio::main]
async fn main() {tracing_subscriber::fmt().with_max_level(Level::TRACE).with_writer(io::stdout).init();let span = info_span!("trace_my_instrument");test_span1().instrument(span).await;
}

Instrument中的?

[?]就是使用Debug的简写,直接看代码:

use std::io;
use tracing::*;
use tracing_subscriber;#[derive(Debug)]
struct MyStruct {field: &'static str,
}
async fn test_span1() {let my_struct = MyStruct {field: "Hello world!",};event!(Level::TRACE, greeting = ?my_struct);let _ = std::time::Duration::from_secs(1);
}
#[tokio::main]
async fn main() {tracing_subscriber::fmt().with_max_level(Level::TRACE).with_writer(io::stdout).init();let span = info_span!("trace_my_instrument");test_span1().instrument(span).await;
}

tracing_subscriber

代码中的tracing_subscriber用于格式化信息输出,包括数据格式,时间格式,输出到哪里,设置tracing最大级别等等。 由此名称也可以推断,每次生成的tracing信息都由其收集。


tracing 的原生Subscribers

当Spans和Events发生时,它们会被Subscriber trait的实现记录或聚合。当事件发生以及输入或退出Span时,Subscriber 会收到通知。这些通知由以下Subscriber trait方法表示:

event, 当事件发生时触发
enter, 当进入跨度时触发
exit, 当推出跨度时触发

当我们需要高度定制化的Subscriber 时不如实现Subscriber trait来试试。

总结

至此,tracing 的基本使用方法和核心的几种方法就介绍完了,当然与之相连的还有很多crate,读者需要在需要时仔细阅读,多加练习。
开发者一般关注日志追踪的目的也时为了解决问题和提升系统,所以一般情况下错误处理和日志管理是一起讲的,thiserror , Anyhow
等都是很好的错误处理crate,错误处理在Rust中也犹如艺术一般。

“爬到山顶的最好方式就是不要去看远处的山顶,而是多注意脚下的路”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/8723.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

flink 内存配置(二):设置TaskManager内存

flink 内存配置&#xff08;一&#xff09;&#xff1a;设置Flink进程内存 flink 内存配置&#xff08;二&#xff09;&#xff1a;设置TaskManager内存 flink 内存配置&#xff08;三&#xff09;&#xff1a;设置JobManager内存 flink 内存配置&#xff08;四&#xff09;…

基于SpringBoot沉浸式戏曲文化体验系统【附源码】

基于SpringBoot沉浸式戏曲文化体验系统 效果如下&#xff1a; 系统主页面 系统登陆页面 用户管理页面 戏曲剧目管理页面 戏曲倾听页面 活动信息管理页面 个人中心页面 研究背景 随着互联网技术的飞速发展&#xff0c;传统文化传播方式正面临着前所未有的变革。戏曲作为我国传…

P3-1.【结构化程序设计】第一节——知识要点:算法、顺序结构程序设计、if语句的语法结构及各种用法

讲解视频&#xff1a; P3-1.【结构化程序设计】第一节——知识要点&#xff1a;算法、顺序结构程序设计、if语句的语法结构及各种用法 知识要点&#xff1a;算法、顺序结构程序设计、if语句的语法结构及各种用法 一、算法、顺序结构程序设计任务分析 知识要点&#xff1a;算法…

RAG三件套运行的新选择 - GPUStack

GPUStack 是一个开源的大模型即服务平台&#xff0c;可以高效整合并利用 Nvidia、Apple Metal、华为昇腾和摩尔线程等各种异构的 GPU/NPU 资源&#xff0c;提供本地私有部署大模型解决方案。 GPUStack 可以支持 RAG 系统中所需要的三种关键模型&#xff1a;Chat 对话模型&…

SSM物联网养殖管理系统-计算机毕业设计源码03998

目录 1 绪论 1.1 研究背景和意义 1.2国内外研究现状 1.3论文结构与章节安排 2 系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2经济可行性分析 2.1.3操作可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例分析 2.4 系统流程分析…

使用Python进行健康监测和分析的案例研究

健康监测和分析是指系统地使用健康数据来跟踪和评估个人或人群在一段时间内的健康状况。它包含一系列活动&#xff0c;从实时生理数据收集&#xff08;如心率&#xff0c;血压和体温&#xff09;到分析更复杂的健康记录&#xff08;包括患者病史&#xff0c;生活方式选择和遗传…

RHCE 第四次作业

一.搭建dns服务器能够对自定义的正向或者反向域完成数据解析查询。 1.配置环境 [rootlocalhost ~]# yum install bind [rootlocalhost ~]#systemctl stop firewalld [rootlocalhost ~]#setenforce 0 2.配置DNS主服务器 [rootlocalhost ~]# vim /etc/named.conf options { …

打字机效果显示

文章目录 打字机效果显示一、效果图二、视频效果三、代码 打字机效果显示 一、效果图 二、视频效果 B站-打字机效果图 打字机效果 打字机效果 三、代码 框架&#xff1a; <div class"t_title"><span>我的能力</span> <!-- <span>使…

PyQt5实战——翻译的实现,成功爬取微软翻译(可长期使用)经验总结(九)

个人博客&#xff1a;苏三有春的博客 系类往期文章&#xff1a; PyQt5实战——多脚本集合包&#xff0c;前言与环境配置&#xff08;一&#xff09; PyQt5实战——多脚本集合包&#xff0c;UI以及工程布局&#xff08;二&#xff09; PyQt5实战——多脚本集合包&#xff0c;程序…

[含文档+PPT+源码等]精品基于Nodejs实现的物流管理系统的设计与实现

基于Node.js实现的物流管理系统的设计与实现背景&#xff0c;主要源于物流行业的快速发展以及信息技术在物流管理中的广泛应用。以下是对该背景的具体阐述&#xff1a; 一、物流行业的快速发展 随着全球经济一体化的加速和电子商务的蓬勃发展&#xff0c;物流行业作为连接生产…

JavaWeb开发9

ResponseBody 类型&#xff1a;方法注解、类注解 位置&#xff1a;Controller方法上/类上 作用&#xff1a;将方法返回值直接响应&#xff0c;如果返回值类型是实体对象/集合&#xff0c;将会转换为JSON格式响应 说明&#xff1a;RestControllerControllerResponseBody; 统…

直播美颜SDK开发指南:实时美颜技术的架构与优化策略

时下&#xff0c;为了满足市场需求&#xff0c;许多企业开始开发自己的美颜SDK&#xff0c;通过集成到直播或视频应用中&#xff0c;实现实时美颜效果。接下来&#xff0c;笔者将从美颜SDK的架构设计和优化策略出发&#xff0c;深入探讨如何打造一个智能化的视频美颜平台。 一…

Leecode热题100-104.二叉树中的最大路径和

二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root &#xff0c…

第六十三周周报 GCN-CNNGA

文章目录 week 63 GCN-CNNGA摘要Abstract1. 题目2. Abstract3. 文献解读3.1 Introduction3.2 创新点 4. 网络结构4.1 数据分析4.2 混合深度学习框架的发展4.3 Mul4.4 CNN block4.5 GCN block4.6 GRU block4.7 注意力机制4.8 模型评估标准 5. 实验结果5.1 不同邻接矩阵的性能评价…

学习笔记——MathType公式编号:右编号和随章节变化

1.如何在word文档中插入带有编号的公式&#xff1f; 步骤&#xff1a;(前提是已经安装mathtype) 2.MathType公式编号怎么随章节变化&#xff1f; 想要编号级数也随标题级数进行自动变化&#xff0c;则需要插入或修改文档的“分隔符” 步骤&#xff1a;

VS+QT开发 找不到宏$(Qt_INCLUDEPATH_) $(Qt_LIBS_)

问题&#xff1a;在VSQT开发环境&#xff0c;项目右键->属性->C/C->常规->附加包含目录->宏&#xff08;位置在右下角&#xff09;->右侧新弹出的属性框内搜索Qt_INCLUDEPATH_ 找不到的场景的解决办法。

STl学习-迭代器

1.迭代器种类 这五种迭代器的声明如下&#xff1a; truct output_iterator_tag {};//输出迭代器 truct input_iterator_tag{ };//输入迭代器 truct forward iterator tag : public input iterator tag {};//向前迭代器 truct bidirectional iterator tag :public forward iter…

亲测在Windows系统安装、使用、定制Ollama服务

一、前言 1.1 Ollama介绍 Ollama是一个专为在本地环境中运行和定制大型语言模型而设计的工具。它提供了一个简单而高效的接口&#xff0c;用于创建、运行和管理这些模型&#xff0c;同时还提供了一个丰富的预构建模型库&#xff0c;可以轻松集成到各种应用程序中。Ollama的目标…

aLoNg3x.2 | CrackMe

cm下载链接&#xff1a; https://n0zom1z0.lanzoup.com/iB4Gz2el88cb 密码:38sy crack目标是让register框去掉。不让patch&#xff0c;所以要真算出Code。 第一个难点&#xff1a; DELPHI。。。窗口文字与处理函数的定义在这种地方&#xff1a; 这个cancel处&#xff0c;只要…

STl学习-函数对象

1.含有状态的函数对象类 函数对象类除了 operator()之外也可以包含其他成员。函数对象类通常含有一些数据成员这些成员被用于定制调用运算符中的操作。举个例子&#xff0c;我们将定义一个打印 string 的类。默认情况下&#xff0c;会将内容写入到cout 中&#xff0c;每个stri…