Graphql-ruby: RFC: Re-raise errors with additional GraphQL backtrace

Created on 22 Aug 2017  路  8Comments  路  Source: rmosolgo/graphql-ruby

I just learned you can provide a backtrace when raising an error as the third argument to raise(error_or_class, message, backtrace). So, you could amend a backtrace before raising an error, for example:

def raise_error
  raise KeyError, "Something bad happened"
end

begin
  raise_error
rescue
  backtrace_additions = ["(added):1", "(added:2)"]
  raise $!, $!.message, backtrace_additions + $!.backtrace
end
# KeyError: Something bad happened
#   from (added):1
#   from (added:2)
#   from (irb):2:in `raise_error'
#   from (irb):6
#   from /usr/bin/irb:12:in `<main>'

So, could we track graphql execution and _add_ entries to the backtrace when errors come from graphql resolve functions?

Most helpful comment

Yeah exactly! Maybe it could be optional while we try it out, eg

# lib/graphql/error.rb
  def backtrace 
    if GraphQL.path_backtrace && @context 
      backtrace_from_context(@context) + super 
    else 
      super 
    end 
  end 

All 8 comments

Are you thinking that we would add things like the path in the query?

query MyQuery {
  node(id: "...") { someField { someOtherField } }
}
# maybe other queries in the document too...
# Show the name of the operation, and the path:
#       in someOtherField
#       in someField[3]
#       in node(id: "...")
#   in MyQuery
#   from (irb):2:in `raise_error'
#   from (irb):6
#   from /usr/bin/irb:12:in `<main>'

Yeah exactly! Maybe it could be optional while we try it out, eg

# lib/graphql/error.rb
  def backtrace 
    if GraphQL.path_backtrace && @context 
      backtrace_from_context(@context) + super 
    else 
      super 
    end 
  end 

Here's another approach to modifying the backtrace:

https://github.com/ko1/pretty_backtrace

The approach looks like:

Don't have a strong opinion which approach to use, but something along these lines would be super-useful. Figuring out which chain of selections/fields resulted in a specific error is one of the most annoying parts of debugging our schema right now.

Interesting idea. Is it worth it in a world where resolvers are methods on objects? The reason why the backtrace is not super clear right now is the heavy proc usage during execution, I have a feeling it will become if the definition changes in the following weeks / months 馃挱

I think it's still worth it. Even when resolvers are methods, the ruby trace alone won't tell you how you got there, e.g. consider the following totally made-up query:

{
  myObject { foo }
  myListOfObjects(first: 10) { edge { node { foo } } }
}

Even if you know the exception occurred in the method for foo, it probably looks something like

foo:123
someInternalGemMethod:xxx
someInternalGemMethod2:xxx
someInternalGemMethod3:xxx
someInternalGemMethod4:xxx

It would still be really helpful to know whether the exception came from myObject or from myListOfObjects and if from the list, from which one.

Good point.

As long as we add to it and not modify it / delete from it , I think it would provide great value 馃憤

trying in #946

I didn't use RubyVM::DebugInspector like koichi's gem above because it's MRI-only, and I know some folks use JRuby.

Was this page helpful?
0 / 5 - 0 ratings