Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added ActiveSupport::BufferedLogger as a duck-typing alternative (alb…

…eit with no formatter) to the Ruby Logger, which provides a very nice speed bump (inspired by Ezra's buffered logger) [DHH] Changed the default logger from Ruby's own Logger with the clean_logger extensions to ActiveSupport::BufferedLogger for performance reasons [DHH]. (You can change it back with config.logger = Logger.new(/path/to/log, level).)

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7626 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 79a9c7a702f4bccb2af5c82bb9a78209b28ab1c7 1 parent 501244f
David Heinemeier Hansson dhh authored
2  activesupport/CHANGELOG
View
@@ -1,5 +1,7 @@
*SVN*
+* Added ActiveSupport::BufferedLogger as a duck-typing alternative (albeit with no formatter) to the Ruby Logger, which provides a very nice speed bump (inspired by Ezra's buffered logger) [DHH]
+
* Object#instance_exec produces fewer garbage methods. [Mauricio Fernandez]
* Decode json strings as Dates/Times if they're using a YAML-compatible format. Closes #9614 [Rick]
3  activesupport/lib/active_support.rb
View
@@ -29,7 +29,10 @@
require 'active_support/inflector'
require 'active_support/core_ext'
+
require 'active_support/clean_logger'
+require 'active_support/buffered_logger'
+
require 'active_support/dependencies'
require 'active_support/deprecation'
79 activesupport/lib/active_support/buffered_logger.rb
View
@@ -0,0 +1,79 @@
+module ActiveSupport
+ # Inspired by the buffered logger idea by Ezra
+ class BufferedLogger
+ module Severity
+ DEBUG = 0
+ INFO = 1
+ WARN = 2
+ ERROR = 3
+ FATAL = 4
+ UNKNOWN = 5
+ end
+ include Severity
+
+ # Set to false to disable the silencer
+ cattr_accessor :silencer
+ self.silencer = true
+
+ # Silences the logger for the duration of the block.
+ def silence(temporary_level = ERROR)
+ if silencer
+ begin
+ old_logger_level, self.level = level, temporary_level
+ yield self
+ ensure
+ self.level = old_logger_level
+ end
+ else
+ yield self
+ end
+ end
+
+ attr_accessor :level, :auto_flushing
+ attr_reader :buffer
+
+ def initialize(log, level = DEBUG)
+ @level = level
+ @buffer = ""
+ @auto_flushing = true
+
+ if log.respond_to?(:write)
+ @log = log
+ elsif File.exist?(log)
+ @log = open(log, (File::WRONLY | File::APPEND))
+ @log.sync = true
+ else
+ @log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
+ @log.sync = true
+ @log.write("# Logfile created on %s" % [Time.now.to_s])
+ end
+ end
+
+ for severity in Severity.constants
+ class_eval <<-EOT
+ def #{severity.downcase}(message)
+ return if @level > #{severity}
+ message << "\\n" unless message[-1] == ?\\n
+ @buffer << message
+ flush if auto_flushing
+ message
+ end
+
+ def #{severity.downcase}?
+ @level == #{severity}
+ end
+ EOT
+ end
+
+ def flush
+ return if @buffer.size == 0
+ @log.write(@buffer.slice!(0..-1))
+ end
+
+ def close
+ flush
+ @log.close if @log.respond_to?(:close)
+ @log = nil
+ end
+ end
+end
2  activesupport/lib/active_support/clean_logger.rb
View
@@ -11,6 +11,8 @@
# You can then specify the datetime format, for example:
#
# logger.datetime_format = "%Y-%m-%d"
+#
+# Note: This logger is deprecated in favor of ActiveSupport::BufferedLogger
class Logger
# Set to false to disable the silencer
cattr_accessor :silencer
2  railties/CHANGELOG
View
@@ -1,5 +1,7 @@
*SVN*
+* Changed the default logger from Ruby's own Logger with the clean_logger extensions to ActiveSupport::BufferedLogger for performance reasons [DHH]. (You can change it back with config.logger = Logger.new("/path/to/log", level).)
+
* Added a default 422.html page to be rendered when ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved, or ActionController::InvalidAuthenticityToken is raised [DHH]
* Added --skip-fixture option to script/generate model #6862 [sandofsky]
11 railties/lib/dispatcher.rb
View
@@ -38,13 +38,14 @@ def dispatch(cgi = nil, session_options = ActionController::CgiRequest::DEFAULT_
controller = ActionController::Routing::Routes.recognize(request)
controller.process(request, response).out(output)
end
- rescue Exception => exception # errors from CGI dispatch
+ rescue Exception => exception # errors from CGI dispatch
failsafe_response(cgi, output, '500 Internal Server Error', exception) do
controller ||= (ApplicationController rescue ActionController::Base)
controller.process_with_exception(request, response, exception).out(output)
end
ensure
- # Do not give a failsafe response here.
+ # Do not give a failsafe response here
+ flush_logger
reset_after_dispatch
end
@@ -165,9 +166,13 @@ def failsafe_logger
if defined?(RAILS_DEFAULT_LOGGER) && !RAILS_DEFAULT_LOGGER.nil?
RAILS_DEFAULT_LOGGER
else
- Logger.new($stderr)
+ ActiveSupport::BufferedLogger.new($stderr)
end
end
+
+ def flush_logger
+ RAILS_DEFAULT_LOGGER.flush if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:flush)
+ end
end
end
11 railties/lib/initializer.rb
View
@@ -240,11 +240,12 @@ def initialize_logger
unless logger = configuration.logger
begin
- logger = Logger.new(configuration.log_path)
- logger.level = Logger.const_get(configuration.log_level.to_s.upcase)
- rescue StandardError
- logger = Logger.new(STDERR)
- logger.level = Logger::WARN
+ logger = ActiveSupport::BufferedLogger.new(configuration.log_path)
+ logger.level = ActiveSupport::BufferedLogger.const_get(configuration.log_level.to_s.upcase)
+ logger.auto_flushing = false if configuration.environment == "production"
+ rescue StandardError =>e
+ logger = ActiveSupport::BufferedLogger.new(STDERR)
+ logger.level = ActiveSupport::BufferedLogger::WARN
logger.warn(
"Rails Error: Unable to access log file. Please ensure that #{configuration.log_path} exists and is chmod 0666. " +
"The log level has been raised to WARN and the output directed to STDERR until the problem is fixed."
Please sign in to comment.
Something went wrong with that request. Please try again.