appsignal/appsignal-ruby

Support nested exceptions

Closed this issue ยท 12 comments

When an exception is manually wrapped, it's possible to know the original exception by calling #cause

TODO

  • Add native support for Nested exceptions
  • Add nested exceptions to a test setup

For some context, imagine a piece of code like the following.
(A nice functioning example using: https://pokeapi.co)

module PokeApi
  Error = Class.new(StandardError)

  class Client

    def pokemon(name:)
      get("api/v2/pokemon/#{name}").body
    end

    private

      def get(...)
        connection.get(...)
      rescue Faraday::Error
        raise Error
      end

      def connection
        Faraday. new("https://pokeapi.co/") do |faraday|
          faraday.response :json
          faraday.response :raise_error
        end
      end

  end
end

In my code I rely on error.cause for details, while still having the nice custom exceptions (with very minimal work).

poke_api = PokeApi::Client.new
begin
  poke_api.pokemon(name: "definetly-invalid")
rescue PokeApi::Error => error
  puts error.cause.inspect
end

But Appsignal will pick this up simply as PokeApi::Error with no additional info.

Hi there!

But Appsignal will pick this up simply as PokeApi::Error with no additional info.

We still need to think about the solution. To me, the two main concerns are:

  • The backtrace we want to show on the incident page.
  • Until which level of causes do we want to show as errors can be nested ad infinitum?

@jessevdp as a nested error user? Which backtrace is the one you consider the most valuable?

I think the backtrace of the top-level error is still very important. The errors I'm wrapping are usually 3rd party libs so their backtrace is usually not as important. (Similar to "show application backtrace" vs "show full backtrace" buttons in Appsignal currently.)

Perhaps in ideal solution would be something like:

MyCustomException: <message>
...
backtrace
...

Caused by:
AnotherException: <message>
...
backtrace
...

This is definitely a type of format I've seen before.

I suppose the nesting is never actually infinite. So showing causes as far down as they'll go seems like the way to go. But of course I haven't done my research into all the edge cases that would uncover.

(I mean you might technically be able to code this into a loop, where 2 exceptions point at each other as their cause, but that shouldn't happen naturally, and could probably be detected)

Aside: for now I've used a bit of custom_data to uncover 1 level of error.cause. This isn't fully ideal but it surfaces just enough information for my current use. The backtraces as described above would be far better.

# somewhere in an initializer
class AppsignalNestedErrorEnricher
  def report(error, handled:, severity:, context:, source: nil)
    return if error.cause.nil?

    Appsignal::Transaction.current.set_sample_data(
      "custom_data",
      error_cause: {
        class: error.cause.class.name,
        message: error.cause.message,
      }
    )
  end
end

# This relies on Rails.error.report being run around the code.
Rails.error.subscribe(AppsignalNestedErrorEnricher.new)
# In ApplicationController
around_action do |_controller, action|
  # used by config/initializers/appsignal_nested_error_enricher.rb
  Rails.error.record(&action)
end

This is very valuable info. Thank you very much @jessevdp

This issue seems is labelled as a new feature. Our customers may want to be informed about these changes through a blog post announcement. An issue has been created in blog repo so we remember to publish a blog post about it.

If a blog post is not required, please add the [skip blogpost] tag next time, and close the created issue.

  • This issue has not had any activity in 14 days. Please provide a status update if it is still relevant. Closed it if it is no longer relevant. Or move it to another column if it's blocked or requires another look at it. - (More info)

This is a message from the daily scheduled checks.

New issue guide | Backlog management | Rules | Feedback

I'd still love this feature ๐Ÿ˜

@jessevdp Well, I have good news for you...

ezgif-1-eedcea310d

Stay tuned! ๐Ÿ“ป

Hehe nice! ๐Ÿฅณ

(I was just shushing the backlog-helper BTW ๐Ÿ˜)

Hi @jessevdp,

AppSignal for Ruby 3.5.0 was released yesterday, including support for error causes! See our changelog for details. ๐ŸŽ‰