Skip to content

Commit 7aabb0b

Browse files
authored
Add Logger#with_level{...} for block-scoped log level. (#85)
* Update lib/logger/severity.rb
1 parent 0c67cbd commit 7aabb0b

File tree

4 files changed

+76
-18
lines changed

4 files changed

+76
-18
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# HEAD
2+
3+
* Support fiber-local log levels using `Logger#with_level` [#84](https://github.com/ruby/logger/issue/84)
4+
15
# 1.4.2
26

37
* Document that shift_age of 0 disables log file rotation [#43](https://github.com/ruby/logger/pull/43) (thanks to jeremyevans)

lib/logger.rb

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#
1111
# A simple system for logging messages. See Logger for more documentation.
1212

13+
require 'fiber'
1314
require 'monitor'
1415
require 'rbconfig'
1516

@@ -380,7 +381,9 @@ class Logger
380381
include Severity
381382

382383
# Logging severity threshold (e.g. <tt>Logger::INFO</tt>).
383-
attr_reader :level
384+
def level
385+
@level_override[Fiber.current] || @level
386+
end
384387

385388
# Sets the log level; returns +severity+.
386389
# See {Log Level}[rdoc-ref:Logger@Log+Level].
@@ -395,24 +398,23 @@ class Logger
395398
# Logger#sev_threshold= is an alias for Logger#level=.
396399
#
397400
def level=(severity)
398-
if severity.is_a?(Integer)
399-
@level = severity
400-
else
401-
case severity.to_s.downcase
402-
when 'debug'
403-
@level = DEBUG
404-
when 'info'
405-
@level = INFO
406-
when 'warn'
407-
@level = WARN
408-
when 'error'
409-
@level = ERROR
410-
when 'fatal'
411-
@level = FATAL
412-
when 'unknown'
413-
@level = UNKNOWN
401+
@level = Severity.coerce(severity)
402+
end
403+
404+
# Adjust the log level during the block execution for the current Fiber only
405+
#
406+
# logger.with_level(:debug) do
407+
# logger.debug { "Hello" }
408+
# end
409+
def with_level(severity)
410+
prev, @level_override[Fiber.current] = level, Severity.coerce(severity)
411+
begin
412+
yield
413+
ensure
414+
if prev
415+
@level_override[Fiber.current] = prev
414416
else
415-
raise ArgumentError, "invalid log level: #{severity}"
417+
@level_override.delete(Fiber.current)
416418
end
417419
end
418420
end
@@ -583,6 +585,7 @@ def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
583585
self.datetime_format = datetime_format
584586
self.formatter = formatter
585587
@logdev = nil
588+
@level_override = {}
586589
if logdev && logdev != File::NULL
587590
@logdev = LogDevice.new(logdev, shift_age: shift_age,
588591
shift_size: shift_size,

lib/logger/severity.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,24 @@ module Severity
1515
FATAL = 4
1616
# An unknown message that should always be logged.
1717
UNKNOWN = 5
18+
19+
LEVELS = {
20+
"debug" => DEBUG,
21+
"info" => INFO,
22+
"warn" => WARN,
23+
"error" => ERROR,
24+
"fatal" => FATAL,
25+
"unknown" => UNKNOWN,
26+
}
27+
private_constant :LEVELS
28+
29+
def self.coerce(severity)
30+
if severity.is_a?(Integer)
31+
severity
32+
else
33+
key = severity.to_s.downcase
34+
LEVELS[key] || raise(ArgumentError, "invalid log level: #{severity}")
35+
end
36+
end
1837
end
1938
end

test/logger/test_severity.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
require 'logger'
44

55
class TestLoggerSeverity < Test::Unit::TestCase
6+
include Logger::Severity
7+
68
def test_enum
79
logger_levels = Logger.constants
810
levels = ["WARN", "UNKNOWN", "INFO", "FATAL", "DEBUG", "ERROR"]
@@ -23,4 +25,34 @@ def test_level_assignment
2325
assert(logger.level) == Logger::Severity.const_get(level)
2426
end
2527
end
28+
29+
def test_thread_local_level
30+
logger = Logger.new(nil)
31+
logger.level = INFO # default level
32+
other = Logger.new(nil)
33+
other.level = ERROR # default level
34+
35+
assert_equal(other.level, ERROR)
36+
logger.with_level(:WARN) do
37+
assert_equal(other.level, ERROR)
38+
assert_equal(logger.level, WARN)
39+
40+
logger.with_level(DEBUG) do # verify reentrancy
41+
assert_equal(logger.level, DEBUG)
42+
43+
Thread.new do
44+
assert_equal(logger.level, INFO)
45+
logger.with_level(:WARN) do
46+
assert_equal(other.level, ERROR)
47+
assert_equal(logger.level, WARN)
48+
end
49+
assert_equal(logger.level, INFO)
50+
end.join
51+
52+
assert_equal(logger.level, DEBUG)
53+
end
54+
assert_equal(logger.level, WARN)
55+
end
56+
assert_equal(logger.level, INFO)
57+
end
2658
end

0 commit comments

Comments
 (0)