当前位置: 首页 > news >正文

rust 日志记录与跟踪

日志

Cargo.toml

[dependencies]
warp = "0.3.7"
tokio = {version = "1.39.3", features = ["full"]}
serde = { version = "1.0.208", features = ["derive"] }
serde_json = "1.0.125"
#log = "0.4"
#env_logger = "0.11"
#log4rs = "1.3.0"
tracing = {version = "0.1.40", features = ["log"]}
tracing-subscriber = {version = "0.3.18", features = ["env-filter"]}
uuid = {version = "0.8", features = ["v4"]}

日志记录

env_logger

log = "0.4"
env_logger = "0.11"
#log4rs = "1.3.0"
$ RUST_LOG=info cargo run -p wrap_demo01 --bin wrap_demo01
$ RUST_LOG=debug cargo run -p wrap_demo01 --bin wrap_demo01

log4rs

log = "0.4"
#env_logger = "0.11"
log4rs = "1.3.0"

记录 HTTP 请求

  • 输出到控制台
  • 输出到文件

log4rs.yaml 配置

refresh_rate: 30 seconds
appenders:stdout:kind: consoleencoder:kind: jsonfile:kind: filepath: "stderr.log"encoder:kind : json#pattern: "{d} - {m}{n}"root:level: infoappenders:- stdout- file
log4rs::init_file("log4rs.yaml", Default::default()).unwrap();
let log = warp::log::custom(|info| {eprintln!("{} {} {} {:?} from {} with {:?}",info.method(),info.path(),info.status(),info.elapsed(),info.remote_addr().unwrap(),info.request_headers())});
let routes = get_questions.or(add_question).or(update_question).or(delete_question).or(add_answer).with(cors).with(log).recover(error::return_error);
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;

创建结构化的日志

let log = warp::log::custom(|info| {eprintln!("{} {} {} {:?} from {} with {:?}",info.method(),info.path(),info.status(),info.elapsed(),info.remote_addr().unwrap(),info.request_headers())});

日志跟踪

tracing = {version = "0.1.40", features = ["log"]}
tracing-subscriber = {version = "0.3.18", features = ["env-filter"]}
let log_filter =std::env::var("RUST_LOG").unwrap_or_else(|_| "wrap_demo01=info,warp=error".to_owned());tracing_subscriber::fmt().with_env_filter(log_filter).with_span_events(FmtSpan::CLOSE).init();// 针对某个请求设置跟踪
let get_questions = warp::get().and(warp::path("questions")).and(warp::path::end()).and(warp::query()).and(store_filter.clone()).and_then(get_questions).with(warp::trace(|info| {tracing::info_span!("get_questions request", method = %info.method(),path = %info.path(),id = %uuid::Uuid::new_v4()) // 可根据 UUID 跟踪某个请求}));// 记录每个传入的请求
let routes = get_questions.or(add_question).or(update_question).or(delete_question).or(add_answer).with(cors)//.with(log).with(warp::trace::request()).recover(error::return_error);warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
  • 未设置 instrument​ , 单个请求有3条记录

    $ cargo run -p wrap_demo01 --bin wrap_demo01
    2024-08-23T14:18:45.013769Z  INFO get_questions request{method=GET path=/questions id=5828015e-0289-47f1-9a26-16028f54dd3f}: wrap_demo01::routes::question: Querying questions
    2024-08-23T14:18:45.013967Z  INFO get_questions request{method=GET path=/questions id=5828015e-0289-47f1-9a26-16028f54dd3f}: wrap_demo01::routes::question: pagination=false
    2024-08-23T14:18:45.014083Z  INFO get_questions request{method=GET path=/questions id=5828015e-0289-47f1-9a26-16028f54dd3f}: wrap_demo01: close time.busy=355µs time.idle=45.9µs
    
#[instrument]
pub async fn get_questions(params: HashMap<String, String>,store: Store,
) -> Result<impl Reply, Rejection> {info!("Querying questions");match extract_pagination(params) {Ok(pagination) => {info!(pagination = true);let questions = store.get(Some(pagination)).await;Ok(warp::reply::json(&questions))}Err(_) => {info!(pagination = false);let questions = store.get(None).await;Ok(warp::reply::json(&questions))}}
}
  • 设置 instrument​ 后, 单个请求有 4 条记录, 且提供更详细的信息

    $ cargo run -p wrap_demo01 --bin wrap_demo01
    2024-08-23T14:22:46.631654Z  INFO get_questions request{method=GET path=/questions id=da967f3f-ff95-4dc0-bf17-935a38a863e8}:get_questions{params={} store=Store { questions: RwLock { data: {QuestionId("1"): Question { id: QuestionId("1"), title: "How?", content: "Please help!", tags: Some(["general"]) }} }, answers: RwLock { data: {} } }}: wrap_demo01::routes::question: Querying questions
    2024-08-23T14:22:46.631765Z  INFO get_questions request{method=GET path=/questions id=da967f3f-ff95-4dc0-bf17-935a38a863e8}:get_questions{params={} store=Store { questions: RwLock { data: {QuestionId("1"): Question { id: QuestionId("1"), title: "How?", content: "Please help!", tags: Some(["general"]) }} }, answers: RwLock { data: {} } }}: wrap_demo01::routes::question: pagination=false
    2024-08-23T14:22:46.631851Z  INFO get_questions request{method=GET path=/questions id=da967f3f-ff95-4dc0-bf17-935a38a863e8}:get_questions{params={} store=Store { questions: RwLock { data: {QuestionId("1"): Question { id: QuestionId("1"), title: "How?", content: "Please help!", tags: Some(["general"]) }} }, answers: RwLock { data: {} } }}: wrap_demo01::routes::question: close time.busy=212µs time.idle=9.73µs
    2024-08-23T14:22:46.632025Z  INFO get_questions request{method=GET path=/questions id=da967f3f-ff95-4dc0-bf17-935a38a863e8}: wrap_demo01: close time.busy=520µs time.idle=87.6µs
    

日志调试

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 沉浸式解压小视频在哪找?非常减压的几个视频素材网站分享
  • NLP发展脉络-->特征优化阶段
  • SAM 2——视频和图像实时实例分割的全新开源模型
  • matlab实现粒子群优化算法
  • AI学习记录 - 怎么理解 torch 的 nn.Conv2d
  • Godot《躲避小兵》实战之创建游戏主场景
  • 怎么写spring security的账号密码成功失败处理器并且加一个验证码过滤器
  • 错误提示:‘interface‘ declarations can only be used in TypeScript files
  • 解读FastAPI异步化为transformers模型打造高性能接口解析
  • 【在Linux世界中追寻伟大的One Piece】应用层协议HTTP
  • 关于Java中@Component的使用中出现@Autowired为NULL的问题
  • 模型 FIRE沟通法
  • 视频插帧—— RIFE 和 IFNet 的机制和应用
  • Code Practice Journal | Day53_Graph04
  • 力扣1442.形成两个异或相等数组的三元组数目
  • 2017 前端面试准备 - 收藏集 - 掘金
  • E-HPC支持多队列管理和自动伸缩
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • js算法-归并排序(merge_sort)
  • JS字符串转数字方法总结
  • maya建模与骨骼动画快速实现人工鱼
  • underscore源码剖析之整体架构
  • 分布式熔断降级平台aegis
  • 嵌入式文件系统
  • 原生js练习题---第五课
  • 怎么把视频里的音乐提取出来
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • Hibernate主键生成策略及选择
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • ​学习一下,什么是预包装食品?​
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • #vue3 实现前端下载excel文件模板功能
  • (2)STL算法之元素计数
  • (day6) 319. 灯泡开关
  • (Python) SOAP Web Service (HTTP POST)
  • (八)Flink Join 连接
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (一)、软硬件全开源智能手表,与手机互联,标配多表盘,功能丰富(ZSWatch-Zephyr)
  • (一)插入排序
  • (转)http-server应用
  • **PHP分步表单提交思路(分页表单提交)
  • .gitignore文件设置了忽略但不生效
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .NET中两种OCR方式对比
  • @Autowired @Resource @Qualifier的区别
  • @ModelAttribute 注解
  • @test注解_Spring 自定义注解你了解过吗?
  • [ 物联网 ]拟合模型解决传感器数据获取中数据与实际值的误差的补偿方法
  • [AIGC] HashMap的扩容与缩容:动态调整容量以提高性能
  • [AIGC] MySQL存储引擎详解
  • [ANT] 项目中应用ANT
  • [Asp.net MVC]Bundle合并,压缩js、css文件