Skip to content

Commit 1b4e472

Browse files
committed
Clear level overrides in #dup and #clone
Cloning loggers can be used, for example, to create different loggers for different classes/components/subsystems that share the same log_dev and other configuration (possibly a subclass of Logger), but with different verbosity levels, formatters, etc. But, that doesn't work if they share `@level_override`. Rather than use OverrideMap.new, the existing `@level_override` is cloned and cleared, to preserve `@level_override`'s class.
1 parent 4576128 commit 1b4e472

2 files changed

Lines changed: 28 additions & 1 deletion

File tree

lib/logger.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ class Logger
380380
include Severity
381381

382382
# Must respond to .new and return a Hash-like object.
383-
# The returned object must respond to #[], #[]=, #delete.
383+
# The returned object must respond to #[], #[]=, #delete, #dup, and #clear.
384384
#
385385
# ObjectSpace::WeakKeyMap when supported.
386386
OverrideMap =
@@ -800,6 +800,11 @@ def level_override
800800
@level_override ||= OverrideMap.new
801801
end
802802

803+
def initialize_copy(other)
804+
super
805+
@level_override = @level_override&.clone&.clear
806+
end
807+
803808
def level_key
804809
Fiber.current
805810
end

test/logger/test_severity.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,31 @@ def test_fiber_local_level
3131
logger.level = INFO # default level
3232
other = Logger.new(nil)
3333
other.level = ERROR # default level
34+
clone = logger.clone # should not be chaged
3435

3536
assert_equal(other.level, ERROR)
3637
logger.with_level(:WARN) do
3738
assert_equal(other.level, ERROR)
3839
assert_equal(logger.level, WARN)
40+
assert_equal(clone.level, INFO)
41+
assert_equal(logger.dup.level, INFO)
42+
assert_equal(logger.clone.level, INFO)
43+
logger.clone.with_level(:FATAL) do
44+
assert_equal(logger.level, WARN)
45+
end
3946

4047
logger.with_level(DEBUG) do # verify reentrancy
4148
assert_equal(logger.level, DEBUG)
49+
assert_equal(clone.level, INFO)
4250

4351
Fiber.new do
4452
assert_equal(logger.level, INFO)
4553
logger.with_level(:WARN) do
4654
assert_equal(other.level, ERROR)
4755
assert_equal(logger.level, WARN)
56+
assert_equal(clone.level, INFO)
57+
assert_equal(logger.dup.level, INFO)
58+
assert_equal(logger.clone.level, INFO)
4859
end
4960
assert_equal(logger.level, INFO)
5061
end.resume
@@ -67,20 +78,31 @@ def level_key
6778
logger.level = INFO # default level
6879
other = subclass.new(nil)
6980
other.level = ERROR # default level
81+
clone = logger.clone # should not be chaged
7082

7183
assert_equal(other.level, ERROR)
7284
logger.with_level(:WARN) do
7385
assert_equal(other.level, ERROR)
7486
assert_equal(logger.level, WARN)
87+
assert_equal(clone.level, INFO)
88+
assert_equal(logger.dup.level, INFO)
89+
assert_equal(logger.clone.level, INFO)
90+
logger.clone.with_level(:FATAL) do
91+
assert_equal(logger.level, WARN)
92+
end
7593

7694
logger.with_level(DEBUG) do # verify reentrancy
7795
assert_equal(logger.level, DEBUG)
96+
assert_equal(clone.level, INFO)
7897

7998
Fiber.new do
8099
assert_equal(logger.level, DEBUG)
81100
logger.with_level(:WARN) do
82101
assert_equal(other.level, ERROR)
83102
assert_equal(logger.level, WARN)
103+
assert_equal(clone.level, INFO)
104+
assert_equal(logger.dup.level, INFO)
105+
assert_equal(logger.clone.level, INFO)
84106
end
85107
assert_equal(logger.level, DEBUG)
86108
end.resume

0 commit comments

Comments
 (0)