Peter Marklund

Peter Marklund's Home

Sun August 12, 2007
Programming

Rails Deployment: Dealing with 404s

You probably use Jamis Buck's Exception Notifier plugin to be notified by email of exceptions thrown on your production server. Typically though you don't want to be notified of 404s, at least not when they are caused by an RSS reader requesting an RSS feed that no longer exists, or some spam robot or search engine fetching URLs fetching URLs no longer supported. When the Exception Notifier plugin catches an exception and it is one of ActiveRecord::RecordNotFound, ActionController::UnknownController, or ActionController::UnknownAction, it figures that it is a 404. By default then no email is sent and instead the method render_404 is invoked which in turn renders public/404.html. This is quite appropriate. Unofortunately though you can't trace in the log what the request looked like that caused the 404. The other limitation is that if no route matches a n incoming request, then an ActionController::RoutingError is thrown, yielding a 500 and an exception email. To get consistency in how 404s are dealt with, i.e. make sure they are always fully logged and tracable, but never cause email notifications, I override the render_404 method from the Exception Notifier plugin in my ApplicationController:

  # Overriding the version in ExceptionNotifiable so that we can log the environment and figure
  # out where the request is coming from.
  def render_404
    logger.error("render_404 invoked for request_uri=#{request.request_uri} and env=#{request.env.inspect}")
    super
  end

I then add a catch all route at the end of my routes.rb file:

  map.connect '*anything', :controller => 'application', :action => 'render_404'

Comments

Jarkko Laine said over 7 years ago:

"The other limitation is that if no route matches a n incoming request, then an ActionController::RoutingError is thrown, yielding a 500 and an exception email."

Actually, the latest version of the plugin does treat RoutingErrors as 404: http://svn.rubyonrails.org/rails/plugins/exception_notification/lib/exception_notifiable.rb

So far, I've added it in exception_notifiable.rb by hand.

--------------------------------------------------------------------------------

Peter Marklund said over 7 years ago:

Ah, excellent, so then the catch all route won't be needed anymore. Thanks Jarkko.

--------------------------------------------------------------------------------

Peter Marklund said over 6 years ago:

Another, and it seems the intended way to customize error logging is to override the log_error method in your application controller. I did that to avoid having fat traces from 404s pollute my log file:

# Overriding the method in rescue.rb so that we don't pollute the log with stack traces from
# 404 requests (RoutingError).
def log_error(exception) #:doc:
ActiveSupport::Deprecation.silence do
if ActionView::TemplateError === exception || ActionController::RoutingError === exception
logger.fatal(exception.to_s)
else
logger.fatal(
"\n\n#{exception.class} (#{exception.message}):\n " +
clean_backtrace(exception).join("\n ") +
"\n\n"
)
end
end
end

--------------------------------------------------------------------------------

Jay said over 5 years ago:

Thanks for the log_error override. This worked like a charm!

--------------------------------------------------------------------------------