class GraphQL::Tracing::DetailedTrace
DetailedTrace can make detailed profiles for a subset of production traffic. Install it in Rails with rails generate graphql:detailed_trace.
When MySchema.detailed_trace?(query) returns true, a profiler-specific trace_mode: ... will be used for the query, overriding the one in context[:trace_mode].
By default, the detailed tracer calls .inspect on application objects returned from fields. You can customize this behavior by extending DetailedTrace and overriding inspect object. You can opt out of debug annotations entirely with use ..., debug: false or for a single query with context: { detailed_trace_debug: false }.
You can store saved traces in two ways:
-
ActiveRecord: With
rails generate graphql:detailed_trace, a new migration will be added to your app. That table will be used to store trace data. -
Redis: Pass
redis: ...to save trace data to a Redis database. Depending on your needs, you can configure this database to retain all data (persistent) or to expire data according to your rules.
If you need to save traces indefinitely, you can download them from Perfetto after opening them there.
See GraphQL::Dashboard for viewing stored results.
Examples
Example: Installing with Rails
rails generate graphql:detailed_trace # optional: --redis
Example: Adding the sampler to your schema
class MySchema < GraphQL::Schema # Add the sampler: use GraphQL::Tracing::DetailedTrace, redis: Redis.new(...), limit: 100 # And implement this hook to tell it when to take a sample: def self.detailed_trace?(query) # Could use `query.context`, `query.selected_operation_name`, `query.query_string` here # Could call out to Flipper, etc rand <= 0.000_1 # one in ten thousand end end
Example: Customizing debug output in traces
class CustomDetailedTrace < GraphQL::Tracing::DetailedTrace def inspect_object(object) if object.is_a?(SomeThing) # handle it specially ... else super end end end
Example: disabling debug annotations completely
use DetailedTrace, debug: false, ...
Example: disabling debug annotations for one query
MySchema.execute(query_str, context: { detailed_trace_debug: false })
Attributes
Returns
-
Symbolβ The trace mode to use whenSchema.detailed_trace?returnstrue
Public Class Methods
Source
# File lib/graphql/tracing/detailed_trace.rb, line 202 def self.debug? true end
Default debug setting
Returns
-
true
Source
# File lib/graphql/tracing/detailed_trace.rb, line 186 def self.inspect_object(object) if defined?(ActiveRecord::Relation) && object.is_a?(ActiveRecord::Relation) "#{object.class}, .to_sql=#{object.to_sql.inspect}" else object.inspect end end
# File lib/graphql/tracing/detailed_trace.rb, line 106 def initialize(storage:, trace_mode:, debug:) @storage = storage @trace_mode = trace_mode @debug = debug end
# File lib/graphql/tracing/detailed_trace.rb, line 91 def self.use(schema, trace_mode: :profile_sample, memory: false, debug: debug?, redis: nil, limit: nil, model_class: nil) storage = if redis RedisBackend.new(redis: redis, limit: limit) elsif memory MemoryBackend.new(limit: limit) elsif defined?(ActiveRecord) ActiveRecordBackend.new(limit: limit, model_class: model_class) else raise ArgumentError, "To store traces, install ActiveRecord or provide `redis: ...`" end detailed_trace = self.new(storage: storage, trace_mode: trace_mode, debug: debug) schema.detailed_trace = detailed_trace schema.trace_with(PerfettoTrace, mode: trace_mode, save_profile: true) end
Parameters
-
redis(Redis) β If provided, profiles will be stored in Redis for later review -
limit(Integer) β A maximum number of profiles to store -
debug(Boolean) β iffalse, it wonβt createdebugannotations in Perfetto traces (reduces overhead) -
model_class(Class<ActiveRecord::Base>) β OverridesActiveRecordBackend::GraphqlDetailedTraceif present
Public Instance Methods
Source
# File lib/graphql/tracing/detailed_trace.rb, line 133 def debug? @debug end
Returns
-
Boolean
Source
# File lib/graphql/tracing/detailed_trace.rb, line 178 def delete_all_traces @storage.delete_all_traces end
Returns
-
void
Source
# File lib/graphql/tracing/detailed_trace.rb, line 168 def delete_trace(id) @storage.delete_trace(id) end
Returns
-
void
# File lib/graphql/tracing/detailed_trace.rb, line 158 def find_trace(id) @storage.find_trace(id) end
Returns
-
StoredTrace, nil
Source
# File lib/graphql/tracing/detailed_trace.rb, line 182 def inspect_object(object) self.class.inspect_object(object) end
# File lib/graphql/tracing/detailed_trace.rb, line 123 def save_trace(operation_name, duration_ms, begin_ms, trace_data) @storage.save_trace(operation_name, duration_ms, begin_ms, trace_data) end
Returns
-
Stringβ ID of saved trace
# File lib/graphql/tracing/detailed_trace.rb, line 148 def traces(last: nil, before: nil) @storage.traces(last: last, before: before) end
Parameters
-
last(Integer) -
before(Integer) β Timestamp in milliseconds since epoch
Returns
-
Enumerable<StoredTrace>