diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 9155e3cf274535155ad31856164d1c056d83299d..ea31261c955ec70a0e16d088baa3cba98aa97cbf 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -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] diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 9eec6f3b3848c5fcfd80c333e93544c4c7628cca..28424dd6a7d58e674b759763b90d4a7ca76df310 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -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' diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb new file mode 100644 index 0000000000000000000000000000000000000000..b28f4a5ad382389255315b38ef94ae68f593b1e6 --- /dev/null +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -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 \ No newline at end of file diff --git a/activesupport/lib/active_support/clean_logger.rb b/activesupport/lib/active_support/clean_logger.rb index 95d4f07f4d6e02809caf91c44519086c0968a19b..0c6de67f8d013f7f545816aceedf47a2bf53d6f5 100644 --- a/activesupport/lib/active_support/clean_logger.rb +++ b/activesupport/lib/active_support/clean_logger.rb @@ -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 diff --git a/railties/CHANGELOG b/railties/CHANGELOG index b015d92060fb1e41fc4ab75f3014d6501501f1fc..3f77a2f37bee8f7fe7e7985da8e54d8ef40e2126 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -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] diff --git a/railties/lib/dispatcher.rb b/railties/lib/dispatcher.rb index cb1289957e931a77e57757ef2f2facd085df71a2..398acb7e973801fe4d42cb5f3236a81ab50b34bf 100644 --- a/railties/lib/dispatcher.rb +++ b/railties/lib/dispatcher.rb @@ -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 diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index b9fa9eee01edad699089cb06fda36a93bd8dba90..c2862ee4439dec9cdd480a8d030eeafc7e58e156 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -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."