aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorschneems <richard.schneeman@gmail.com>2016-01-05 16:23:43 -0600
committerschneems <richard.schneeman@gmail.com>2016-01-06 09:55:35 -0600
commit3d10d9d6c3b831fe9632c43a0ffec46104f912a7 (patch)
tree0f4e2050c58d477d93e048c71a1cc7c6f3f3f5d2 /activesupport
parent9dcb1b9b074e313fe0d2a738345c623620f594a2 (diff)
downloadrails-3d10d9d6c3b831fe9632c43a0ffec46104f912a7.tar.gz
rails-3d10d9d6c3b831fe9632c43a0ffec46104f912a7.tar.bz2
rails-3d10d9d6c3b831fe9632c43a0ffec46104f912a7.zip
[close #22917] Don't output to `STDOUT` twice
When `rails console` or `rails server` are used along with a logger set to output to `STDOUT` then the contents will show up twice. This happens because the logger is extended with `ActiveSupportLogger.broadcast` with a destination of STDOUT even if it is already outputting to `STDOUT`. Previously PR #22592 attempted to fix this issue, but it ended up causing NoMethodErrors. A better approach than relying on adding a method and flow control is to inspect the log destination directly. For this `ActiveSupport::Logger.logger_outputs_to?` was introduced ```ruby logger = Logger.new(STDOUT) ActiveSupport::Logger.logger_outputs_to?(logger, STDOUT) # => true ``` To accomplish this we must look inside of an instance variable of standard lib's Logger `@logdev`. There is a related Ruby proposal to expose this method in a standard way: https://bugs.ruby-lang.org/issues/11955
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/lib/active_support/logger.rb12
-rw-r--r--activesupport/test/logger_test.rb12
2 files changed, 21 insertions, 3 deletions
diff --git a/activesupport/lib/active_support/logger.rb b/activesupport/lib/active_support/logger.rb
index 3c9c86c30b..f9aacd20fc 100644
--- a/activesupport/lib/active_support/logger.rb
+++ b/activesupport/lib/active_support/logger.rb
@@ -1,4 +1,3 @@
-require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/logger_silence'
require 'logger'
@@ -6,6 +5,17 @@ module ActiveSupport
class Logger < ::Logger
include LoggerSilence
+ # Returns true if the logger destination matches one of the sources
+ #
+ # logger = Logger.new(STDOUT)
+ # ActiveSupport::Logger.logger_outputs_to?(logger, STDOUT)
+ # # => true
+ def self.logger_outputs_to?(logger, *sources)
+ logdev = logger.instance_variable_get("@logdev")
+ logger_source = logdev.dev if logdev.respond_to?(:dev)
+ sources.any? { |source| source == logger_source }
+ end
+
# Broadcasts logs to multiple loggers.
def self.broadcast(logger) # :nodoc:
Module.new do
diff --git a/activesupport/test/logger_test.rb b/activesupport/test/logger_test.rb
index a57dc7a241..317e09b7f2 100644
--- a/activesupport/test/logger_test.rb
+++ b/activesupport/test/logger_test.rb
@@ -17,6 +17,14 @@ class LoggerTest < ActiveSupport::TestCase
@logger = Logger.new(@output)
end
+ def test_log_outputs_to
+ assert Logger.logger_outputs_to?(@logger, @output), "Expected logger_outputs_to? @output to return true but was false"
+ assert Logger.logger_outputs_to?(@logger, @output, STDOUT), "Expected logger_outputs_to? @output or STDOUT to return true but was false"
+
+ assert_not Logger.logger_outputs_to?(@logger, STDOUT), "Expected logger_outputs_to? to STDOUT to return false, but was true"
+ assert_not Logger.logger_outputs_to?(@logger, STDOUT, STDERR), "Expected logger_outputs_to? to STDOUT or STDERR to return false, but was true"
+ end
+
def test_write_binary_data_to_existing_file
t = Tempfile.new ['development', 'log']
t.binmode
@@ -65,7 +73,7 @@ class LoggerTest < ActiveSupport::TestCase
def test_should_not_log_debug_messages_when_log_level_is_info
@logger.level = Logger::INFO
@logger.add(Logger::DEBUG, @message)
- assert ! @output.string.include?(@message)
+ assert_not @output.string.include?(@message)
end
def test_should_add_message_passed_as_block_when_using_add
@@ -129,7 +137,7 @@ class LoggerTest < ActiveSupport::TestCase
@logger.error "THIS IS HERE"
end
- assert !@output.string.include?("NOT THERE")
+ assert_not @output.string.include?("NOT THERE")
assert @output.string.include?("THIS IS HERE")
end