Skip to content

Commit

Permalink
Migrate docs and some tests, make platform tracing use new traces und…
Browse files Browse the repository at this point in the history
…er the hood
  • Loading branch information
rmosolgo committed Feb 16, 2023
1 parent 1005822 commit ced5001
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 40 deletions.
19 changes: 4 additions & 15 deletions guides/queries/tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ desc: Observation hooks for execution
index: 11
---

{{ "GraphQL::Tracing" | api_doc }} provides a `.trace` hook to observe events from the GraphQL runtime.

A tracer must implement `.trace`, for example:
{{ "GraphQL::Tracing::Trace" | api_doc }} provides hooks to observe and modify events during runtime. Tracing hooks are methods, defined in modules and mixed in with {{ "Schema.trace_with" | api_doc }}.

```ruby
class MyCustomTracer
Expand All @@ -30,20 +28,13 @@ end
To run a tracer for __every query__, add it to the schema with `tracer`:

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

Or, to run a tracer for __one query only__, add it to `context:` as `tracers: [...]`, for example:

```ruby
# Run `MyCustomTracer` for this query
MySchema.execute(..., context: { tracers: [MyCustomTracer]})
```

For a full list of events, see the {{ "GraphQL::Tracing" | api_doc }} API docs.
For a full list of methods and their arguments, see {{ "GraphQL::Tracing::Trace" | api_doc }}.

## ActiveSupport::Notifications

Expand All @@ -64,8 +55,6 @@ Several monitoring platforms are supported out-of-the box by GraphQL-Ruby (see p

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

Implementations are based on {{ "Tracing::PlatformTracing" | api_doc }}.

## AppOptics

[AppOptics](https://appoptics.com/) instrumentation will be automatic starting
Expand Down
19 changes: 7 additions & 12 deletions guides/subscriptions/multi_tenant.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,22 @@ There are a few places where subscriptions might need to load data:

Each of these operations will need to select the right tenant in order to load data properly.

For __building the payload__, use a {% internal_link "Tracer", "queries/tracing" %}:
For __building the payload__, use a {% internal_link "Trace module", "queries/tracing" %}:

```ruby
class TenantSelectionTracer
def self.trace(event, data)
case event
when "execute_multiplex" # this is the top-level, umbrella event
context = data[:multiplex].queries.first.context # This assumes that all queries in a multiplex have the same tenant
MultiTenancy.select_tenant(context[:tenant]) do
module TenantSelectionTrace
def execute_multiplex(multiplex:) # this is the top-level, umbrella event
context = data[:multiplex].queries.first.context # This assumes that all queries in a multiplex have the same tenant
MultiTenancy.select_tenant(context[:tenant]) do
# ^^ your multi-tenancy implementation here
yield
end
else
yield
super # Call through to the rest of execution
end
end
end

# ...
class MySchema < GraphQL::Schema
tracer(TenantSelectionTracer)
trace_with(TenantSelectionTrace)
end
```

Expand Down
16 changes: 14 additions & 2 deletions lib/graphql/tracing/platform_tracing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,20 @@ def trace(key, data)
end

def self.use(schema_defn, options = {})
tracer = self.new(**options)
schema_defn.tracer(tracer)
if options[:legacy_tracing]
tracer = self.new(**options)
schema_defn.tracer(tracer)
else
tracing_name = self.name.split("::").last
trace_name = tracing_name.sub("Tracing", "Trace")
if GraphQL::Tracing.const_defined?(trace_name, false)
trace_module = GraphQL::Tracing.const_get(trace_name)
schema_defn.trace_with(trace_module, **options)
else
tracer = self.new(**options)
schema_defn.tracer(tracer)
end
end
end

private
Expand Down
17 changes: 6 additions & 11 deletions spec/graphql/subscriptions/action_cable_subscriptions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -304,23 +304,18 @@ class Subscription < GraphQL::Schema::Object
field :point_scored, subscription: PointScored
end

class TenantTracer
def self.trace(event, data)
case event
when "execute_multiplex"
tenant = data[:multiplex].queries.first.context[:tenant]
Data.switch(tenant) do
yield
end
else
yield
module TenantTrace
def execute_multiplex(multiplex:)
tenant = multiplex.queries.first.context[:tenant]
Data.switch(tenant) do
super
end
end
end

query(Player)
subscription(Subscription)
tracer(TenantTracer)
trace_with(TenantTrace)

module Serialize
def self.load(message, ctx)
Expand Down
4 changes: 4 additions & 0 deletions spec/graphql/tracing/new_relic_tracing_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ class SchemaWithScalarTrace < GraphQL::Schema
NewRelic.clear_all
end

it "Actually uses the new-style trace under the hood" do
assert NewRelicTest::SchemaWithoutTransactionName.trace_class < GraphQL::Tracing::NewRelicTrace
end

it "works with the built-in node field, even though it doesn't have an @owner" do
res = NewRelicTest::SchemaWithoutTransactionName.execute '{ node(id: "1") { __typename } }'
assert_equal "Thing", res["data"]["node"]["__typename"]
Expand Down

0 comments on commit ced5001

Please sign in to comment.