Ran
Ran

Reputation: 7709

Rails - How to change log level for ActionController::RoutingError

Is there a way to change the log level for ActionController::RoutingError?
I'd like to change it from Error to Warning. Googled around and haven't found a solution...
I'd like just the routing errors to show up as warnings. but not change other logging behaviors.
One possible workaround (or part of that workaround) is described here https://stackoverflow.com/a/5386515/10272 but that's not exactly what I want. In this solution they just add a catch-all router for page-not-found errors and then deal with it in the catch-all-controller. But I'd like to be able to just change the log severity, if that's possible, it seems to better describe my intent...

Upvotes: 7

Views: 1814

Answers (2)

jaredlt
jaredlt

Reputation: 713

I solved this in Rails 5.2 using the following in an intializer:

# /config/initializers/routing_error_logger_defatalizer.rb

# Spammers and script kiddies hit the site looking for exploits
# which blows up our logs as we get a bunch of fatal errors for 404s on eg. "/wp-admin.php"
# This initializer changes the log level of RoutingErrors to 'warn' (so they still appear in logs but are not fatal)
# this means we can use logging notifications on eg. >= error without all the false positives
# ref: https://stackoverflow.com/questions/33827663/hide-actioncontrollerroutingerror-in-logs-for-assets
# ref: https://github.com/roidrage/lograge/issues/146#issuecomment-461632965
if Rails.env.production?
  module ActionDispatch
    class DebugExceptions
      alias_method :old_log_error, :log_error
      def log_error(request, wrapper)
        if wrapper.exception.is_a?  ActionController::RoutingError
          # Have prepended "[404]" to the message for easier log searches, otherwise it is the default Rails messaging
          # Full message eg. "[404] ActionController::RoutingError (No route matches [GET] \"/wp-login.php\")"
          logger(request).send(:warn, "[404] ActionController::RoutingError (#{wrapper.exception.message})")
          return
        else
          old_log_error request, wrapper
        end
      end
    end
  end
end

For Rails 4.2 use:

if Rails.env.production?
  class ActionDispatch::DebugExceptions # Rails 4.2
    alias_method :old_log_error, :log_error
    def log_error(request, wrapper)
      if wrapper.exception.is_a?  ActionController::RoutingError
        # Have prepended "[404]" to the message for easier log searches, otherwise it is the default Rails messaging
        # Full message eg. "[404] ActionController::RoutingError (No route matches [GET] \"/wp-login.php\")"
        logger(request).send(:warn, "[404] ActionController::RoutingError (#{wrapper.exception.message})")
        return
      else
        old_log_error request, wrapper
      end
    end
  end
end

Upvotes: 1

Musannif Zahir
Musannif Zahir

Reputation: 3029

You could override the Simple Formatter so that you're logging the error as a warning.

However, I don't recommend taking this route as you end up logging a warning message for an action the application sees as an error/exception. The more elegant option would be to have a catch-all page as you described, with the controller catching the exception and logging the warning message.

Upvotes: 0

Related Questions