How to set up exception logging correctly?

Hey :wave: ,

I want to set up exception logging in a Hanami 2.2 app (api-only). If you do not do this and use the :json formatter in the production environment, then the log file contains a mixture of json lines and string lines. Furthermore, by default, the exceptions are swallowed up in the productive env, because of the RenderErrors-middleware.

How I did it:
By default (config.render_errors = true), the exception is swallowed and not logged at all. Error html pages are rendered, which is not intended with api only.

With the following config I changed this behavior:

# config/app.rb
require "hanami"

module MyApp
  class App < Hanami::App
   #...
    environment(:production) do
      config.render_errors = false # 
      config.logger.formatter = :json
    end
  end
end

Then I set up exception logging:

# app/action.rb

# auto_register: false
# frozen_string_literal: true

require "hanami/action"
require "dry/monads"

module MyApp
  class Action < Hanami::Action
    # Provide `Success` and `Failure` for pattern matching on operation results
    include Dry::Monads[:result]

    handle_exception Exception => :handle_base_exception

    private

    def handle_base_exception(_, _, exception)
      Hanami.app["logger"].error(exception)
    end
  end
end

However, I believe that with this solution, exceptions that occur in the json middleware, for example, are not logged correctly. What is your opinion, or how would you proceed? Is there a better way?

Should we add Hanami.app["logger"].error(exception) to the RenderErrors-middlware?

Thanks

My initial thought here is that it should probably be middleware that is loaded into the top-level app router stack.

You could do it as middleware outside the Hanami app, but that would probably require rolling your own structured logging. Doing it in the app-level allows you to reuse the logger configuration.

This is tricky, because in production situations most people have a third-party error collector, and they’re all a little bit different, but I believe most of the time they are implemented as middleware.

Thanks for your thoughts.
Do you think that such logging-middleware should be included with Hanami? Or do you think it should be left to the users to decide how to deal with it? In my opinion, json logging only makes sense if exceptions are also logged accordingly.

In production, you will usually see an error collector middleware that traps unhandled exceptions and forwards them to a service. Every one is different.

The only thing I can think of that the framework could handle is reporting exceptions in JSON format when structured logging is enabled. You never want both.

You might want to enable something like better_errors in local dev.

1 Like