Ruby如何为不同日志目标设置差异化日志级别
实现Ruby日志分级别输出到控制台和文件
我之前也碰到过一模一样的需求,用Ruby标准库的Logger就能完美解决,核心思路就是给同一个Logger实例挂两个输出设备——文件和控制台,然后分别给每个设备设置独立的日志级别,同时保留环境变量的全局控制能力。
下面是直接能用的实现代码:
require 'logger' # 先做个环境变量到Logger级别的映射,方便转换 LOG_LEVEL_MAP = { 'debug' => Logger::DEBUG, 'info' => Logger::INFO, 'warn' => Logger::WARN, 'error' => Logger::ERROR, 'fatal' => Logger::FATAL }.freeze # 读取环境变量的全局级别,默认用Info global_log_level = LOG_LEVEL_MAP.fetch(ENV['LOG_LEVEL']&.downcase, Logger::INFO) # 控制台级别取全局级别和Info的最大值,确保永远不会输出Debug console_level = [global_log_level, Logger::INFO].max # 文件级别强制设为Debug,不管全局怎么配置都记录所有Debug及以上日志 file_level = Logger::DEBUG # 创建Logger实例,先绑定控制台输出 logger = Logger.new(STDOUT) # 自定义日志格式(可选,也可以用默认格式) logger.formatter = proc do |severity, timestamp, _, msg| "[#{timestamp.strftime('%Y-%m-%d %H:%M:%S')}] #{severity.ljust(5)}: #{msg}\n" end # 添加文件输出设备,并指定它的级别 log_file = File.open('app.log', 'a') file_device = Logger::LogDevice.new(log_file) logger.add(file_device, file_level) # 最后把控制台的级别设置好 logger.level = console_level # 测试一下效果 logger.debug('这条Debug日志只会出现在文件里') logger.info('这条Info日志控制台和文件都会有') logger.warn('这条Warn日志也是两边都有') logger.error('Error日志同样两边输出') # 记得程序退出时关闭日志文件,避免资源泄漏 at_exit { log_file.close }
关键逻辑解释:
- 多设备分离:Ruby的
Logger支持通过add方法添加多个输出设备,每个设备可以单独设置日志级别,这是实现分渠道输出的核心。 - 控制台级别兜底:用
[global_log_level, Logger::INFO].max做兜底,就算环境变量设成了debug,控制台也只会从Info级别开始输出,完全符合需求。 - 文件级别强制:文件设备的级别固定为
Logger::DEBUG,不管环境变量怎么调整,所有Debug及以上的日志都会被写入文件。 - 环境变量兼容:保留了环境变量控制全局级别的能力,比如如果环境变量设为
warn,控制台只会输出Warn及以上的日志,而文件依然会完整记录从Debug到Fatal的所有日志。
内容的提问来源于stack exchange,提问作者scorpion35
相关产品推荐
相关产品推荐

