From a67b81140b7acf798bf8c656bfc31ff74e6ce3ed Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 16 Aug 2019 09:12:06 -0700 Subject: [PATCH] Add reraise_write_errors keyword argument to Logger and LogDevice This allows the user to specify exception classes to treat as regular exceptions instead of being swallowed. Among other things, it is useful for having Logger work with Timeout. Fixes Ruby Bug 9115. --- lib/logger.rb | 9 +++++++-- lib/logger/log_device.rb | 9 ++++++++- test/logger/test_logger.rb | 9 +++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/logger.rb b/lib/logger.rb index 4940999..3a09c9d 100644 --- a/lib/logger.rb +++ b/lib/logger.rb @@ -575,10 +575,14 @@ def fatal!; self.level = FATAL; end # - +shift_period_suffix+: sets the format for the filename suffix # for periodic log file rotation; default is '%Y%m%d'. # See {Periodic Rotation}[rdoc-ref:Logger@Periodic+Rotation]. + # - +reraise_write_errors+: An array of exception classes, which will + # be reraised if there is an error when writing to the log device. + # The default is to swallow all exceptions raised. # def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG, progname: nil, formatter: nil, datetime_format: nil, - binmode: false, shift_period_suffix: '%Y%m%d') + binmode: false, shift_period_suffix: '%Y%m%d', + reraise_write_errors: []) self.level = level self.progname = progname @default_formatter = Formatter.new @@ -590,7 +594,8 @@ def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG, @logdev = LogDevice.new(logdev, shift_age: shift_age, shift_size: shift_size, shift_period_suffix: shift_period_suffix, - binmode: binmode) + binmode: binmode, + reraise_write_errors: reraise_write_errors) end end diff --git a/lib/logger/log_device.rb b/lib/logger/log_device.rb index 84277a2..4876adf 100644 --- a/lib/logger/log_device.rb +++ b/lib/logger/log_device.rb @@ -11,9 +11,10 @@ class LogDevice attr_reader :filename include MonitorMixin - def initialize(log = nil, shift_age: nil, shift_size: nil, shift_period_suffix: nil, binmode: false) + def initialize(log = nil, shift_age: nil, shift_size: nil, shift_period_suffix: nil, binmode: false, reraise_write_errors: []) @dev = @filename = @shift_age = @shift_size = @shift_period_suffix = nil @binmode = binmode + @reraise_write_errors = reraise_write_errors mon_initialize set_dev(log) if @filename @@ -34,16 +35,22 @@ def write(message) if @shift_age and @dev.respond_to?(:stat) begin check_shift_log + rescue *@reraise_write_errors + raise rescue warn("log shifting failed. #{$!}") end end begin @dev.write(message) + rescue *@reraise_write_errors + raise rescue warn("log writing failed. #{$!}") end end + rescue *@reraise_write_errors + raise rescue Exception => ignored warn("log writing failed. #{ignored}") end diff --git a/test/logger/test_logger.rb b/test/logger/test_logger.rb index 37d0f58..2023553 100644 --- a/test/logger/test_logger.rb +++ b/test/logger/test_logger.rb @@ -113,6 +113,15 @@ def test_string_level assert_raise(ArgumentError) { @logger.level = 'something_wrong' } end + def test_reraise_write_errors + c = Object.new + e = Class.new(StandardError) + c.define_singleton_method(:write){|*| raise e} + c.define_singleton_method(:close){} + logger = Logger.new(c, :reraise_write_errors=>[e]) + assert_raise(e) { logger.warn('foo') } + end + def test_progname assert_nil(@logger.progname) @logger.progname = "name"