Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify GraphQL::Backtrace #5217

Merged
merged 6 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
- run: bundle exec rake compile
- run: bundle exec rake test
- run: git fetch --no-tags --prune --depth=10 origin +refs/heads/*:refs/remotes/origin/*
- run: bundle exec pronto run -f github_status github_pr -c origin/${{ github.base_ref }}
- run: bundle exec pronto run -f github_pr -c origin/${{ github.base_ref }}
if: ${{ !!matrix.coverage }}
env:
PRONTO_PULL_REQUEST_ID: ${{ github.event.pull_request.number }}
Expand Down
1 change: 1 addition & 0 deletions benchmark/run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require "stackprof"
require "memory_profiler"
require "graphql/batch"
require "securerandom"

module GraphQLBenchmark
QUERY_STRING = GraphQL::Introspection::INTROSPECTION_QUERY
Expand Down
20 changes: 1 addition & 19 deletions lib/graphql/backtrace.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# frozen_string_literal: true
require "graphql/backtrace/inspect_result"
require "graphql/backtrace/table"
require "graphql/backtrace/traced_error"
require "graphql/backtrace/tracer"
require "graphql/backtrace/trace"
module GraphQL
# Wrap unhandled errors with {TracedError}.
#
Expand All @@ -24,7 +21,7 @@ class Backtrace
def_delegators :to_a, :each, :[]

def self.use(schema_defn)
schema_defn.trace_with(self::Trace)
schema_defn.using_backtrace = true
end

def initialize(context, value: nil)
Expand All @@ -40,20 +37,5 @@ def inspect
def to_a
@table.to_backtrace
end

# Used for internal bookkeeping
# @api private
class Frame
attr_reader :path, :query, :ast_node, :object, :field, :arguments, :parent_frame
def initialize(path:, query:, ast_node:, object:, field:, arguments:, parent_frame:)
@path = path
@query = query
@ast_node = ast_node
@field = field
@object = object
@arguments = arguments
@parent_frame = parent_frame
end
end
end
end
38 changes: 0 additions & 38 deletions lib/graphql/backtrace/inspect_result.rb

This file was deleted.

150 changes: 95 additions & 55 deletions lib/graphql/backtrace/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,70 @@ def to_backtrace
private

def rows
@rows ||= build_rows(@context, rows: [HEADERS], top: true)
@rows ||= begin
query = @context.query
query_ctx = @context
runtime_inst = query_ctx.namespace(:interpreter_runtime)[:runtime]
result = runtime_inst.instance_variable_get(:@response)
rows = []
result_path = []
last_part = nil
path = @context.current_path
path.each do |path_part|
value = value_at(runtime_inst, result_path)

if result_path.empty?
name = query.selected_operation.operation_type || "query"
if (n = query.selected_operation_name)
name += " #{n}"
end
args = query.variables
else
name = result.graphql_field.path
args = result.graphql_arguments
end

object = result.graphql_parent ? result.graphql_parent.graphql_application_value : result.graphql_application_value
object = object.object.inspect

rows << [
result.ast_node.position.join(":"),
name,
"#{object}",
args.to_h.inspect,
inspect_result(value),
]

result_path << path_part
if path_part == path.last
last_part = path_part
else
result = result[path_part]
end
end


object = result.graphql_application_value.object.inspect
ast_node = result.graphql_selections.find { |s| s.alias == last_part || s.name == last_part }
field_defn = query.get_field(result.graphql_result_type, ast_node.name)
args = query.arguments_for(ast_node, field_defn).to_h
field_path = field_defn.path
if ast_node.alias
field_path += " as #{ast_node.alias}"
end

rows << [
ast_node.position.join(":"),
field_path,
"#{object}",
args.inspect,
inspect_result(@override_value)
]

rows << HEADERS
rows.reverse!
rows
end
end

# @return [String]
Expand Down Expand Up @@ -75,67 +138,44 @@ def render_table(rows)
table
end

# @return [Array] 5 items for a backtrace table (not `key`)
def build_rows(context_entry, rows:, top: false)
case context_entry
when Backtrace::Frame
field_alias = context_entry.ast_node.respond_to?(:alias) && context_entry.ast_node.alias
value = if top && @override_value
@override_value
else
value_at(@context.query.context.namespace(:interpreter_runtime)[:runtime], context_entry.path)
end
rows << [
"#{context_entry.ast_node ? context_entry.ast_node.position.join(":") : ""}",
"#{context_entry.field.path}#{field_alias ? " as #{field_alias}" : ""}",
"#{context_entry.object.object.inspect}",
context_entry.arguments.to_h.inspect, # rubocop:disable Development/ContextIsPassedCop -- unrelated method
Backtrace::InspectResult.inspect_result(value),
]
if (parent = context_entry.parent_frame)
build_rows(parent, rows: rows)
else
rows
end
when GraphQL::Query::Context
query = context_entry.query
op = query.selected_operation
if op
op_type = op.operation_type
position = "#{op.line}:#{op.col}"
else
op_type = "query"
position = "?:?"
end
op_name = query.selected_operation_name
object = query.root_value
if object.is_a?(GraphQL::Schema::Object)
object = object.object
end
value = value_at(context_entry.namespace(:interpreter_runtime)[:runtime], [])
rows << [
"#{position}",
"#{op_type}#{op_name ? " #{op_name}" : ""}",
"#{object.inspect}",
query.variables.to_h.inspect,
Backtrace::InspectResult.inspect_result(value),
]
else
raise "Unexpected get_rows subject #{context_entry.class} (#{context_entry.inspect})"
end
end

def value_at(runtime, path)
response = runtime.final_result
path.each do |key|
if response && (response = response[key])
next
else
break
end
response && (response = response[key])
end
response
end

def inspect_result(obj)
case obj
when Hash
"{" +
obj.map do |key, val|
"#{key}: #{inspect_truncated(val)}"
end.join(", ") +
"}"
when Array
"[" +
obj.map { |v| inspect_truncated(v) }.join(", ") +
"]"
else
inspect_truncated(obj)
end
end

def inspect_truncated(obj)
case obj
when Hash
"{...}"
when Array
"[...]"
when GraphQL::Execution::Lazy
"(unresolved)"
else
"#{obj.inspect}"
end
end
end
end
end
93 changes: 0 additions & 93 deletions lib/graphql/backtrace/trace.rb

This file was deleted.

Loading
Loading