Permalink
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...
1 parent 501244f commit 79a9c7a702f4bccb2af5c82bb9a78209b28ab1c7 @dhh dhh committed Sep 25, 2007
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]
@@ -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'
@@ -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
@@ -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
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]
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
@@ -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."

0 comments on commit 79a9c7a

Please sign in to comment.