[ruby/logger] Add Logger#with_level{...} for block-scoped log level.

(https://github.com/ruby/logger/pull/85)

* Update lib/logger/severity.rb

https://github.com/ruby/logger/commit/7aabb0b4aa
This commit is contained in:
Mike Perham 2023-02-09 17:08:33 -08:00 committed by git
parent b61edc5f5d
commit 194520f80e
3 changed files with 72 additions and 18 deletions

View File

@ -10,6 +10,7 @@
# #
# A simple system for logging messages. See Logger for more documentation. # A simple system for logging messages. See Logger for more documentation.
require 'fiber'
require 'monitor' require 'monitor'
require 'rbconfig' require 'rbconfig'
@ -380,7 +381,9 @@ class Logger
include Severity include Severity
# Logging severity threshold (e.g. <tt>Logger::INFO</tt>). # Logging severity threshold (e.g. <tt>Logger::INFO</tt>).
attr_reader :level def level
@level_override[Fiber.current] || @level
end
# Sets the log level; returns +severity+. # Sets the log level; returns +severity+.
# See {Log Level}[rdoc-ref:Logger@Log+Level]. # See {Log Level}[rdoc-ref:Logger@Log+Level].
@ -395,24 +398,23 @@ class Logger
# Logger#sev_threshold= is an alias for Logger#level=. # Logger#sev_threshold= is an alias for Logger#level=.
# #
def level=(severity) def level=(severity)
if severity.is_a?(Integer) @level = Severity.coerce(severity)
@level = severity end
# Adjust the log level during the block execution for the current Fiber only
#
# logger.with_level(:debug) do
# logger.debug { "Hello" }
# end
def with_level(severity)
prev, @level_override[Fiber.current] = level, Severity.coerce(severity)
begin
yield
ensure
if prev
@level_override[Fiber.current] = prev
else else
case severity.to_s.downcase @level_override.delete(Fiber.current)
when 'debug'
@level = DEBUG
when 'info'
@level = INFO
when 'warn'
@level = WARN
when 'error'
@level = ERROR
when 'fatal'
@level = FATAL
when 'unknown'
@level = UNKNOWN
else
raise ArgumentError, "invalid log level: #{severity}"
end end
end end
end end
@ -583,6 +585,7 @@ class Logger
self.datetime_format = datetime_format self.datetime_format = datetime_format
self.formatter = formatter self.formatter = formatter
@logdev = nil @logdev = nil
@level_override = {}
if logdev && logdev != File::NULL if logdev && logdev != File::NULL
@logdev = LogDevice.new(logdev, shift_age: shift_age, @logdev = LogDevice.new(logdev, shift_age: shift_age,
shift_size: shift_size, shift_size: shift_size,

View File

@ -15,5 +15,24 @@ class Logger
FATAL = 4 FATAL = 4
# An unknown message that should always be logged. # An unknown message that should always be logged.
UNKNOWN = 5 UNKNOWN = 5
LEVELS = {
"debug" => DEBUG,
"info" => INFO,
"warn" => WARN,
"error" => ERROR,
"fatal" => FATAL,
"unknown" => UNKNOWN,
}
private_constant :LEVELS
def self.coerce(severity)
if severity.is_a?(Integer)
severity
else
key = severity.to_s.downcase
LEVELS[key] || raise(ArgumentError, "invalid log level: #{severity}")
end
end
end end
end end

View File

@ -3,6 +3,8 @@
require 'logger' require 'logger'
class TestLoggerSeverity < Test::Unit::TestCase class TestLoggerSeverity < Test::Unit::TestCase
include Logger::Severity
def test_enum def test_enum
logger_levels = Logger.constants logger_levels = Logger.constants
levels = ["WARN", "UNKNOWN", "INFO", "FATAL", "DEBUG", "ERROR"] levels = ["WARN", "UNKNOWN", "INFO", "FATAL", "DEBUG", "ERROR"]
@ -23,4 +25,34 @@ class TestLoggerSeverity < Test::Unit::TestCase
assert(logger.level) == Logger::Severity.const_get(level) assert(logger.level) == Logger::Severity.const_get(level)
end end
end end
def test_thread_local_level
logger = Logger.new(nil)
logger.level = INFO # default level
other = Logger.new(nil)
other.level = ERROR # default level
assert_equal(other.level, ERROR)
logger.with_level(:WARN) do
assert_equal(other.level, ERROR)
assert_equal(logger.level, WARN)
logger.with_level(DEBUG) do # verify reentrancy
assert_equal(logger.level, DEBUG)
Thread.new do
assert_equal(logger.level, INFO)
logger.with_level(:WARN) do
assert_equal(other.level, ERROR)
assert_equal(logger.level, WARN)
end
assert_equal(logger.level, INFO)
end.join
assert_equal(logger.level, DEBUG)
end
assert_equal(logger.level, WARN)
end
assert_equal(logger.level, INFO)
end
end end