Tracing

GraphQL::Tracing::Trace provides hooks to observe and modify events during runtime. Tracing hooks are methods, defined in modules and mixed in with Schema.trace_with.

module CustomTrace
  def parse(query_string:)
    # measure, log, etc
    super
  end

  # ...
end

To include a trace module when running queries, add it to the schema with trace_with:

# Run `MyCustomTrace` for all queries
class MySchema < GraphQL::Schema
  trace_with(MyCustomTrace)
end

For a full list of methods and their arguments, see GraphQL::Tracing::Trace.

By default, GraphQL-Ruby makes a new trace instance when it runs a query. You can pass an existing instance as context: { trace: ... }. Also, GraphQL.parse( ..., trace: ...) accepts a trace instance.

Trace Modes

You can attach a trace module to run only in some circumstances by using mode:. For example, to add detailed tracing for only some requests:

trace_with DetailedTracing, mode: :detailed_metrics

Then, to opt into that trace, use context: { trace_mode: :detailed_metrics, ... } when executing queries.

Any custom trace modes also include the default trace_with ... modules (that is, those added without any particular mode: ... configuration).

ActiveSupport::Notifications

You can emit events to ActiveSupport::Notifications with an experimental tracer, ActiveSupportNotificationsTrace.

To enable it, install the tracer:

# Send execution events to ActiveSupport::Notifications
class MySchema < GraphQL::Schema
  trace_with(GraphQL::Tracing::ActiveSupportNotificationsTrace)
end

Monitoring

Several monitoring platforms are supported out-of-the box by GraphQL-Ruby (see platforms below).

Leaf fields are not monitored (to avoid high cardinality in the metrics service).

AppOptics

AppOptics instrumentation will be automatic starting with appoptics_apm-4.11.0.gem. For earlier gem versions please add appoptics_apm tracing as follows:

require 'appoptics_apm'

class MySchema < GraphQL::Schema
  use(GraphQL::Tracing::AppOpticsTracing)
end

Appsignal

To add AppSignal instrumentation:

class MySchema < GraphQL::Schema
  use(GraphQL::Tracing::AppsignalTracing)
end

New Relic

To add New Relic instrumentation:

class MySchema < GraphQL::Schema
  use(GraphQL::Tracing::NewRelicTracing)
  # Optional, use the operation name to set the new relic transaction name:
  # use(GraphQL::Tracing::NewRelicTracing, set_transaction_name: true)
end

Scout

To add Scout APM instrumentation:

class MySchema < GraphQL::Schema
  use(GraphQL::Tracing::ScoutTracing)
end

Skylight

To add Skylight instrumentation, you may either enable the GraphQL probe or use ActiveSupportNotificationsTracing.

# config/application.rb
config.skylight.probes << "graphql"

GraphQL instrumentation for Skylight is available in versions >= 4.2.0.

Datadog

To add Datadog instrumentation:

class MySchema < GraphQL::Schema
  use(GraphQL::Tracing::DataDogTracing, options)
end

You may provide options as a Hash with the following values:

Key Description Default
service Service name used for graphql instrumentation 'ruby-graphql'
tracer Datadog::Tracer used to perform instrumentation. Usually you don’t need to set this. Datadog.tracer

For more details about Datadog’s tracing API, check out the Ruby documentation or the APM documentation for more product information.

Prometheus

To add Prometheus instrumentation:

require 'prometheus_exporter/client'

class MySchema < GraphQL::Schema
  use(GraphQL::Tracing::PrometheusTracing)
end

The PrometheusExporter server must be run with a custom type collector that extends GraphQL::Tracing::PrometheusTracing::GraphQLCollector:

# lib/graphql_collector.rb
if defined?(PrometheusExporter::Server)
  require 'graphql/tracing'

  class GraphQLCollector < GraphQL::Tracing::PrometheusTracing::GraphQLCollector
  end
end
bundle exec prometheus_exporter -a lib/graphql_collector.rb

Statsd

You can add Statsd instrumentation by initializing a statsd client and passing it to GraphQL::Tracing::StatsdTracing:

$statsd = Statsd.new 'localhost', 9125
# ...

class MySchema < GraphQL::Schema
  use GraphQL::Tracing::StatsdTracing, statsd: $statsd
end

Any Statsd client that implements .time(name) { ... } will work.