@@ -17,163 +17,56 @@ module Tracing
1717 # @example Installing without trace events for `authorized?` or `resolve_type` calls
1818 # trace_with GraphQL::Tracing::NewRelicTrace, trace_authorized: false, trace_resolve_type: false
1919 module NewRelicTrace
20- # @param set_transaction_name [Boolean] If true, the GraphQL operation name will be used as the transaction name.
21- # This is not advised if you run more than one query per HTTP request, for example, with `graphql-client` or multiplexing.
22- # It can also be specified per-query with `context[:set_new_relic_transaction_name]`.
23- # @param trace_authorized [Boolean] If `false`, skip tracing `authorized?` calls
24- # @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 )
26- @set_transaction_name = set_transaction_name
27- @trace_authorized = trace_authorized
28- @trace_resolve_type = trace_resolve_type
29- @nr_field_names = Hash . new do |h , field |
30- h [ field ] = "GraphQL/#{ field . owner . graphql_name } /#{ field . graphql_name } "
31- end . compare_by_identity
32-
33- @nr_authorized_names = Hash . new do |h , type |
34- h [ type ] = "GraphQL/Authorized/#{ type . graphql_name } "
35- end . compare_by_identity
36-
37- @nr_resolve_type_names = Hash . new do |h , type |
38- h [ type ] = "GraphQL/ResolveType/#{ type . graphql_name } "
39- end . compare_by_identity
40-
41- @nr_source_names = Hash . new do |h , source_inst |
42- h [ source_inst ] = "GraphQL/Source/#{ source_inst . class . name } "
43- end . compare_by_identity
44-
45- @nr_parse = @nr_validate = @nr_analyze = @nr_execute = nil
46- super
47- end
48-
49- def parse ( query_string :)
50- @nr_parse = NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : "GraphQL/parse" , category : :web )
51- super
52- ensure
53- @nr_parse . finish
54- end
55-
56- def begin_validate ( query , validate )
57- @nr_validate = NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : "GraphQL/validate" , category : :web )
58- super
59- end
60-
61- def end_validate ( query , validate , validation_errors )
62- @nr_validate . finish
63- super
64- end
65-
66- def begin_analyze_multiplex ( multiplex , analyzers )
67- @nr_analyze = NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : "GraphQL/analyze" , category : :web )
68- super
69- end
70-
71- def end_analyze_multiplex ( multiplex , analyzers )
72- @nr_analyze . finish
73- super
74- end
75-
76- def execute_multiplex ( multiplex :)
77- query = multiplex . queries . first
78- set_this_txn_name = query . context [ :set_new_relic_transaction_name ]
79- if set_this_txn_name || ( set_this_txn_name . nil? && @set_transaction_name )
80- NewRelic ::Agent . set_transaction_name ( transaction_name ( query ) )
20+ include NotificationsTrace
21+ class NewRelicEngine < NotificationsTrace ::Engine
22+ PARSE_NAME = "GraphQL/parse"
23+ LEX_NAME = "GraphQL/lex"
24+ VALIDATE_NAME = "GraphQL/validate"
25+ EXECUTE_NAME = "GraphQL/execute"
26+ ANALYZE_NAME = "GraphQL/analyze"
27+
28+ def instrument ( keyword , payload , &block )
29+ if keyword == :execute && payload . queries . size == 1
30+ query = payload . queries . first
31+ set_this_txn_name = query . context [ :set_new_relic_transaction_name ]
32+ if set_this_txn_name || ( set_this_txn_name . nil? && @set_transaction_name )
33+ NewRelic ::Agent . set_transaction_name ( transaction_name ( query ) )
34+ end
35+ end
36+ ::NewRelic ::Agent ::MethodTracerHelpers . trace_execution_scoped ( name_for ( keyword , payload ) , &block )
8137 end
82- @nr_execute = NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : "GraphQL/execute" , category : :web )
83- super
84- ensure
85- @nr_execute . finish
86- end
87-
88- def begin_execute_field ( field , object , arguments , query )
89- nr_segment_stack << NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : @nr_field_names [ field ] , category : :web )
90- super
91- end
92-
93- def end_execute_field ( field , objects , arguments , query , result )
94- nr_segment_stack . pop . finish
95- super
96- end
9738
98- def begin_authorized ( type , obj , ctx )
99- if @trace_authorized
100- nr_segment_stack << NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : @nr_authorized_names [ type ] , category : :web )
39+ def platform_source_class_key ( source_class )
40+ "GraphQL/Source/#{ source_class . name } "
10141 end
102- super
103- end
10442
105- def end_authorized ( type , obj , ctx , is_authed )
106- if @trace_authorized
107- nr_segment_stack . pop . finish
43+ def platform_field_key ( field )
44+ "GraphQL/#{ field . owner . graphql_name } /#{ field . graphql_name } "
10845 end
109- super
110- end
11146
112- def begin_resolve_type ( type , value , context )
113- if @trace_resolve_type
114- nr_segment_stack << NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : @nr_resolve_type_names [ type ] , category : :web )
47+ def platform_authorized_key ( type )
48+ "GraphQL/Authorized/#{ type . graphql_name } "
11549 end
116- super
117- end
11850
119- def end_resolve_type ( type , value , context , resolved_type )
120- if @trace_resolve_type
121- nr_segment_stack . pop . finish
51+ def platform_resolve_type_key ( type )
52+ "GraphQL/ResolveType/#{ type . graphql_name } "
12253 end
123- super
124- end
12554
126- def begin_dataloader ( dl )
127- super
128- end
55+ class Event < NotificationsTrace ::Engine ::Event
56+ def start
57+ name = @engine . name_for ( keyword , payload )
58+ @nr_ev = NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : name , category : :web )
59+ end
12960
130- def end_dataloader ( dl )
131- super
132- end
133-
134- def begin_dataloader_source ( source )
135- nr_segment_stack << NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : @nr_source_names [ source ] , category : :web )
136- super
137- end
138-
139- def end_dataloader_source ( source )
140- nr_segment_stack . pop . finish
141- super
142- end
143-
144- def dataloader_fiber_yield ( source )
145- current_segment = nr_segment_stack . last
146- current_segment . finish
147- super
148- end
149-
150- def dataloader_fiber_resume ( source )
151- prev_segment = nr_segment_stack . pop
152- seg_partial_name = prev_segment . name . sub ( /^.*(GraphQL.*)$/ , '\1' )
153- nr_segment_stack << NewRelic ::Agent ::Tracer . start_transaction_or_segment ( partial_name : seg_partial_name , category : :web )
154- super
155- end
156-
157- private
158-
159- def nr_segment_stack
160- Fiber [ :graphql_nr_segment_stack ] ||= [ ]
161- end
162-
163- def transaction_name ( query )
164- selected_op = query . selected_operation
165- txn_name = if selected_op
166- op_type = selected_op . operation_type
167- op_name = selected_op . name || fallback_transaction_name ( query . context ) || "anonymous"
168- "#{ op_type } .#{ op_name } "
169- else
170- "query.anonymous"
61+ def finish
62+ @nr_ev . finish
63+ end
17164 end
172- "GraphQL/#{ txn_name } "
17365 end
17466
175- def fallback_transaction_name ( context )
176- context [ :tracing_fallback_transaction_name ]
67+ # @see NotificationsTrace Parent module documents configuration options
68+ def initialize ( engine : NewRelicEngine , **_rest )
69+ super
17770 end
17871 end
17972 end
0 commit comments