mirror of https://github.com/rails/rails
Fix the LoggerSilence to work as described:
- Following the Rails guide which state that a logger needs to include the `ActiveSupport::LoggerSilence` as well as `ActiveSupport::LoggerThreadSafe` modules isn't enough and won't work. Here is a test cases with 3 tests that all fails https://gist.github.com/Edouard-chin/4a72930c2b1eafbbd72a80c66f102010 The problems are the following: 1) The logger needs to call `after_initialize` in order to setup some instance variables. 2) The silence doesn't actually work because the bare ruby Logger `add` method checks for the instance variable `@logger`. We need to override the `add` (like we used to in the ActiveSupport::Logger class). 3) Calling `debug?` `info?` etc... doesn't work as the bare ruby methods will check for the instance variable. Again we need to override this methods (like we used to in the ActiveSupport::Logger class) The LoggerSilence won't work without LoggerThreadSafe, but the later is not public API, the user shouldn't have to include it so I modified to include it automatically. Same for the `after_initialize` method. I find unuintitive to have to call it directly. I modified to instance the variables when the module get included.
This commit is contained in:
parent
92fece96da
commit
05ad44eb89
|
@ -6,7 +6,6 @@ require "logger"
|
|||
|
||||
module ActiveSupport
|
||||
class Logger < ::Logger
|
||||
include ActiveSupport::LoggerThreadSafeLevel
|
||||
include LoggerSilence
|
||||
|
||||
# Returns true if the logger destination matches one of the sources
|
||||
|
@ -81,20 +80,6 @@ module ActiveSupport
|
|||
def initialize(*args)
|
||||
super
|
||||
@formatter = SimpleFormatter.new
|
||||
after_initialize if respond_to? :after_initialize
|
||||
end
|
||||
|
||||
def add(severity, message = nil, progname = nil, &block)
|
||||
return true if @logdev.nil? || (severity || UNKNOWN) < level
|
||||
super
|
||||
end
|
||||
|
||||
Logger::Severity.constants.each do |severity|
|
||||
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
|
||||
def #{severity.downcase}? # def debug?
|
||||
Logger::#{severity} >= level # DEBUG >= level
|
||||
end # end
|
||||
EOT
|
||||
end
|
||||
|
||||
# Simple formatter which only displays the message.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
require "active_support/concern"
|
||||
require "active_support/core_ext/module/attribute_accessors"
|
||||
require "active_support/logger_thread_safe_level"
|
||||
|
||||
module LoggerSilence
|
||||
extend ActiveSupport::Concern
|
||||
|
@ -22,6 +23,7 @@ module ActiveSupport
|
|||
|
||||
included do
|
||||
cattr_accessor :silencer, default: true
|
||||
include ActiveSupport::LoggerThreadSafeLevel
|
||||
end
|
||||
|
||||
# Silences the logger for the duration of the block.
|
||||
|
|
|
@ -1,14 +1,30 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "active_support/concern"
|
||||
require "active_support/core_ext/module/attribute_accessors"
|
||||
require "concurrent"
|
||||
|
||||
module ActiveSupport
|
||||
module LoggerThreadSafeLevel # :nodoc:
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
cattr_accessor :local_levels, default: Concurrent::Map.new(initial_capacity: 2), instance_accessor: false
|
||||
end
|
||||
|
||||
Logger::Severity.constants.each do |severity|
|
||||
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
|
||||
def #{severity.downcase}? # def debug?
|
||||
Logger::#{severity} >= level # DEBUG >= level
|
||||
end # end
|
||||
EOT
|
||||
end
|
||||
|
||||
def after_initialize
|
||||
@local_levels = Concurrent::Map.new(initial_capacity: 2)
|
||||
ActiveSupport::Deprecation.warn(
|
||||
"Logger don't need to call #after_initialize directly anymore. It will be deprecated without replacement in " \
|
||||
"Rails 6.1."
|
||||
)
|
||||
end
|
||||
|
||||
def local_log_id
|
||||
|
@ -16,19 +32,24 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
def local_level
|
||||
@local_levels[local_log_id]
|
||||
self.class.local_levels[local_log_id]
|
||||
end
|
||||
|
||||
def local_level=(level)
|
||||
if level
|
||||
@local_levels[local_log_id] = level
|
||||
self.class.local_levels[local_log_id] = level
|
||||
else
|
||||
@local_levels.delete(local_log_id)
|
||||
self.class.local_levels.delete(local_log_id)
|
||||
end
|
||||
end
|
||||
|
||||
def level
|
||||
local_level || super
|
||||
end
|
||||
|
||||
def add(severity, message = nil, progname = nil, &block) # :nodoc:
|
||||
return true if @logdev.nil? || (severity || UNKNOWN) < level
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -123,6 +123,8 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
class CustomLogger
|
||||
include ActiveSupport::LoggerSilence
|
||||
|
||||
attr_reader :adds, :closed, :chevrons
|
||||
attr_accessor :level, :progname, :formatter, :local_level
|
||||
|
||||
|
@ -174,7 +176,6 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
class FakeLogger < CustomLogger
|
||||
include ActiveSupport::LoggerSilence
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "abstract_unit"
|
||||
require "active_support/logger_silence"
|
||||
require "logger"
|
||||
|
||||
class LoggerSilenceTest < ActiveSupport::TestCase
|
||||
class MyLogger < ::Logger
|
||||
include LoggerSilence
|
||||
end
|
||||
|
||||
setup do
|
||||
@io = StringIO.new
|
||||
@logger = MyLogger.new(@io)
|
||||
end
|
||||
|
||||
test "#silence silences the log" do
|
||||
@logger.silence(Logger::ERROR) do
|
||||
@logger.info("Foo")
|
||||
end
|
||||
@io.rewind
|
||||
|
||||
assert_empty @io.read
|
||||
end
|
||||
|
||||
test "#debug? is true when setting the temporary level to Logger::DEBUG" do
|
||||
@logger.level = Logger::INFO
|
||||
|
||||
@logger.silence(Logger::DEBUG) do
|
||||
assert_predicate @logger, :debug?
|
||||
end
|
||||
|
||||
assert_predicate @logger, :info?
|
||||
end
|
||||
end
|
|
@ -119,11 +119,10 @@ defaults to `:debug` for all environments. The available log levels are: `:debug
|
|||
* `config.logger` is the logger that will be used for `Rails.logger` and any related Rails logging such as `ActiveRecord::Base.logger`. It defaults to an instance of `ActiveSupport::TaggedLogging` that wraps an instance of `ActiveSupport::Logger` which outputs a log to the `log/` directory. You can supply a custom logger, to get full compatibility you must follow these guidelines:
|
||||
* To support a formatter, you must manually assign a formatter from the `config.log_formatter` value to the logger.
|
||||
* To support tagged logs, the log instance must be wrapped with `ActiveSupport::TaggedLogging`.
|
||||
* To support silencing, the logger must include `ActiveSupport::LoggerSilence` and `ActiveSupport::LoggerThreadSafeLevel` modules. The `ActiveSupport::Logger` class already includes these modules.
|
||||
* To support silencing, the logger must include `ActiveSupport::LoggerSilence` module. The `ActiveSupport::Logger` class already includes these modules.
|
||||
|
||||
```ruby
|
||||
class MyLogger < ::Logger
|
||||
include ActiveSupport::LoggerThreadSafeLevel
|
||||
include ActiveSupport::LoggerSilence
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue