Skip to content

Commit 92529ce

Browse files
authored
Merge pull request #25 from nullscreen/wl-FixBroadcastLoggerPatch
Fix broadcast logger patch
2 parents 8d68844 + cac7ee8 commit 92529ce

5 files changed

Lines changed: 22 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 0.9.2
4+
5+
- Fix double log issue in Rails 7.1+
6+
37
## 0.9.1
48

59
- Remove Rails 8 from CI

lib/epilog/rails/railtie.rb

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,26 @@ def self.rails_6_1_higher?
5555
end
5656
end
5757

58+
# In Rails 7.1+, the server, console, and other components (like Sidekiq)
59+
# call Rails.logger.broadcast_to() to add additional log destinations.
60+
# This causes duplicate log lines and can lead to blocks being executed
61+
# multiple times (via BroadcastLogger's method_missing delegation).
62+
#
63+
# This initializer runs AFTER :initialize_logger (which wraps the logger
64+
# in a BroadcastLogger) but BEFORE any after_initialize hooks (where
65+
# Sidekiq and others add their loggers). This ensures the no-op is in
66+
# place before anyone tries to call broadcast_to.
67+
initializer 'epilog.prevent_broadcast', after: :initialize_logger do
68+
if ::Rails.gem_version >= Gem::Version.new('7.1') && ::Rails.logger
69+
::Rails.logger.define_singleton_method(:broadcast_to) { |*| nil }
70+
end
71+
end
72+
5873
# In Rails 7.1+, ActionView::LogSubscriber::Start are attached late
5974
# in the initialization process, so we need to disable them after
6075
# initialization completes
6176
config.after_initialize do
6277
disable_rails_defaults
63-
prevent_double_logs_from_broadcast
6478
end
6579

6680
class << self
@@ -101,21 +115,6 @@ def unsubscribe_action_view_start_listeners
101115
end
102116
end
103117

104-
# In Rails 7.1+, the server and console call Rails.logger.broadcast_to(console)
105-
# which adds a second logger and causes every log line to appear twice
106-
# (e.g. custom format + default Logger format). Override broadcast_to with
107-
# a no-op to prevent adding duplicate destinations.
108-
#
109-
# This must be done in after_initialize (not at require time) because:
110-
# 1. Rails wraps the logger in a BroadcastLogger during bootstrap
111-
# 2. We need to override the instance method on the actual Rails.logger
112-
def prevent_double_logs_from_broadcast
113-
return if ::Rails.gem_version < Gem::Version.new('7.1')
114-
return unless ::Rails.logger
115-
116-
::Rails.logger.define_singleton_method(:broadcast_to) { |*| nil }
117-
end
118-
119118
def blacklisted_subscribers
120119
ActiveSupport::LogSubscriber.log_subscribers.select do |subscriber|
121120
SUBSCRIBER_BLACKLIST.include?(subscriber.class)

lib/epilog/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
module Epilog
4-
VERSION = '0.9.1'
4+
VERSION = '0.9.2'
55

66
def self.version
77
Gem::Version.new(VERSION)

spec/rails/action_controller_subscriber_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ def params(values)
198198
Rails.logger.info('middle')
199199
expect { get(:index) }.to raise_error('Something bad happened')
200200

201-
controller_log = [request: hash_including(path: '/error')]
201+
controller_log = [{ request: hash_including(path: '/error') }]
202202
expect(Rails.logger[0][4]).to match(controller_log)
203203
expect(Rails.logger[2][4]).to eq([])
204204
expect(Rails.logger[3][4]).to match(controller_log)

spec/rails/active_job_subscriber_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def perform
100100
expect { described_class.perform_later }
101101
.to raise_error('Something went wrong')
102102

103-
job_context = [job: hash_including(class: 'TestErrorJob')]
103+
job_context = [{ job: hash_including(class: 'TestErrorJob') }]
104104
expect(Rails.logger[0][4]).to match(job_context)
105105
expect(Rails.logger[2][4]).to eq([])
106106
log_line = Rails::VERSION::MAJOR >= 6 ? 4 : 3

0 commit comments

Comments
 (0)