Skip to content

Commit 96ab01e

Browse files
committed
Maintain a seperate buffer for each thread
1 parent c1a8690 commit 96ab01e

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

activesupport/lib/active_support/buffered_logger.rb

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,10 @@ def silence(temporary_level = ERROR)
3333

3434
attr_accessor :level
3535
attr_reader :auto_flushing
36-
attr_reader :buffer
3736

3837
def initialize(log, level = DEBUG)
3938
@level = level
40-
@buffer = []
39+
@buffer = {}
4140
@auto_flushing = 1
4241
@guard = Mutex.new
4342

@@ -60,9 +59,7 @@ def add(severity, message = nil, progname = nil, &block)
6059
# If a newline is necessary then create a new message ending with a newline.
6160
# Ensures that the original message is not mutated.
6261
message = "#{message}\n" unless message[-1] == ?\n
63-
@guard.synchronize do
64-
buffer << message
65-
end
62+
buffer << message
6663
auto_flush
6764
message
6865
end
@@ -96,8 +93,8 @@ def auto_flushing=(period)
9693
def flush
9794
@guard.synchronize do
9895
unless buffer.empty?
99-
old_buffer = @buffer
100-
@buffer = []
96+
old_buffer = buffer
97+
clear_buffer
10198
@log.write(old_buffer.join)
10299
end
103100
end
@@ -113,5 +110,13 @@ def close
113110
def auto_flush
114111
flush if buffer.size >= @auto_flushing
115112
end
113+
114+
def buffer
115+
@buffer[Thread.current] ||= []
116+
end
117+
118+
def clear_buffer
119+
@buffer[Thread.current] = []
120+
end
116121
end
117122
end

activesupport/test/buffered_logger_test.rb

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def test_should_not_mutate_message
7070
end
7171

7272
@logger.flush
73-
assert !@output.string.empty?, @logger.buffer.size
73+
assert !@output.string.empty?, @logger.send(:buffer).size
7474
end
7575

7676
define_method "test_disabling_auto_flush_with_#{disable.inspect}_should_flush_at_max_buffer_size_as_failsafe" do
@@ -83,10 +83,10 @@ def test_should_not_mutate_message
8383
end
8484

8585
@logger.info 'there it is.'
86-
assert !@output.string.empty?, @logger.buffer.size
86+
assert !@output.string.empty?, @logger.send(:buffer).size
8787
end
8888
end
89-
89+
9090
def test_should_know_if_its_loglevel_is_below_a_given_level
9191
ActiveSupport::BufferedLogger::Severity.constants.each do |level|
9292
@logger.level = ActiveSupport::BufferedLogger::Severity.const_get(level) - 1
@@ -105,7 +105,7 @@ def test_should_auto_flush_every_n_messages
105105
@logger.info 'there it is.'
106106
assert !@output.string.empty?, @output.string
107107
end
108-
108+
109109
def test_should_create_the_log_directory_if_it_doesnt_exist
110110
tmp_directory = File.join(File.dirname(__FILE__), "tmp")
111111
log_file = File.join(tmp_directory, "development.log")
@@ -115,4 +115,25 @@ def test_should_create_the_log_directory_if_it_doesnt_exist
115115
ensure
116116
FileUtils.rm_rf(tmp_directory)
117117
end
118+
119+
def test_logger_should_maintain_separate_buffers_for_each_thread
120+
@logger.auto_flushing = false
121+
122+
a = Thread.new do
123+
@logger.info("a"); Thread.pass;
124+
@logger.info("b"); Thread.pass;
125+
@logger.info("c"); @logger.flush
126+
end
127+
128+
b = Thread.new do
129+
@logger.info("x"); Thread.pass;
130+
@logger.info("y"); Thread.pass;
131+
@logger.info("z"); @logger.flush
132+
end
133+
134+
a.join
135+
b.join
136+
137+
assert_equal "a\nb\nc\nx\ny\nz\n", @output.string
138+
end
118139
end

0 commit comments

Comments
 (0)