graphql 2.0.21 → 2.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
  3. data/lib/generators/graphql/mutation_update_generator.rb +1 -1
  4. data/lib/generators/graphql/relay.rb +18 -1
  5. data/lib/graphql/backtrace.rb +0 -4
  6. data/lib/graphql/dataloader/source.rb +69 -45
  7. data/lib/graphql/dataloader.rb +4 -4
  8. data/lib/graphql/execution/interpreter/arguments_cache.rb +31 -30
  9. data/lib/graphql/execution/interpreter/runtime.rb +122 -101
  10. data/lib/graphql/execution/interpreter.rb +1 -2
  11. data/lib/graphql/execution/lookahead.rb +1 -1
  12. data/lib/graphql/filter.rb +2 -1
  13. data/lib/graphql/introspection/entry_points.rb +1 -1
  14. data/lib/graphql/language/document_from_schema_definition.rb +16 -9
  15. data/lib/graphql/language/lexer.rb +89 -57
  16. data/lib/graphql/language/nodes.rb +3 -0
  17. data/lib/graphql/language/parser.rb +706 -691
  18. data/lib/graphql/language/parser.y +1 -0
  19. data/lib/graphql/language/printer.rb +28 -14
  20. data/lib/graphql/language/visitor.rb +64 -61
  21. data/lib/graphql/query/context.rb +16 -7
  22. data/lib/graphql/query/null_context.rb +8 -18
  23. data/lib/graphql/query/validation_pipeline.rb +2 -1
  24. data/lib/graphql/query.rb +37 -12
  25. data/lib/graphql/schema/addition.rb +38 -12
  26. data/lib/graphql/schema/always_visible.rb +10 -0
  27. data/lib/graphql/schema/argument.rb +8 -10
  28. data/lib/graphql/schema/build_from_definition.rb +8 -7
  29. data/lib/graphql/schema/directive.rb +1 -1
  30. data/lib/graphql/schema/enum_value.rb +2 -2
  31. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  32. data/lib/graphql/schema/field.rb +26 -15
  33. data/lib/graphql/schema/input_object.rb +9 -7
  34. data/lib/graphql/schema/interface.rb +5 -1
  35. data/lib/graphql/schema/introspection_system.rb +1 -1
  36. data/lib/graphql/schema/member/build_type.rb +10 -2
  37. data/lib/graphql/schema/member/has_arguments.rb +9 -7
  38. data/lib/graphql/schema/member/has_directives.rb +1 -1
  39. data/lib/graphql/schema/member/has_fields.rb +1 -1
  40. data/lib/graphql/schema/member/has_interfaces.rb +1 -1
  41. data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
  42. data/lib/graphql/schema/object.rb +6 -1
  43. data/lib/graphql/schema/printer.rb +3 -1
  44. data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
  45. data/lib/graphql/schema/resolver.rb +12 -10
  46. data/lib/graphql/schema/timeout.rb +1 -1
  47. data/lib/graphql/schema/validator.rb +1 -1
  48. data/lib/graphql/schema/warden.rb +37 -4
  49. data/lib/graphql/schema.rb +92 -23
  50. data/lib/graphql/tracing/appoptics_trace.rb +35 -11
  51. data/lib/graphql/tracing/appsignal_trace.rb +4 -0
  52. data/lib/graphql/tracing/data_dog_trace.rb +89 -50
  53. data/lib/graphql/tracing/data_dog_tracing.rb +7 -21
  54. data/lib/graphql/tracing/legacy_trace.rb +5 -1
  55. data/lib/graphql/tracing/notifications_trace.rb +7 -0
  56. data/lib/graphql/tracing/platform_trace.rb +26 -12
  57. data/lib/graphql/tracing/prometheus_trace.rb +4 -0
  58. data/lib/graphql/tracing/scout_trace.rb +3 -0
  59. data/lib/graphql/tracing/statsd_trace.rb +4 -0
  60. data/lib/graphql/tracing.rb +1 -0
  61. data/lib/graphql/types/relay/connection_behaviors.rb +1 -1
  62. data/lib/graphql/types/relay/edge_behaviors.rb +1 -1
  63. data/lib/graphql/version.rb +1 -1
  64. data/readme.md +1 -1
  65. metadata +36 -24
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "graphql/schema/addition"
3
+ require "graphql/schema/always_visible"
3
4
  require "graphql/schema/base_64_encoder"
4
5
  require "graphql/schema/find_inherited_value"
5
6
  require "graphql/schema/finder"
@@ -157,14 +158,25 @@ module GraphQL
157
158
  def trace_class_for(mode)
158
159
  @trace_modes ||= {}
159
160
  @trace_modes[mode] ||= begin
160
- base_class = if superclass.respond_to?(:trace_class_for)
161
- superclass.trace_class_for(mode)
162
- elsif mode == :default_backtrace
163
- GraphQL::Backtrace::DefaultBacktraceTrace
161
+ case mode
162
+ when :default
163
+ superclass_base_class = if superclass.respond_to?(:trace_class_for)
164
+ superclass.trace_class_for(mode)
165
+ else
166
+ GraphQL::Tracing::Trace
167
+ end
168
+ Class.new(superclass_base_class)
169
+ when :default_backtrace
170
+ schema_base_class = trace_class_for(:default)
171
+ Class.new(schema_base_class) do
172
+ include(GraphQL::Backtrace::Trace)
173
+ end
164
174
  else
165
- GraphQL::Tracing::Trace
175
+ mods = trace_modules_for(mode)
176
+ Class.new(trace_class_for(:default)) do
177
+ mods.any? && include(*mods)
178
+ end
166
179
  end
167
- Class.new(base_class)
168
180
  end
169
181
  end
170
182
 
@@ -179,6 +191,19 @@ module GraphQL
179
191
  nil
180
192
  end
181
193
 
194
+ def own_trace_modules
195
+ @own_trace_modules ||= Hash.new { |h, k| h[k] = [] }
196
+ end
197
+
198
+ # @return [Array<Module>] Modules added for tracing in `trace_mode`, including inherited ones
199
+ def trace_modules_for(trace_mode)
200
+ modules = own_trace_modules[trace_mode]
201
+ if superclass.respond_to?(:trace_modules_for)
202
+ modules += superclass.trace_modules_for(trace_mode)
203
+ end
204
+ modules
205
+ end
206
+
182
207
 
183
208
  # Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
184
209
  # @see {#as_json}
@@ -244,11 +269,13 @@ module GraphQL
244
269
  end
245
270
 
246
271
  def default_filter
247
- GraphQL::Filter.new(except: default_mask, silence_deprecation_warning: true)
272
+ GraphQL::Filter.new(except: default_mask)
248
273
  end
249
274
 
250
275
  def default_mask(new_mask = nil)
251
276
  if new_mask
277
+ line = caller(2, 10).find { |l| !l.include?("lib/graphql") }
278
+ GraphQL::Deprecation.warn("GraphQL::Filter and Schema.mask are deprecated and will be removed in v2.1.0. Implement `visible?` on your schema members instead (https://graphql-ruby.org/authorization/visibility.html).\n #{line}")
252
279
  @own_default_mask = new_mask
253
280
  else
254
281
  @own_default_mask || find_inherited_value(:default_mask, Schema::NullMask)
@@ -418,6 +445,18 @@ module GraphQL
418
445
  @root_types
419
446
  end
420
447
 
448
+ def warden_class
449
+ if defined?(@warden_class)
450
+ @warden_class
451
+ elsif superclass.respond_to?(:warden_class)
452
+ superclass.warden_class
453
+ else
454
+ GraphQL::Schema::Warden
455
+ end
456
+ end
457
+
458
+ attr_writer :warden_class
459
+
421
460
  # @param type [Module] The type definition whose possible types you want to see
422
461
  # @return [Hash<String, Module>] All possible types, if no `type` is given.
423
462
  # @return [Array<Module>] Possible types for `type`, if it's given.
@@ -959,10 +998,8 @@ module GraphQL
959
998
  end
960
999
 
961
1000
  def tracer(new_tracer)
962
- if defined?(@trace_modes) && !(trace_class_for(:default) < GraphQL::Tracing::LegacyTrace)
963
- raise ArgumentError, "Can't add tracer after configuring a `trace_class`, use GraphQL::Tracing::LegacyTrace to merge legacy tracers into a trace class instead."
964
- else
965
- trace_mode(:default, Class.new(GraphQL::Tracing::LegacyTrace))
1001
+ if !(trace_class_for(:default) < GraphQL::Tracing::CallLegacyTracers)
1002
+ trace_with(GraphQL::Tracing::CallLegacyTracers)
966
1003
  end
967
1004
 
968
1005
  own_tracers << new_tracer
@@ -976,28 +1013,58 @@ module GraphQL
976
1013
  # will be called at runtime.
977
1014
  #
978
1015
  # @param trace_mod [Module] A module that implements tracing methods
1016
+ # @param mode [Symbol] Trace module will only be used for this trade mode
979
1017
  # @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
980
1018
  # @return [void]
981
- def trace_with(trace_mod, **options)
982
- trace_options.merge!(options)
983
- trace_class.include(trace_mod)
1019
+ def trace_with(trace_mod, mode: :default, **options)
1020
+ if mode.is_a?(Array)
1021
+ mode.each { |m| trace_with(trace_mod, mode: m, **options) }
1022
+ else
1023
+ tc = trace_class_for(mode)
1024
+ tc.include(trace_mod)
1025
+ if mode != :default
1026
+ own_trace_modules[mode] << trace_mod
1027
+ end
1028
+ t_opts = trace_options_for(mode)
1029
+ t_opts.merge!(options)
1030
+ end
1031
+ nil
984
1032
  end
985
1033
 
986
- def trace_options
987
- @trace_options ||= superclass.respond_to?(:trace_options) ? superclass.trace_options.dup : {}
1034
+ # The options hash for this trace mode
1035
+ # @return [Hash]
1036
+ def trace_options_for(mode)
1037
+ @trace_options_for_mode ||= {}
1038
+ @trace_options_for_mode[mode] ||= begin
1039
+ if superclass.respond_to?(:trace_options_for)
1040
+ superclass.trace_options_for(mode).dup
1041
+ else
1042
+ {}
1043
+ end
1044
+ end
988
1045
  end
989
1046
 
990
- def new_trace(**options)
991
- if defined?(@trace_options)
992
- options = trace_options.merge(options)
993
- end
994
- trace_mode = if (target = options[:query] || options[:multiplex]) && target.context[:backtrace]
1047
+ # Create a trace instance which will include the trace modules specified for the optional mode.
1048
+ #
1049
+ # @param mode [Symbol] Trace modules for this trade mode will be included
1050
+ # @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
1051
+ # @return [Tracing::Trace]
1052
+ def new_trace(mode: nil, **options)
1053
+ target = options[:query] || options[:multiplex]
1054
+ mode ||= target && target.context[:trace_mode]
1055
+
1056
+ trace_mode = if mode
1057
+ mode
1058
+ elsif target && target.context[:backtrace]
995
1059
  :default_backtrace
996
1060
  else
997
1061
  :default
998
1062
  end
999
- trace = trace_class_for(trace_mode).new(**options)
1000
- trace
1063
+
1064
+ base_trace_options = trace_options_for(trace_mode)
1065
+ trace_options = base_trace_options.merge(options)
1066
+ trace_class_for_mode = trace_class_for(trace_mode)
1067
+ trace_class_for_mode.new(**trace_options)
1001
1068
  end
1002
1069
 
1003
1070
  def query_analyzer(new_analyzer)
@@ -1036,7 +1103,9 @@ module GraphQL
1036
1103
  {
1037
1104
  backtrace: ctx[:backtrace],
1038
1105
  tracers: ctx[:tracers],
1106
+ trace: ctx[:trace],
1039
1107
  dataloader: ctx[:dataloader],
1108
+ trace_mode: ctx[:trace_mode],
1040
1109
  }
1041
1110
  else
1042
1111
  {}
@@ -28,6 +28,8 @@ module GraphQL
28
28
  Gem::Version.new('1.0.0')
29
29
  end
30
30
 
31
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
32
+
31
33
  [
32
34
  'lex',
33
35
  'parse',
@@ -55,20 +57,41 @@ module GraphQL
55
57
  RUBY
56
58
  end
57
59
 
58
- def platform_execute_field(platform_key, data)
59
- return super if !defined?(AppOpticsAPM) || gql_config[:enabled] == false
60
- layer = platform_key
61
- kvs = metadata(data, layer)
60
+ # rubocop:enable Development/NoEvalCop
62
61
 
63
- ::AppOpticsAPM::SDK.trace(layer, kvs) do
64
- kvs.clear # we don't have to send them twice
65
- yield
62
+ def execute_field(query:, field:, ast_node:, arguments:, object:)
63
+ return_type = field.type.unwrap
64
+ trace_field = if return_type.kind.scalar? || return_type.kind.enum?
65
+ (field.trace.nil? && @trace_scalars) || field.trace
66
+ else
67
+ true
68
+ end
69
+ platform_key = if trace_field
70
+ @platform_key_cache[AppOpticsTrace].platform_field_key_cache[field]
71
+ else
72
+ nil
73
+ end
74
+ if platform_key && trace_field
75
+ return super if !defined?(AppOpticsAPM) || gql_config[:enabled] == false
76
+ layer = platform_key
77
+ kvs = metadata({query: query, field: field, ast_node: ast_node, arguments: arguments, object: object}, layer)
78
+
79
+ ::AppOpticsAPM::SDK.trace(layer, kvs) do
80
+ kvs.clear # we don't have to send them twice
81
+ super
82
+ end
83
+ else
84
+ super
66
85
  end
67
86
  end
68
87
 
88
+ def execute_field_lazy(query:, field:, ast_node:, arguments:, object:)
89
+ execute_field(query: query, field: field, ast_node: ast_node, arguments: arguments, object: object)
90
+ end
91
+
69
92
  def authorized(**data)
70
93
  return super if !defined?(AppOpticsAPM) || gql_config[:enabled] == false
71
- layer = @platform_authorized_key_cache[data[:type]]
94
+ layer = @platform_key_cache[AppOpticsTrace].platform_authorized_key_cache[data[:type]]
72
95
  kvs = metadata(data, layer)
73
96
 
74
97
  ::AppOpticsAPM::SDK.trace(layer, kvs) do
@@ -79,7 +102,7 @@ module GraphQL
79
102
 
80
103
  def authorized_lazy(**data)
81
104
  return super if !defined?(AppOpticsAPM) || gql_config[:enabled] == false
82
- layer = @platform_authorized_key_cache[data[:type]]
105
+ layer = @platform_key_cache[AppOpticsTrace].platform_authorized_key_cache[data[:type]]
83
106
  kvs = metadata(data, layer)
84
107
 
85
108
  ::AppOpticsAPM::SDK.trace(layer, kvs) do
@@ -90,7 +113,8 @@ module GraphQL
90
113
 
91
114
  def resolve_type(**data)
92
115
  return super if !defined?(AppOpticsAPM) || gql_config[:enabled] == false
93
- layer = @platform_resolve_type_key_cache[data[:type]]
116
+ layer = @platform_key_cache[AppOpticsTrace].platform_resolve_type_key_cache[data[:type]]
117
+
94
118
  kvs = metadata(data, layer)
95
119
 
96
120
  ::AppOpticsAPM::SDK.trace(layer, kvs) do
@@ -101,7 +125,7 @@ module GraphQL
101
125
 
102
126
  def resolve_type_lazy(**data)
103
127
  return super if !defined?(AppOpticsAPM) || gql_config[:enabled] == false
104
- layer = @platform_resolve_type_key_cache[data[:type]]
128
+ layer = @platform_key_cache[AppOpticsTrace].platform_resolve_type_key_cache[data[:type]]
105
129
  kvs = metadata(data, layer)
106
130
 
107
131
  ::AppOpticsAPM::SDK.trace(layer, kvs) do
@@ -13,6 +13,8 @@ module GraphQL
13
13
  super
14
14
  end
15
15
 
16
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
17
+
16
18
  {
17
19
  "lex" => "lex.graphql",
18
20
  "parse" => "parse.graphql",
@@ -43,6 +45,8 @@ module GraphQL
43
45
  RUBY
44
46
  end
45
47
 
48
+ # rubocop:enable Development/NoEvalCop
49
+
46
50
  def platform_execute_field(platform_key)
47
51
  Appsignal.instrument(platform_key) do
48
52
  yield
@@ -3,24 +3,25 @@
3
3
  module GraphQL
4
4
  module Tracing
5
5
  module DataDogTrace
6
+ # @param tracer [#trace] Deprecated
6
7
  # @param analytics_enabled [Boolean] Deprecated
7
8
  # @param analytics_sample_rate [Float] Deprecated
8
- def initialize(tracer: nil, analytics_enabled: false, analytics_sample_rate: 1.0, service: "ruby-graphql", **rest)
9
+ def initialize(tracer: nil, analytics_enabled: false, analytics_sample_rate: 1.0, service: nil, **rest)
9
10
  if tracer.nil?
10
11
  tracer = defined?(Datadog::Tracing) ? Datadog::Tracing : Datadog.tracer
11
12
  end
12
13
  @tracer = tracer
13
14
 
14
- analytics_available = defined?(Datadog::Contrib::Analytics) \
15
- && Datadog::Contrib::Analytics.respond_to?(:enabled?) \
16
- && Datadog::Contrib::Analytics.respond_to?(:set_sample_rate)
17
-
18
- @analytics_enabled = analytics_available && Datadog::Contrib::Analytics.enabled?(analytics_enabled)
15
+ @analytics_enabled = analytics_enabled
19
16
  @analytics_sample_rate = analytics_sample_rate
17
+
20
18
  @service_name = service
19
+ @has_prepare_span = respond_to?(:prepare_span)
21
20
  super
22
21
  end
23
22
 
23
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
24
+
24
25
  {
25
26
  'lex' => 'lex.graphql',
26
27
  'parse' => 'parse.graphql',
@@ -33,12 +34,9 @@ module GraphQL
33
34
  }.each do |trace_method, trace_key|
34
35
  module_eval <<-RUBY, __FILE__, __LINE__
35
36
  def #{trace_method}(**data)
36
- @tracer.trace("#{trace_key}", service: @service_name) do |span|
37
- span.span_type = 'custom'
38
- if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
39
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
40
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, '#{trace_method}')
41
- end
37
+ @tracer.trace("#{trace_key}", service: @service_name, type: 'custom') do |span|
38
+ span.set_tag('component', 'graphql')
39
+ span.set_tag('operation', '#{trace_method}')
42
40
 
43
41
  #{
44
42
  if trace_method == 'execute_multiplex'
@@ -53,10 +51,8 @@ module GraphQL
53
51
  end
54
52
  span.resource = resource if resource
55
53
 
56
- # For top span of query, set the analytics sample rate tag, if available.
57
- if @analytics_enabled
58
- Datadog::Contrib::Analytics.set_sample_rate(span, @analytics_sample_rate)
59
- end
54
+ # [Deprecated] will be removed in the future
55
+ span.set_metric('_dd1.sr.eausr', @analytics_sample_rate) if @analytics_enabled
60
56
  RUBY
61
57
  elsif trace_method == 'execute_query'
62
58
  <<-RUBY
@@ -66,61 +62,104 @@ module GraphQL
66
62
  RUBY
67
63
  end
68
64
  }
69
- prepare_span("#{trace_method.sub("platform_", "")}", data, span)
65
+ if @has_prepare_span
66
+ prepare_span("#{trace_method.sub("platform_", "")}", data, span)
67
+ end
70
68
  super
71
69
  end
72
70
  end
73
71
  RUBY
74
72
  end
75
73
 
76
- def platform_execute_field(platform_key, data, span_key = "execute_field")
77
- @tracer.trace(platform_key, service: @service_name) do |span|
78
- span.span_type = 'custom'
79
- if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
80
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
81
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, span_key)
74
+ # rubocop:enable Development/NoEvalCop
75
+
76
+ def execute_field_span(span_key, query, field, ast_node, arguments, object)
77
+ return_type = field.type.unwrap
78
+ trace_field = if return_type.kind.scalar? || return_type.kind.enum?
79
+ (field.trace.nil? && @trace_scalars) || field.trace
80
+ else
81
+ true
82
+ end
83
+ platform_key = if trace_field
84
+ @platform_key_cache[DataDogTrace].platform_field_key_cache[field]
85
+ else
86
+ nil
87
+ end
88
+ if platform_key && trace_field
89
+ @tracer.trace(platform_key, service: @service_name, type: 'custom') do |span|
90
+ span.set_tag('component', 'graphql')
91
+ span.set_tag('operation', span_key)
92
+
93
+ if @has_prepare_span
94
+ prepare_span_data = { query: query, field: field, ast_node: ast_node, arguments: arguments, object: object }
95
+ prepare_span(span_key, prepare_span_data, span)
96
+ end
97
+ yield
82
98
  end
83
- prepare_span(span_key, data, span)
99
+ else
84
100
  yield
85
101
  end
86
102
  end
103
+ def execute_field(query:, field:, ast_node:, arguments:, object:)
104
+ execute_field_span("execute_field", query, field, ast_node, arguments, object) do
105
+ super(query: query, field: field, ast_node: ast_node, arguments: arguments, object: object)
106
+ end
107
+ end
87
108
 
88
- def platform_execute_field_lazy(platform_key, data, &block)
89
- platform_execute_field(platform_key, data, "execute_field_lazy", &block)
109
+ def execute_field_lazy(query:, field:, ast_node:, arguments:, object:)
110
+ execute_field_span("execute_field_lazy", query, field, ast_node, arguments, object) do
111
+ super(query: query, field: field, ast_node: ast_node, arguments: arguments, object: object)
112
+ end
90
113
  end
91
114
 
92
- def authorized(object:, type:, query:, span_key: "authorized")
93
- platform_key = @platform_authorized_key_cache[type]
94
- @tracer.trace(platform_key, service: @service_name) do |span|
95
- span.span_type = 'custom'
96
- if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
97
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
98
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, span_key)
99
- end
100
- prepare_span(span_key, {object: object, type: type, query: query}, span)
115
+ def authorized(query:, type:, object:)
116
+ authorized_span("authorized", object, type, query) do
101
117
  super(query: query, type: type, object: object)
102
118
  end
103
119
  end
104
120
 
105
- def authorized_lazy(**kwargs, &block)
106
- authorized(span_key: "authorized_lazy", **kwargs, &block)
107
- end
121
+ def authorized_span(span_key, object, type, query)
122
+ platform_key = @platform_key_cache[DataDogTrace].platform_authorized_key_cache[type]
123
+ @tracer.trace(platform_key, service: @service_name, type: 'custom') do |span|
124
+ span.set_tag('component', 'graphql')
125
+ span.set_tag('operation', span_key)
108
126
 
109
- def resolve_type(object:, type:, query:, span_key: "resolve_type")
110
- platform_key = @platform_resolve_type_key_cache[type]
111
- @tracer.trace(platform_key, service: @service_name) do |span|
112
- span.span_type = 'custom'
113
- if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
114
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
115
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, span_key)
127
+ if @has_prepare_span
128
+ prepare_span(span_key, {object: object, type: type, query: query}, span)
116
129
  end
117
- prepare_span(span_key, {object: object, type: type, query: query}, span)
130
+ yield
131
+ end
132
+ end
133
+
134
+ def authorized_lazy(object:, type:, query:)
135
+ authorized_span("authorized_lazy", object, type, query) do
118
136
  super(query: query, type: type, object: object)
119
137
  end
120
138
  end
121
139
 
122
- def resolve_type_lazy(**kwargs, &block)
123
- resolve_type(span_key: "resolve_type_lazy", **kwargs, &block)
140
+ def resolve_type(object:, type:, query:)
141
+ resolve_type_span("resolve_type", object, type, query) do
142
+ super(object: object, query: query, type: type)
143
+ end
144
+ end
145
+
146
+ def resolve_type_lazy(object:, type:, query:)
147
+ resolve_type_span("resolve_type_lazy", object, type, query) do
148
+ super(object: object, query: query, type: type)
149
+ end
150
+ end
151
+
152
+ def resolve_type_span(span_key, object, type, query)
153
+ platform_key = @platform_key_cache[DataDogTrace].platform_resolve_type_key_cache[type]
154
+ @tracer.trace(platform_key, service: @service_name, type: 'custom') do |span|
155
+ span.set_tag('component', 'graphql')
156
+ span.set_tag('operation', span_key)
157
+
158
+ if @has_prepare_span
159
+ prepare_span(span_key, {object: object, type: type, query: query}, span)
160
+ end
161
+ yield
162
+ end
124
163
  end
125
164
 
126
165
  include PlatformTrace
@@ -129,8 +168,8 @@ module GraphQL
129
168
  # @param key [String] The event being traced
130
169
  # @param data [Hash] The runtime data for this event (@see GraphQL::Tracing for keys for each event)
131
170
  # @param span [Datadog::Tracing::SpanOperation] The datadog span for this event
132
- def prepare_span(key, data, span)
133
- end
171
+ # def prepare_span(key, data, span)
172
+ # end
134
173
 
135
174
  def platform_field_key(field)
136
175
  field.path
@@ -15,12 +15,9 @@ module GraphQL
15
15
  }
16
16
 
17
17
  def platform_trace(platform_key, key, data)
18
- tracer.trace(platform_key, service: service_name) do |span|
19
- span.span_type = 'custom'
20
- if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
21
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
22
- span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, key)
23
- end
18
+ tracer.trace(platform_key, service: options[:service], type: 'custom') do |span|
19
+ span.set_tag('component', 'graphql')
20
+ span.set_tag('operation', key)
24
21
 
25
22
  if key == 'execute_multiplex'
26
23
  operations = data[:multiplex].queries.map(&:selected_operation_name).join(', ')
@@ -33,10 +30,8 @@ module GraphQL
33
30
  end
34
31
  span.resource = resource if resource
35
32
 
36
- # For top span of query, set the analytics sample rate tag, if available.
37
- if analytics_enabled?
38
- Datadog::Contrib::Analytics.set_sample_rate(span, analytics_sample_rate)
39
- end
33
+ # [Deprecated] will be removed in the future
34
+ span.set_metric('_dd1.sr.eausr', analytics_sample_rate) if analytics_enabled?
40
35
  end
41
36
 
42
37
  if key == 'execute_query'
@@ -51,10 +46,6 @@ module GraphQL
51
46
  end
52
47
  end
53
48
 
54
- def service_name
55
- options.fetch(:service, 'ruby-graphql')
56
- end
57
-
58
49
  # Implement this method in a subclass to apply custom tags to datadog spans
59
50
  # @param key [String] The event being traced
60
51
  # @param data [Hash] The runtime data for this event (@see GraphQL::Tracing for keys for each event)
@@ -65,18 +56,13 @@ module GraphQL
65
56
  def tracer
66
57
  default_tracer = defined?(Datadog::Tracing) ? Datadog::Tracing : Datadog.tracer
67
58
 
59
+ # [Deprecated] options[:tracer] will be removed in the future
68
60
  options.fetch(:tracer, default_tracer)
69
61
  end
70
62
 
71
- def analytics_available?
72
- defined?(Datadog::Contrib::Analytics) \
73
- && Datadog::Contrib::Analytics.respond_to?(:enabled?) \
74
- && Datadog::Contrib::Analytics.respond_to?(:set_sample_rate)
75
- end
76
-
77
63
  def analytics_enabled?
78
64
  # [Deprecated] options[:analytics_enabled] will be removed in the future
79
- analytics_available? && Datadog::Contrib::Analytics.enabled?(options.fetch(:analytics_enabled, false))
65
+ options.fetch(:analytics_enabled, false)
80
66
  end
81
67
 
82
68
  def analytics_sample_rate
@@ -4,7 +4,7 @@ module GraphQL
4
4
  # This trace class calls legacy-style tracer with payload hashes.
5
5
  # New-style `trace_with` modules significantly reduce the overhead of tracing,
6
6
  # but that advantage is lost when legacy-style tracers are also used (since the payload hashes are still constructed).
7
- class LegacyTrace < Trace
7
+ module CallLegacyTracers
8
8
  def lex(query_string:)
9
9
  (@multiplex || @query).trace("lex", { query_string: query_string }) { super }
10
10
  end
@@ -61,5 +61,9 @@ module GraphQL
61
61
  query.trace("resolve_type_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
62
62
  end
63
63
  end
64
+
65
+ class LegacyTrace < Trace
66
+ include CallLegacyTracers
67
+ end
64
68
  end
65
69
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_trace"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  # This implementation forwards events to a notification handler (i.e.
@@ -14,12 +16,15 @@ module GraphQL
14
16
  super
15
17
  end
16
18
 
19
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
20
+
17
21
  {
18
22
  "lex" => "lex.graphql",
19
23
  "parse" => "parse.graphql",
20
24
  "validate" => "validate.graphql",
21
25
  "analyze_multiplex" => "analyze_multiplex.graphql",
22
26
  "analyze_query" => "analyze_query.graphql",
27
+ "execute_multiplex" => "execute_multiplex.graphql",
23
28
  "execute_query" => "execute_query.graphql",
24
29
  "execute_query_lazy" => "execute_query_lazy.graphql",
25
30
  "execute_field" => "execute_field.graphql",
@@ -36,6 +41,8 @@ module GraphQL
36
41
  RUBY
37
42
  end
38
43
 
44
+ # rubocop:enable Development/NoEvalCop
45
+
39
46
  include PlatformTrace
40
47
  end
41
48
  end