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

【Rust GUI开发入门】编写一个本地音乐播放器(15. 记录运行日志) - Jordan

本系列教程对应的代码已开源在 Github zeedle

本篇文章介绍如何将音乐播放器的运行情况持久化记录到日志文件中,这对分析程序意外情况出现的原因很有帮助!

使用最常用的env_logger,将其添加到Cargo.toml中:

env_logger = "0.11.8"

将日志同时输出到控制台和文件

与最普通的单输出不同,我们希望同时将日志输出到控制台日志文件中,这是因为:

  • 在调试程序的时候,将日志输出到控制台较为简便和迅速,打开日志文件进行观察太费时间了
  • 程序打包分发之后,以release模式运行,我们不希望出现一个黑框控制台,所以只能持久化到文件中,出现BUG时打包日志文件反馈给开发者

env_logger不直接支持多目标输出,需要自己定义输出Target

use std::{fs,io::{self, Write},path::{Path, PathBuf},
};use env_logger::Target;
use log::LevelFilter;struct MultiWriter {console: Box<dyn Write + Send>,file: Box<dyn Write + Send>,
}impl Write for MultiWriter {fn write(&mut self, buf: &[u8]) -> io::Result<usize> {self.console.write(buf)?;self.file.write(buf)}fn flush(&mut self) -> io::Result<()> {self.console.flush()?;self.file.flush()}
}fn get_log_path() -> PathBuf {let f_name = ".zeedle.log";if let Some(mut p) = home::home_dir() {p.push(f_name);p} else {PathBuf::from(f_name)}
}pub fn init_default_logger(path: Option<impl AsRef<Path>>) {let log_path = if let Some(p) = path {p.as_ref().to_path_buf()} else {get_log_path()};if log_path.exists() {if fs::metadata(&log_path).unwrap().len() > 1024 * 1024 * 10 {fs::remove_file(&log_path).expect("Failed to remove old log file");}}let log_file = fs::OpenOptions::new().create(true).write(true).append(true).open(&log_path).expect("can't open this file!");let log_target = Box::new(MultiWriter {console: Box::new(io::stdout()),file: Box::new(log_file),});env_logger::builder().format(move |buf, record| {writeln!(buf,"[{} | {} | {}:{}] --> {}",chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),record.level(),record.file().unwrap_or("unknown"),record.line().unwrap_or(0),record.args())}).filter(None, LevelFilter::Info) // 设置日志级别为Info.target(Target::Pipe(log_target)).init();
}

上述MultiWriter即为自己定义的日志输出Target,在输出时同时向控制台和指定文件写入日志消息,在初始化时指定此Target即可。

重定向Panic消息输出

对于GUI程序,在release模式下控制台不可见,如果不定向Panic消息,在GUI窗口异常退出时,将无法记录Panic的发生原因,给开发者修复问题增加难度。好在,Rust直接允许指定发生Panic时自定义回调函数:

fn main() {...logger::init_default_logger(None::<PathBuf>);// when panics happen, auto port errors to logstd::panic::set_hook(Box::new(|info| {log::error!("{}", info);}));...
}
http://www.hskmm.com/?act=detail&tid=23201

相关文章:

  • 6 种常见 AI 编程协作便捷的方法总结
  • DeploySharp开源发布:让C#部署深度学习模型更加简单
  • 别样的国庆作业大战
  • ROS2之服务
  • macOS上优雅运行Docker容器
  • 题解:CF1770H Koxia, Mahiru and Winter Festival
  • HarmonyOS之LocalStorage - 详解
  • Spring Boot Logback:实现定时任务日志与业务日志隔离 - Higurashi
  • 网络流 最小割 Dinic算法
  • 15.VLANIF(2025年9月30日) - 教程
  • 树莓派搭建NAS之一:安装系统
  • 新手Markdown学习
  • 马云归来,“新零售”不死 - 指南
  • RNN
  • 10.2笔记
  • Shell / Bash 学习
  • 【Linux 架构探幽:从入门到内核・系统编程开篇】基础指令与权限精讲,筑牢框架制作根基
  • 使用 Dart 进行验证码识别
  • 用 Rust 进行验证码识别
  • teset3
  • Java并发编程(5)
  • 定时任务详解
  • 华为wlan无线配置 - 教程
  • PINN训练新思路:把初始条件和边界约束嵌入网络架构,解决多目标优化难题
  • 可持久化数据结构
  • 2025.10.2——1黄
  • 图的匹配
  • Tarjan 算法
  • Mondriaans Dream题解
  • 网络流 最大流 Dinic 算法