1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #23616 from piotrj/issue_23609_logger_broadcast_silencing

Fix logger silencing for broadcasted loggers
This commit is contained in:
Rafael Mendonça França 2016-02-24 10:25:03 -03:00
commit e56e2459cb
4 changed files with 86 additions and 21 deletions

View file

@ -1,8 +1,10 @@
require 'active_support/logger_silence'
require 'active_support/logger_thread_safe_level'
require 'logger'
module ActiveSupport
class Logger < ::Logger
include ActiveSupport::LoggerThreadSafeLevel
include LoggerSilence
# Returns true if the logger destination matches one of the sources
@ -48,6 +50,11 @@ module ActiveSupport
logger.level = level
super(level)
end
define_method(:local_level=) do |level|
logger.local_level = level if logger.respond_to?(:local_level=)
super(level) if respond_to?(:local_level=)
end
end
end

View file

@ -7,39 +7,22 @@ module LoggerSilence
included do
cattr_accessor :silencer
attr_reader :local_levels
self.silencer = true
end
def after_initialize
@local_levels = Concurrent::Map.new(:initial_capacity => 2)
end
def local_log_id
Thread.current.__id__
end
def level
local_levels[local_log_id] || super
end
# Silences the logger for the duration of the block.
def silence(temporary_level = Logger::ERROR)
if silencer
begin
old_local_level = local_levels[local_log_id]
local_levels[local_log_id] = temporary_level
old_local_level = local_level
self.local_level = temporary_level
yield self
ensure
if old_local_level
local_levels[local_log_id] = old_local_level
else
local_levels.delete(local_log_id)
end
self.local_level = old_local_level
end
else
yield self
end
end
end
end

View file

@ -0,0 +1,31 @@
require 'active_support/concern'
module ActiveSupport
module LoggerThreadSafeLevel
extend ActiveSupport::Concern
def after_initialize
@local_levels = Concurrent::Map.new(:initial_capacity => 2)
end
def local_log_id
Thread.current.__id__
end
def local_level
@local_levels[local_log_id]
end
def local_level=(level)
if level
@local_levels[local_log_id] = level
else
@local_levels.delete(local_log_id)
end
end
def level
local_level || super
end
end
end

View file

@ -141,6 +141,50 @@ class LoggerTest < ActiveSupport::TestCase
assert @output.string.include?("THIS IS HERE")
end
def test_logger_silencing_works_for_broadcast
another_output = StringIO.new
another_logger = Logger.new(another_output)
@logger.extend Logger.broadcast(another_logger)
@logger.debug "CORRECT DEBUG"
@logger.silence do
@logger.debug "FAILURE"
@logger.error "CORRECT ERROR"
end
assert @output.string.include?("CORRECT DEBUG")
assert @output.string.include?("CORRECT ERROR")
assert_not @output.string.include?("FAILURE")
assert another_output.string.include?("CORRECT DEBUG")
assert another_output.string.include?("CORRECT ERROR")
assert_not another_output.string.include?("FAILURE")
end
def test_broadcast_silencing_does_not_break_plain_ruby_logger
another_output = StringIO.new
another_logger = ::Logger.new(another_output)
@logger.extend Logger.broadcast(another_logger)
@logger.debug "CORRECT DEBUG"
@logger.silence do
@logger.debug "FAILURE"
@logger.error "CORRECT ERROR"
end
assert @output.string.include?("CORRECT DEBUG")
assert @output.string.include?("CORRECT ERROR")
assert_not @output.string.include?("FAILURE")
assert another_output.string.include?("CORRECT DEBUG")
assert another_output.string.include?("CORRECT ERROR")
assert another_output.string.include?("FAILURE")
# We can't silence plain ruby Logger cause with thread safety
# but at least we don't break it
end
def test_logger_level_per_object_thread_safety
logger1 = Logger.new(StringIO.new)
logger2 = Logger.new(StringIO.new)