Skip to content

Commit 9ee3da1

Browse files
authored
Merge pull request rails#53093 from armstrjare/broadcast-logger-with-block
Fix ActiveSupport::BroadcastLogger from executing a block argument for each logger (tagged, info, etc.)
2 parents 368465e + c091113 commit 9ee3da1

File tree

3 files changed

+75
-75
lines changed

3 files changed

+75
-75
lines changed

activesupport/lib/active_support/broadcast_logger.rb

Lines changed: 46 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ class BroadcastLogger
7676

7777
# Returns all the logger that are part of this broadcast.
7878
attr_reader :broadcasts
79-
attr_reader :formatter
8079
attr_accessor :progname
8180

8281
def initialize(*loggers)
@@ -105,62 +104,36 @@ def stop_broadcasting_to(logger)
105104
@broadcasts.delete(logger)
106105
end
107106

108-
def level
109-
@broadcasts.map(&:level).min
110-
end
111-
112-
def <<(message)
113-
dispatch { |logger| logger.<<(message) }
114-
end
115-
116-
def add(...)
117-
dispatch { |logger| logger.add(...) }
118-
end
119-
alias_method :log, :add
120-
121-
def debug(...)
122-
dispatch { |logger| logger.debug(...) }
123-
end
124-
125-
def info(...)
126-
dispatch { |logger| logger.info(...) }
127-
end
128-
129-
def warn(...)
130-
dispatch { |logger| logger.warn(...) }
131-
end
132-
133-
def error(...)
134-
dispatch { |logger| logger.error(...) }
135-
end
136-
137-
def fatal(...)
138-
dispatch { |logger| logger.fatal(...) }
139-
end
140-
141-
def unknown(...)
142-
dispatch { |logger| logger.unknown(...) }
107+
def local_level=(level)
108+
@broadcasts.each do |logger|
109+
logger.local_level = level if logger.respond_to?(:local_level=)
110+
end
143111
end
144112

145-
def formatter=(formatter)
146-
dispatch { |logger| logger.formatter = formatter }
147-
148-
@formatter = formatter
149-
end
113+
def local_level
114+
loggers = @broadcasts.select { |logger| logger.respond_to?(:local_level) }
150115

151-
def level=(level)
152-
dispatch { |logger| logger.level = level }
116+
loggers.map do |logger|
117+
logger.local_level
118+
end.first
153119
end
154-
alias_method :sev_threshold=, :level=
155120

156-
def local_level=(level)
157-
dispatch do |logger|
158-
logger.local_level = level if logger.respond_to?(:local_level=)
159-
end
121+
LOGGER_METHODS = %w[
122+
<< log add debug info warn error fatal unknown
123+
level= sev_threshold= close
124+
formatter formatter=
125+
] # :nodoc:
126+
LOGGER_METHODS.each do |method|
127+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
128+
def #{method}(...)
129+
dispatch(:#{method}, ...)
130+
end
131+
RUBY
160132
end
161133

162-
def close
163-
dispatch { |logger| logger.close }
134+
# Returns the lowest level of all the loggers in the broadcast.
135+
def level
136+
@broadcasts.map(&:level).min
164137
end
165138

166139
# True if the log level allows entries with severity +Logger::DEBUG+ to be written
@@ -171,7 +144,7 @@ def debug?
171144

172145
# Sets the log level to +Logger::DEBUG+ for the whole broadcast.
173146
def debug!
174-
dispatch { |logger| logger.debug! }
147+
dispatch(:debug!)
175148
end
176149

177150
# True if the log level allows entries with severity +Logger::INFO+ to be written
@@ -182,7 +155,7 @@ def info?
182155

183156
# Sets the log level to +Logger::INFO+ for the whole broadcast.
184157
def info!
185-
dispatch { |logger| logger.info! }
158+
dispatch(:info!)
186159
end
187160

188161
# True if the log level allows entries with severity +Logger::WARN+ to be written
@@ -193,7 +166,7 @@ def warn?
193166

194167
# Sets the log level to +Logger::WARN+ for the whole broadcast.
195168
def warn!
196-
dispatch { |logger| logger.warn! }
169+
dispatch(:warn!)
197170
end
198171

199172
# True if the log level allows entries with severity +Logger::ERROR+ to be written
@@ -204,7 +177,7 @@ def error?
204177

205178
# Sets the log level to +Logger::ERROR+ for the whole broadcast.
206179
def error!
207-
dispatch { |logger| logger.error! }
180+
dispatch(:error!)
208181
end
209182

210183
# True if the log level allows entries with severity +Logger::FATAL+ to be written
@@ -215,21 +188,35 @@ def fatal?
215188

216189
# Sets the log level to +Logger::FATAL+ for the whole broadcast.
217190
def fatal!
218-
dispatch { |logger| logger.fatal! }
191+
dispatch(:fatal!)
219192
end
220193

221194
def initialize_copy(other)
222195
@broadcasts = []
223196
@progname = other.progname.dup
224-
@formatter = other.formatter.dup
225197

226198
broadcast_to(*other.broadcasts.map(&:dup))
227199
end
228200

229201
private
230-
def dispatch(&block)
231-
@broadcasts.each { |logger| block.call(logger) }
232-
true
202+
def dispatch(method, *args, **kwargs, &block)
203+
if block_given?
204+
# Maintain semantics that the first logger yields the block
205+
# as normal, but subsequent loggers won't re-execute the block.
206+
# Instead, the initial result is immediately returned.
207+
called, result = false, nil
208+
block = proc { |*args, **kwargs|
209+
if called then result
210+
else
211+
called = true
212+
result = yield(*args, **kwargs)
213+
end
214+
}
215+
end
216+
217+
@broadcasts.map { |logger|
218+
logger.send(method, *args, **kwargs, &block)
219+
}.first
233220
end
234221

235222
def method_missing(name, ...)

activesupport/test/broadcast_logger_test.rb

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -268,14 +268,28 @@ def info(msg, &block)
268268
assert(logger.foo)
269269
end
270270

271-
test "calling a method that accepts a block" do
272-
logger = BroadcastLogger.new(CustomLogger.new)
271+
test "methods are called on each logger" do
272+
calls = 0
273+
loggers = [CustomLogger.new, FakeLogger.new, CustomLogger.new].each do |logger|
274+
logger.define_singleton_method(:special_method) do
275+
calls += 1
276+
end
277+
end
278+
logger = BroadcastLogger.new(*loggers)
279+
logger.special_method
280+
assert_equal(3, calls)
281+
end
273282

274-
called = false
275-
logger.bar do
276-
called = true
283+
test "calling a method that accepts a block is yielded only once" do
284+
called = 0
285+
logger.info do
286+
called += 1
287+
"Hello"
277288
end
278-
assert(called)
289+
290+
assert_equal 1, called, "block should be called just once"
291+
assert_equal [[::Logger::INFO, "Hello", nil]], log1.adds
292+
assert_equal [[::Logger::INFO, "Hello", nil]], log2.adds
279293
end
280294

281295
test "calling a method that accepts args" do
@@ -356,27 +370,27 @@ def qux(param:)
356370
true
357371
end
358372

359-
def debug(message, &block)
373+
def debug(message = nil, &block)
360374
add(::Logger::DEBUG, message, &block)
361375
end
362376

363-
def info(message, &block)
377+
def info(message = nil, &block)
364378
add(::Logger::INFO, message, &block)
365379
end
366380

367-
def warn(message, &block)
381+
def warn(message = nil, &block)
368382
add(::Logger::WARN, message, &block)
369383
end
370384

371-
def error(message, &block)
385+
def error(message = nil, &block)
372386
add(::Logger::ERROR, message, &block)
373387
end
374388

375-
def fatal(message, &block)
389+
def fatal(message = nil, &block)
376390
add(::Logger::FATAL, message, &block)
377391
end
378392

379-
def unknown(message, &block)
393+
def unknown(message = nil, &block)
380394
add(::Logger::UNKNOWN, message, &block)
381395
end
382396

@@ -385,7 +399,8 @@ def <<(x)
385399
end
386400

387401
def add(message_level, message = nil, progname = nil, &block)
388-
@adds << [message_level, message, progname] if message_level >= local_level
402+
@adds << [message_level, block_given? ? block.call : message, progname] if message_level >= local_level
403+
true
389404
end
390405

391406
def debug?

railties/lib/rails/application/bootstrap.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@ module Bootstrap
5959
end
6060
else
6161
Rails.logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase)
62-
broadcast_logger = ActiveSupport::BroadcastLogger.new(Rails.logger)
63-
broadcast_logger.formatter = Rails.logger.formatter
64-
Rails.logger = broadcast_logger
62+
Rails.logger = ActiveSupport::BroadcastLogger.new(Rails.logger)
6563
end
6664
end
6765

0 commit comments

Comments
 (0)