Skip to content

Commit

Permalink
Implement graphql's new tracing API
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyCTHsu committed Jan 29, 2024
1 parent 98eb182 commit 9559705
Show file tree
Hide file tree
Showing 14 changed files with 367 additions and 110 deletions.
16 changes: 9 additions & 7 deletions docs/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -848,24 +848,26 @@ The `instrument :graphql` method accepts the following parameters. Additional op
| Key | Description | Default |
| --- | ----------- | ------- |
| `schemas` | Array of `GraphQL::Schema` objects (that support class-based schema only) to trace. If you do not provide any, then tracing will applied to all the schemas. | `[]` |
| `with_deprecated_tracer` | Enable to instrument with deprecated `GraphQL::Tracing::DataDogTracing`. Default is `false`, using `GraphQL::Tracing::DataDogTrace` | `false` |
| `service_name` | Service name used for graphql instrumentation | `'ruby-graphql'` |

**Manually configuring GraphQL schemas**

If you prefer to individually configure the tracer settings for a schema (e.g. you have multiple schemas with different service names), in the schema definition, you can add the following [using the GraphQL API](http://graphql-ruby.org/queries/tracing.html):
If you prefer to individually configure the tracer settings for a schema (e.g. you have multiple schemas), in the schema definition, you can add the following [using the GraphQL API](http://graphql-ruby.org/queries/tracing.html):

With `GraphQL::Tracing::DataDogTrace`

```ruby
# Class-based schema
class YourSchema < GraphQL::Schema
use(GraphQL::Tracing::DataDogTracing)
trace_with GraphQL::Tracing::DataDogTrace
end
```

Or you can modify an already defined schema:
or with `GraphQL::Tracing::DataDogTracing` (deprecated)

```ruby
# Class-based schema
YourSchema.use(GraphQL::Tracing::DataDogTracing)
class YourSchema < GraphQL::Schema
use(GraphQL::Tracing::DataDogTracing)
end
```

**Note**: This integration does not support define-style schemas. Only class-based schemas are supported.
Expand Down
5 changes: 5 additions & 0 deletions lib/datadog/tracing/contrib/graphql/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ class Settings < Contrib::Configuration::Settings
end

option :service_name

option :with_deprecated_tracer do |o|
o.type :bool
o.default false
end
end
end
end
Expand Down
7 changes: 5 additions & 2 deletions lib/datadog/tracing/contrib/graphql/integration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ def self.version
end

def self.loaded?
!defined?(::GraphQL).nil? \
&& !defined?(::GraphQL::Tracing::DataDogTracing).nil?
!defined?(::GraphQL).nil?
end

# Breaking changes are introduced in `2.2.6` and have been backported to
Expand All @@ -37,6 +36,10 @@ def self.compatible?
)
end

def self.trace_supported?
version >= Gem::Version.new('2.0.19')
end

def new_configuration
Configuration::Settings.new
end
Expand Down
27 changes: 16 additions & 11 deletions lib/datadog/tracing/contrib/graphql/patcher.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require_relative '../analytics'
require_relative '../patcher'
require_relative 'tracing_patcher'
require_relative 'trace_patcher'

module Datadog
module Tracing
Expand All @@ -16,19 +18,18 @@ def target_version
end

def patch
schemas = configuration[:schemas]

if schemas.empty?
::GraphQL::Schema.tracer(::GraphQL::Tracing::DataDogTracing.new(**trace_options))
else
schemas.each do |schema|
if schema.respond_to? :use
schema.use(::GraphQL::Tracing::DataDogTracing, **trace_options)
else
Datadog.logger.warn("Unable to patch #{schema}, please migrate to class-based schema.")
end
unless configuration[:with_deprecated_tracer]
if Integration.trace_supported?
TracePatcher.patch!(schemas, trace_options)
else
Datadog.logger.warn(
"GraphQL version (#{target_version}) does not support GraphQL::Tracing::DataDogTrace. "\
'Falling back to GraphQL::Tracing::DataDogTracing.'
)
end
end

TracingPatcher.patch!(schemas, trace_options)
end

def trace_options
Expand All @@ -42,6 +43,10 @@ def trace_options
def configuration
Datadog.configuration.tracing[:graphql]
end

def schemas
configuration[:schemas]
end
end
end
end
Expand Down
24 changes: 24 additions & 0 deletions lib/datadog/tracing/contrib/graphql/trace_patcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Datadog
module Tracing
module Contrib
module GraphQL
# Provides instrumentation for `graphql` through with GraphQL's trace
module TracePatcher
module_function

def patch!(schemas, options)
if schemas.empty?
::GraphQL::Schema.trace_with(::GraphQL::Tracing::DataDogTrace, **options)
else
schemas.each do |schema|
schema.trace_with(::GraphQL::Tracing::DataDogTrace, **options)
end
end
end
end
end
end
end
end
28 changes: 28 additions & 0 deletions lib/datadog/tracing/contrib/graphql/tracing_patcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

module Datadog
module Tracing
module Contrib
module GraphQL
# Provides instrumentation for `graphql` through the GraphQL's tracing
module TracingPatcher
module_function

def patch!(schemas, options)
if schemas.empty?
::GraphQL::Schema.tracer(::GraphQL::Tracing::DataDogTracing.new(**options))
else
schemas.each do |schema|
if schema.respond_to? :use
schema.use(::GraphQL::Tracing::DataDogTracing, **options)
else
Datadog.logger.warn("Unable to patch #{schema}: Please migrate to class-based schema.")
end
end
end
end
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,30 @@
end
end
end

describe 'with_deprecated_tracer' do
context 'when default' do
it do
settings = described_class.new

expect(settings.with_deprecated_tracer).to eq(false)
end
end

context 'when given `true`' do
it do
settings = described_class.new(with_deprecated_tracer: true)

expect(settings.with_deprecated_tracer).to eq(true)
end
end

context 'when given `false`' do
it do
settings = described_class.new(with_deprecated_tracer: false)

expect(settings.with_deprecated_tracer).to eq(false)
end
end
end
end
26 changes: 16 additions & 10 deletions spec/datadog/tracing/contrib/graphql/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,19 @@
describe '.loaded?' do
subject(:loaded?) { described_class.loaded? }

context 'when neither GraphQL or GraphQL::Tracing::DataDogTracing are defined' do
context 'when GraphQL is not defined' do
before do
hide_const('GraphQL')
hide_const('GraphQL::Tracing::DataDogTracing')
end

it { is_expected.to be false }
end

context 'when only GraphQL is defined' do
context 'when GraphQL is defined' do
before do
stub_const('GraphQL', Class.new)
hide_const('GraphQL::Tracing::DataDogTracing')
end

it { is_expected.to be false }
end

context 'when GraphQL::Tracing::DataDogTracing is defined' do
before { stub_const('GraphQL::Tracing::DataDogTracing', Class.new) }

it { is_expected.to be true }
end
end
Expand Down Expand Up @@ -96,6 +88,20 @@
it { is_expected.to be(true) }
end

describe '.trace_supported?' do
subject(:trace_supported) { described_class.trace_supported? }

context 'with version `2.0.19`' do
include_context 'loaded gems', graphql: '2.0.19'
it { is_expected.to be true }
end

context 'with version `2.0.18`' do
include_context 'loaded gems', graphql: decrement_gem_version('2.0.19')
it { is_expected.to be false }
end
end

describe '#default_configuration' do
subject(:default_configuration) { integration.default_configuration }

Expand Down
147 changes: 147 additions & 0 deletions spec/datadog/tracing/contrib/graphql/patcher_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
require 'datadog/tracing/contrib/support/spec_helper'
require 'datadog/tracing/contrib/graphql/test_schema_examples'
require 'datadog/tracing/contrib/graphql/tracing_patcher'
require 'datadog/tracing/contrib/graphql/trace_patcher'

require 'ddtrace'

RSpec.describe Datadog::Tracing::Contrib::GraphQL::Patcher do
around do |example|
remove_patch!(:graphql)
Datadog.configuration.reset!
Datadog.configuration.tracing[:graphql].reset!

without_warnings do
example.run
end

remove_patch!(:graphql)
Datadog.configuration.reset!
Datadog.configuration.tracing[:graphql].reset!
end

describe 'patch' do
context 'when graphql does not support trace' do
context 'with default configuration' do
it 'patches GraphQL' do
allow(Datadog::Tracing::Contrib::GraphQL::Integration).to receive(:trace_supported?).and_return(true)
expect(Datadog::Tracing::Contrib::GraphQL::TracePatcher).to receive(:patch!).with(
[],
hash_including(:analytics_enabled, :analytics_sample_rate, :service)
)

Datadog.configure do |c|
c.tracing.instrument :graphql
end
end
end

context 'with with_deprecated_tracer enabled' do
it do
allow(Datadog::Tracing::Contrib::GraphQL::Integration).to receive(:trace_supported?).and_return(true)
expect(Datadog::Tracing::Contrib::GraphQL::TracingPatcher).to receive(:patch!).with(
[],
hash_including(:analytics_enabled, :analytics_sample_rate, :service)
)

Datadog.configure do |c|
c.tracing.instrument :graphql, with_deprecated_tracer: true
end
end
end

context 'with with_deprecated_tracer disabled' do
it do
allow(Datadog::Tracing::Contrib::GraphQL::Integration).to receive(:trace_supported?).and_return(true)
expect(Datadog::Tracing::Contrib::GraphQL::TracePatcher).to receive(:patch!).with(
[],
hash_including(:analytics_enabled, :analytics_sample_rate, :service)
)

Datadog.configure do |c|
c.tracing.instrument :graphql, with_deprecated_tracer: false
end
end
end

context 'with given schema' do
it do
allow(Datadog::Tracing::Contrib::GraphQL::Integration).to receive(:trace_supported?).and_return(true)
expect(Datadog::Tracing::Contrib::GraphQL::TracePatcher).to receive(:patch!).with(
[TestGraphQLSchema],
hash_including(:analytics_enabled, :analytics_sample_rate, :service)
)

Datadog.configure do |c|
c.tracing.instrument :graphql, schemas: [TestGraphQLSchema]
end
end
end
end

context 'when graphql supports trace' do
context 'with default configuration' do
it 'patches GraphQL' do
allow(Datadog::Tracing::Contrib::GraphQL::Integration).to receive(:trace_supported?).and_return(false)
expect(Datadog::Tracing::Contrib::GraphQL::TracingPatcher).to receive(:patch!).with(
[],
hash_including(:analytics_enabled, :analytics_sample_rate, :service)
)
expect_any_instance_of(Datadog::Core::Logger).to receive(:warn)
.with(/Falling back to GraphQL::Tracing::DataDogTracing/)

Datadog.configure do |c|
c.tracing.instrument :graphql
end
end
end

context 'with with_deprecated_tracer enabled' do
it do
allow(Datadog::Tracing::Contrib::GraphQL::Integration).to receive(:trace_supported?).and_return(false)
expect(Datadog::Tracing::Contrib::GraphQL::TracingPatcher).to receive(:patch!).with(
[],
hash_including(:analytics_enabled, :analytics_sample_rate, :service)
)
expect_any_instance_of(Datadog::Core::Logger).not_to receive(:warn)

Datadog.configure do |c|
c.tracing.instrument :graphql, with_deprecated_tracer: true
end
end
end

context 'with with_deprecated_tracer disabled' do
it do
allow(Datadog::Tracing::Contrib::GraphQL::Integration).to receive(:trace_supported?).and_return(false)
expect(Datadog::Tracing::Contrib::GraphQL::TracingPatcher).to receive(:patch!).with(
[],
hash_including(:analytics_enabled, :analytics_sample_rate, :service)
)
expect_any_instance_of(Datadog::Core::Logger).to receive(:warn)
.with(/Falling back to GraphQL::Tracing::DataDogTracing/)

Datadog.configure do |c|
c.tracing.instrument :graphql, with_deprecated_tracer: false
end
end
end

context 'with given schema' do
it do
allow(Datadog::Tracing::Contrib::GraphQL::Integration).to receive(:trace_supported?).and_return(false)
expect(Datadog::Tracing::Contrib::GraphQL::TracingPatcher).to receive(:patch!).with(
[TestGraphQLSchema],
hash_including(:analytics_enabled, :analytics_sample_rate, :service)
)
expect_any_instance_of(Datadog::Core::Logger).to receive(:warn)
.with(/Falling back to GraphQL::Tracing::DataDogTracing/)

Datadog.configure do |c|
c.tracing.instrument :graphql, schemas: [TestGraphQLSchema]
end
end
end
end
end
end
Loading

0 comments on commit 9559705

Please sign in to comment.