Skip to content

Commit 156f6f3

Browse files
authored
Merge pull request #5477 from rmosolgo/perfetto-better-inspect
Improve .inspect support for DetailedTrace
2 parents f0232f0 + fc66fe3 commit 156f6f3

File tree

10 files changed

+77253
-43723
lines changed

10 files changed

+77253
-43723
lines changed

lib/graphql/tracing/detailed_trace.rb

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ module Tracing
99
# When `MySchema.detailed_trace?(query)` returns `true`, a profiler-specific `trace_mode: ...` will be used for the query,
1010
# overriding the one in `context[:trace_mode]`.
1111
#
12+
# By default, the detailed tracer calls `.inspect` on application objects returned from fields. You can customize
13+
# this behavior by extending {DetailedTrace} and overriding {#inspect_object}. You can opt out of debug annotations
14+
# entirely with `use ..., debug: false` or for a single query with `context: { detailed_trace_debug: false }`.
15+
#
1216
# __Redis__: The sampler stores its results in a provided Redis database. Depending on your needs,
13-
# You can configure this database to retail all data (persistent) or to expire data according to your rules.
17+
# You can configure this database to retain all data (persistent) or to expire data according to your rules.
1418
# If you need to save traces indefinitely, you can download them from Perfetto after opening them there.
1519
#
1620
# @example Adding the sampler to your schema
@@ -27,24 +31,45 @@ module Tracing
2731
# end
2832
#
2933
# @see Graphql::Dashboard GraphQL::Dashboard for viewing stored results
34+
#
35+
# @example Customizing debug output in traces
36+
# class CustomDetailedTrace < GraphQL::Tracing::DetailedTrace
37+
# def inspect_object(object)
38+
# if object.is_a?(SomeThing)
39+
# # handle it specially ...
40+
# else
41+
# super
42+
# end
43+
# end
44+
# end
45+
#
46+
# @example disabling debug annotations completely
47+
# use DetailedTrace, debug: false, ...
48+
#
49+
# @example disabling debug annotations for one query
50+
# MySchema.execute(query_str, context: { detailed_trace_debug: false })
51+
#
3052
class DetailedTrace
3153
# @param redis [Redis] If provided, profiles will be stored in Redis for later review
3254
# @param limit [Integer] A maximum number of profiles to store
33-
def self.use(schema, trace_mode: :profile_sample, memory: false, redis: nil, limit: nil)
55+
# @param debug [Boolean] if `false`, it won't create `debug` annotations in Perfetto traces (reduces overhead)
56+
def self.use(schema, trace_mode: :profile_sample, memory: false, debug: debug?, redis: nil, limit: nil)
3457
storage = if redis
3558
RedisBackend.new(redis: redis, limit: limit)
3659
elsif memory
3760
MemoryBackend.new(limit: limit)
3861
else
3962
raise ArgumentError, "Pass `redis: ...` to store traces in Redis for later review"
4063
end
41-
schema.detailed_trace = self.new(storage: storage, trace_mode: trace_mode)
64+
detailed_trace = self.new(storage: storage, trace_mode: trace_mode, debug: debug)
65+
schema.detailed_trace = detailed_trace
4266
schema.trace_with(PerfettoTrace, mode: trace_mode, save_profile: true)
4367
end
4468

45-
def initialize(storage:, trace_mode:)
69+
def initialize(storage:, trace_mode:, debug:)
4670
@storage = storage
4771
@trace_mode = trace_mode
72+
@debug = debug
4873
end
4974

5075
# @return [Symbol] The trace mode to use when {Schema.detailed_trace?} returns `true`
@@ -55,6 +80,11 @@ def save_trace(operation_name, duration_ms, begin_ms, trace_data)
5580
@storage.save_trace(operation_name, duration_ms, begin_ms, trace_data)
5681
end
5782

83+
# @return [Boolean]
84+
def debug?
85+
@debug
86+
end
87+
5888
# @param last [Integer]
5989
# @param before [Integer] Timestamp in milliseconds since epoch
6090
# @return [Enumerable<StoredTrace>]
@@ -77,6 +107,24 @@ def delete_all_traces
77107
@storage.delete_all_traces
78108
end
79109

110+
def inspect_object(object)
111+
self.class.inspect_object(object)
112+
end
113+
114+
def self.inspect_object(object)
115+
if defined?(ActiveRecord::Relation) && object.is_a?(ActiveRecord::Relation)
116+
"#{object.class}, .to_sql=#{object.to_sql.inspect}"
117+
else
118+
object.inspect
119+
end
120+
end
121+
122+
# Default debug setting
123+
# @return [true]
124+
def self.debug?
125+
true
126+
end
127+
80128
class StoredTrace
81129
def initialize(id:, operation_name:, duration_ms:, begin_ms:, trace_data:)
82130
@id = id

0 commit comments

Comments
 (0)