-
Notifications
You must be signed in to change notification settings - Fork 21.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add BroadcastLogger#deep_dup
#49720
Add BroadcastLogger#deep_dup
#49720
Conversation
6645484
to
134ad0c
Compare
Are you calling this directly or through some other API? |
duplicate = dup | ||
|
||
broadcasts.each do |broadcast| | ||
duplicate.stop_broadcasting_to(broadcast) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we care that this might drop messages?
@@ -218,6 +218,17 @@ def fatal! | |||
dispatch { |logger| logger.fatal! } | |||
end | |||
|
|||
def deep_dup | |||
duplicate = dup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about just doing self.class.new(*@broadcasts.map(&:dup)
?
To me, BroadcastLogger
is a rather lightweight shell around the loggers, so there's not much value in duplicating it.
This way you'd avoid having to call #stop_broadcasting_to
. (Also note that #stop_broadcasting_to
is equivalent to removing an item from @broadcasts
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I just realized that calling dup
like you do is not going to work. Even @broadcasts
itself is not duplicated:
bl1 = ActiveSupport::BroadcastLogger.new
bl2 = bl1.dup
bl1.broadcasts.__id__ == bl2.broadcasts.__id__
#=> true
One more reason to use self.class.new
instead. 😉
|
||
duplicate = broadcast_logger.deep_dup | ||
|
||
assert_equal ::Logger::WARN, duplicate.broadcasts.sole.level |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering my other comments, I'd suggest adding assertions that confirm the original BroadcastLogger
(and its list of @broadcasts
) was not altered, and is not tied to its duplicate.
assert_equal logger, broadcast_logger.broadcasts.sole
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tried it and got this error:
Failure:
ActiveSupport::BroadcastLoggerTest#test_#deep_dup_duplicates_the_broadcasts [activesupport/test/broadcast_logger_test.rb:300]:
No visible difference in the ActiveSupport::BroadcastLoggerTest::CustomLogger#inspect output.
You should look at the implementation of #== on ActiveSupport::BroadcastLoggerTest::CustomLogger or its members.
#<ActiveSupport::BroadcastLoggerTest::CustomLogger:0xXXXXXX @adds=[], @closed=false, @chevrons=[], @level=2, @local_level=0, @progname=nil, @formatter=nil>
Very curious. Looking at the doc for MiniTest's assert_equal
, I found this:
If there is no visible difference but the assertion fails, you should suspect that your #== is buggy, or your inspect output is missing crucial details.
Instead I tried using assert_same
:
assert_same logger, broadcast_logger.broadcasts.sole
refute_same logger, duplicate.broadcasts.sole
assert_equal ::Logger::WARN, duplicate.broadcasts.sole.level
And then I get the failure I expected:
Failure:
ActiveSupport::BroadcastLoggerTest#test_#deep_dup_duplicates_the_broadcasts [activesupport/test/broadcast_logger_test.rb:300]:
Expected #<ActiveSupport::BroadcastLoggerTest::CustomLogger:0x00000001030de158 @adds=[], @closed=false, @chevrons=[], @level=2, @local_level=0, @progname=nil, @formatter=nil> (oid=5640) to be the same as #<ActiveSupport::BroadcastLoggerTest::CustomLogger:0x00000001030de1f8 @adds=[], @closed=false, @chevrons=[], @level=2, @local_level=0, @progname=nil, @formatter=nil> (oid=5660).
Here are the changes that I would suggest to make: diff --git i/activesupport/lib/active_support/broadcast_logger.rb w/activesupport/lib/active_support/broadcast_logger.rb
index 9454c456b4..605f275736 100644
--- i/activesupport/lib/active_support/broadcast_logger.rb
+++ w/activesupport/lib/active_support/broadcast_logger.rb
@@ -219,14 +219,10 @@ def fatal!
end
def deep_dup
- duplicate = dup
-
- broadcasts.each do |broadcast|
- duplicate.stop_broadcasting_to(broadcast)
- duplicate.broadcast_to(broadcast.dup)
+ self.class.new(*@broadcasts.map(&:dup)).tap do |logger|
+ logger.formatter = formatter.dup
+ logger.progname = progname.dup
end
-
- duplicate
end
private
diff --git i/activesupport/test/broadcast_logger_test.rb w/activesupport/test/broadcast_logger_test.rb
index d018e79018..703bb445cf 100644
--- i/activesupport/test/broadcast_logger_test.rb
+++ w/activesupport/test/broadcast_logger_test.rb
@@ -297,8 +297,9 @@ def info(msg, &block)
duplicate = broadcast_logger.deep_dup
+ assert_same logger, broadcast_logger.broadcasts.sole
+ refute_same logger, duplicate.broadcasts.sole
assert_equal ::Logger::WARN, duplicate.broadcasts.sole.level
- assert_not_equal logger, duplicate.broadcasts.sole
end
class CustomLogger One more thing: using |
I agree with @davidstosik's suggestion. Unless there's a reason users might want a "shallow" This can be best done by defining |
134ad0c
to
c14b98c
Compare
Add `BroadcastLogger#deep_dup`
@broadcasts = [] | ||
@progname = other.progname.dup | ||
@formatter = other.formatter.dup | ||
|
||
broadcast_to(*other.broadcasts.map(&:dup)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Late nitpick, but I don't get why this was better than doing @broadcasts = other.broadcasts.map(&:dup)
in the first line. 🤔
Motivation / Background
This Pull Request has been created because, I want to easily duplicate instances of
BroadcastLogger
in my app. Just callingdup
is no good because it does not duplicate thebroadcasts
. So I believe we could use adeep_dup
method.Detail
This Pull Request adds a
ActiveSupport::BroadcastLogger#deep_dup
. Callingdeep_dup
dups the broadcast logger, and then iterates through each of it's broadcasts and duplicates them.Additional information
N/A
Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]