Skip to content

Commit c035ec7

Browse files
authored
Merge pull request #5271 from rmosolgo/nr-scalars-fix
Fix(NewRelic) reimplement trace_scalars
2 parents e4e6902 + dd4b4e5 commit c035ec7

File tree

3 files changed

+38
-29
lines changed

3 files changed

+38
-29
lines changed

cop/development/trace_methods_cop.rb

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def on_module(node)
7373
# Not really necessary for making a good trace:
7474
:lex, :analyze_query, :execute_query, :execute_query_lazy,
7575
# Only useful for isolated event tracking:
76+
:begin_dataloader, :end_dataloader,
7677
:dataloader_fiber_exit, :dataloader_spawn_execution_fiber, :dataloader_spawn_source_fiber
7778
]
7879
missing_defs.each do |missing_def|

lib/graphql/tracing/new_relic_trace.rb

+35-23
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ module NewRelicTrace
2222
# It can also be specified per-query with `context[:set_new_relic_transaction_name]`.
2323
# @param trace_authorized [Boolean] If `false`, skip tracing `authorized?` calls
2424
# @param trace_resolve_type [Boolean] If `false`, skip tracing `resolve_type?` calls
25-
def initialize(set_transaction_name: false, trace_authorized: true, trace_resolve_type: true, **_rest)
25+
# @param trace_scalars [Boolean] If `true`, Enum and Scalar fields will be traced by default
26+
def initialize(set_transaction_name: false, trace_authorized: true, trace_resolve_type: true, trace_scalars: false, **_rest)
2627
@set_transaction_name = set_transaction_name
2728
@trace_authorized = trace_authorized
2829
@trace_resolve_type = trace_resolve_type
30+
@trace_scalars = trace_scalars
2931
@nr_field_names = Hash.new do |h, field|
3032
h[field] = "GraphQL/#{field.owner.graphql_name}/#{field.graphql_name}"
3133
end.compare_by_identity
@@ -92,78 +94,88 @@ def end_execute_multiplex(multiplex)
9294
end
9395

9496
def begin_execute_field(field, object, arguments, query)
95-
nr_segment_stack << NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: @nr_field_names[field], category: :web)
97+
return_type = field.type.unwrap
98+
trace_field = if return_type.kind.scalar? || return_type.kind.enum?
99+
(field.trace.nil? && @trace_scalars) || field.trace
100+
else
101+
true
102+
end
103+
if trace_field
104+
start_segment(partial_name: @nr_field_names[field], category: :web)
105+
end
96106
super
97107
end
98108

99109
def end_execute_field(field, objects, arguments, query, result)
100-
nr_segment_stack.pop.finish
110+
finish_segment
101111
super
102112
end
103113

104114
def begin_authorized(type, obj, ctx)
105115
if @trace_authorized
106-
nr_segment_stack << NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: @nr_authorized_names[type], category: :web)
116+
start_segment(partial_name: @nr_authorized_names[type], category: :web)
107117
end
108118
super
109119
end
110120

111121
def end_authorized(type, obj, ctx, is_authed)
112122
if @trace_authorized
113-
nr_segment_stack.pop.finish
123+
finish_segment
114124
end
115125
super
116126
end
117127

118128
def begin_resolve_type(type, value, context)
119129
if @trace_resolve_type
120-
nr_segment_stack << NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: @nr_resolve_type_names[type], category: :web)
130+
start_segment(partial_name: @nr_resolve_type_names[type], category: :web)
121131
end
122132
super
123133
end
124134

125135
def end_resolve_type(type, value, context, resolved_type)
126136
if @trace_resolve_type
127-
nr_segment_stack.pop.finish
137+
finish_segment
128138
end
129139
super
130140
end
131141

132-
def begin_dataloader(dl)
133-
super
134-
end
135-
136-
def end_dataloader(dl)
137-
super
138-
end
139-
140142
def begin_dataloader_source(source)
141-
nr_segment_stack << NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: @nr_source_names[source], category: :web)
143+
start_segment(partial_name: @nr_source_names[source], category: :web)
142144
super
143145
end
144146

145147
def end_dataloader_source(source)
146-
nr_segment_stack.pop.finish
148+
finish_segment
147149
super
148150
end
149151

150152
def dataloader_fiber_yield(source)
151-
current_segment = nr_segment_stack.last
152-
current_segment.finish
153+
prev_segment = finish_segment
154+
Fiber[:graphql_nr_previous_segment] = prev_segment
153155
super
154156
end
155157

156158
def dataloader_fiber_resume(source)
157-
prev_segment = nr_segment_stack.pop
159+
prev_segment = Fiber[:graphql_nr_previous_segment]
160+
Fiber[:graphql_nr_previous_segment] = nil
158161
seg_partial_name = prev_segment.name.sub(/^.*(GraphQL.*)$/, '\1')
159-
nr_segment_stack << NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: seg_partial_name, category: :web)
162+
start_segment(partial_name: seg_partial_name, category: :web)
160163
super
161164
end
162165

163166
private
164167

165-
def nr_segment_stack
166-
Fiber[:graphql_nr_segment_stack] ||= []
168+
def start_segment(...)
169+
Fiber[:graphql_nr_segment] = NewRelic::Agent::Tracer.start_transaction_or_segment(...)
170+
end
171+
172+
def finish_segment
173+
segment = Fiber[:graphql_nr_segment]
174+
if segment
175+
segment.finish
176+
Fiber[:graphql_nr_segment] = nil
177+
segment
178+
end
167179
end
168180

169181
def transaction_name(query)

spec/graphql/tracing/new_relic_trace_spec.rb

+2-6
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class SchemaWithScalarTrace < GraphQL::Schema
8282

8383
class SchemaWithoutAuthorizedOrResolveType < GraphQL::Schema
8484
query(Query)
85-
trace_with(GraphQL::Tracing::NewRelicTrace, set_transaction_name: true, trace_authorized: false, trace_resolve_type: false)
85+
trace_with(GraphQL::Tracing::NewRelicTrace, set_transaction_name: true, trace_authorized: false, trace_resolve_type: false, trace_scalars: true)
8686
end
8787
end
8888

@@ -166,14 +166,12 @@ class SchemaWithoutAuthorizedOrResolveType < GraphQL::Schema
166166
"FINISH GraphQL/Query/other",
167167
"GraphQL/Authorized/Other",
168168
"FINISH GraphQL/Authorized/Other",
169-
"GraphQL/Other/name",
170-
"FINISH GraphQL/Other/name",
171169
"FINISH GraphQL/execute"
172170
]
173171
assert_equal expected_steps, NewRelic::EXECUTION_SCOPES
174172
end
175173

176-
it "can skip authorized and resolve type" do
174+
it "can skip authorized and resolve type and instrument scalars" do
177175
NewRelicTraceTest::SchemaWithoutAuthorizedOrResolveType.execute("{ nameable { name } }")
178176
expected_steps = [
179177
"GraphQL/parse",
@@ -235,8 +233,6 @@ class SchemaWithoutAuthorizedOrResolveType < GraphQL::Schema
235233
"GraphQL/Authorized/Other",
236234
"FINISH GraphQL/Authorized/Other",
237235

238-
"GraphQL/Other/name",
239-
"FINISH GraphQL/Other/name",
240236
"FINISH GraphQL/execute",
241237
]
242238
assert_equal expected_steps, NewRelic::EXECUTION_SCOPES

0 commit comments

Comments
 (0)