Rust中使用fern日志库时,如何处理可选路径与虚拟文件写入?
Fern日志记录器可选文件路径的解决方案
问题描述
原有代码使用fern库搭建日志记录器,默认同时输出到标准输出和output.log文件。现在需要修改setup_logger函数,使其接受Option<std::path::PathBuf>类型的可选日志路径参数:
fn setup_logger(log_path: Option<std::path::PathBuf>) -> Result<(), log::SetLoggerError>
尝试通过match分支处理可选路径时,遇到了类型不兼容问题:fern::log_file(path)?返回的是文件类型的Sink,而std::io::sink()的类型无法与之匹配。
解决方案
核心思路是将两个分支的Sink统一装箱为Box<dyn fern::Sink>类型,利用Rust的 trait 对象特性消除类型差异。具体修改如下:
将原代码中的(a)行替换为:
.chain(match log_path { Some(path) => Box::new(fern::log_file(path)?) as Box<dyn fern::Sink>, None => Box::new(fern::Output::from(std::io::sink())) as Box<dyn fern::Sink>, })
完整修改后的代码
use log::{debug, error, info, trace, warn}; use std::path::PathBuf; fn setup_logger(log_path: Option<PathBuf>) -> Result<(), log::SetLoggerError> { fern::Dispatch::new() .format(|out, message, record| { out.finish(format_args!( "{}[{}][{}] {}", chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), record.target(), record.level(), message )) }) .level(log::LevelFilter::Debug) .chain(std::io::stdout()) .chain(match log_path { Some(path) => Box::new(fern::log_file(path)?) as Box<dyn fern::Sink>, None => Box::new(fern::Output::from(std::io::sink())) as Box<dyn fern::Sink>, }) .apply()?; Ok(()) }
说明
fern::log_file(path)?返回的FileSink实现了fern::Sinktrait,可以被装箱为Box<dyn fern::Sink>std::io::sink()是一个空写入器,不会产生任何输出,通过fern::Output::from包装后也实现了fern::Sink,同样可以装箱为统一类型- 这样match的两个分支类型完全一致,解决了类型不兼容的问题
内容的提问来源于stack exchange,提问作者Eray Erdin
相关产品推荐
相关产品推荐

