graphql 2.4.11 → 2.4.15

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/analyzer.rb +2 -1
  3. data/lib/graphql/analysis/visitor.rb +37 -40
  4. data/lib/graphql/analysis.rb +12 -9
  5. data/lib/graphql/backtrace/table.rb +37 -14
  6. data/lib/graphql/execution/interpreter/runtime.rb +12 -2
  7. data/lib/graphql/execution/interpreter.rb +1 -0
  8. data/lib/graphql/invalid_null_error.rb +1 -5
  9. data/lib/graphql/language/lexer.rb +7 -3
  10. data/lib/graphql/language/nodes.rb +3 -0
  11. data/lib/graphql/language/parser.rb +1 -1
  12. data/lib/graphql/language/static_visitor.rb +37 -33
  13. data/lib/graphql/language/visitor.rb +59 -55
  14. data/lib/graphql/schema/argument.rb +7 -8
  15. data/lib/graphql/schema/build_from_definition.rb +99 -53
  16. data/lib/graphql/schema/directive.rb +1 -1
  17. data/lib/graphql/schema/enum.rb +2 -2
  18. data/lib/graphql/schema/enum_value.rb +1 -1
  19. data/lib/graphql/schema/field.rb +2 -2
  20. data/lib/graphql/schema/input_object.rb +16 -16
  21. data/lib/graphql/schema/interface.rb +1 -1
  22. data/lib/graphql/schema/member/has_directives.rb +1 -1
  23. data/lib/graphql/schema/member/has_fields.rb +1 -1
  24. data/lib/graphql/schema/member/has_interfaces.rb +1 -1
  25. data/lib/graphql/schema/member/scoped.rb +1 -1
  26. data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
  27. data/lib/graphql/schema/resolver.rb +5 -1
  28. data/lib/graphql/schema.rb +6 -4
  29. data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
  30. data/lib/graphql/testing/helpers.rb +5 -2
  31. data/lib/graphql/tracing/appoptics_trace.rb +4 -0
  32. data/lib/graphql/tracing/appsignal_trace.rb +4 -0
  33. data/lib/graphql/tracing/data_dog_trace.rb +4 -0
  34. data/lib/graphql/tracing/new_relic_trace.rb +41 -24
  35. data/lib/graphql/tracing/notifications_trace.rb +4 -0
  36. data/lib/graphql/tracing/platform_trace.rb +5 -0
  37. data/lib/graphql/tracing/prometheus_trace.rb +4 -0
  38. data/lib/graphql/tracing/scout_trace.rb +3 -0
  39. data/lib/graphql/tracing/sentry_trace.rb +4 -0
  40. data/lib/graphql/tracing/statsd_trace.rb +4 -0
  41. data/lib/graphql/types/relay/connection_behaviors.rb +1 -1
  42. data/lib/graphql/types/relay/edge_behaviors.rb +1 -1
  43. data/lib/graphql/version.rb +1 -1
  44. metadata +3 -31
@@ -13,16 +13,21 @@ module GraphQL
13
13
  # # Optional, use the operation name to set the new relic transaction name:
14
14
  # # trace_with GraphQL::Tracing::NewRelicTrace, set_transaction_name: true
15
15
  # end
16
+ #
17
+ # @example Installing without trace events for `authorized?` or `resolve_type` calls
18
+ # trace_with GraphQL::Tracing::NewRelicTrace, trace_authorized: false, trace_resolve_type: false
16
19
  module NewRelicTrace
17
20
  # @param set_transaction_name [Boolean] If true, the GraphQL operation name will be used as the transaction name.
18
21
  # This is not advised if you run more than one query per HTTP request, for example, with `graphql-client` or multiplexing.
19
22
  # It can also be specified per-query with `context[:set_new_relic_transaction_name]`.
20
23
  # @param trace_authorized [Boolean] If `false`, skip tracing `authorized?` calls
21
24
  # @param trace_resolve_type [Boolean] If `false`, skip tracing `resolve_type?` calls
22
- 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)
23
27
  @set_transaction_name = set_transaction_name
24
28
  @trace_authorized = trace_authorized
25
29
  @trace_resolve_type = trace_resolve_type
30
+ @trace_scalars = trace_scalars
26
31
  @nr_field_names = Hash.new do |h, field|
27
32
  h[field] = "GraphQL/#{field.owner.graphql_name}/#{field.graphql_name}"
28
33
  end.compare_by_identity
@@ -89,78 +94,90 @@ module GraphQL
89
94
  end
90
95
 
91
96
  def begin_execute_field(field, object, arguments, query)
92
- 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
93
106
  super
94
107
  end
95
108
 
96
109
  def end_execute_field(field, objects, arguments, query, result)
97
- nr_segment_stack.pop.finish
110
+ finish_segment
98
111
  super
99
112
  end
100
113
 
101
114
  def begin_authorized(type, obj, ctx)
102
115
  if @trace_authorized
103
- 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)
104
117
  end
105
118
  super
106
119
  end
107
120
 
108
121
  def end_authorized(type, obj, ctx, is_authed)
109
122
  if @trace_authorized
110
- nr_segment_stack.pop.finish
123
+ finish_segment
111
124
  end
112
125
  super
113
126
  end
114
127
 
115
128
  def begin_resolve_type(type, value, context)
116
129
  if @trace_resolve_type
117
- 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)
118
131
  end
119
132
  super
120
133
  end
121
134
 
122
135
  def end_resolve_type(type, value, context, resolved_type)
123
136
  if @trace_resolve_type
124
- nr_segment_stack.pop.finish
137
+ finish_segment
125
138
  end
126
139
  super
127
140
  end
128
141
 
129
- def begin_dataloader(dl)
130
- super
131
- end
132
-
133
- def end_dataloader(dl)
134
- super
135
- end
136
-
137
142
  def begin_dataloader_source(source)
138
- 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)
139
144
  super
140
145
  end
141
146
 
142
147
  def end_dataloader_source(source)
143
- nr_segment_stack.pop.finish
148
+ finish_segment
144
149
  super
145
150
  end
146
151
 
147
152
  def dataloader_fiber_yield(source)
148
- current_segment = nr_segment_stack.last
149
- current_segment.finish
153
+ prev_segment = finish_segment
154
+ Fiber[:graphql_nr_previous_segment] = prev_segment
150
155
  super
151
156
  end
152
157
 
153
158
  def dataloader_fiber_resume(source)
154
- prev_segment = nr_segment_stack.pop
155
- seg_partial_name = prev_segment.name.sub(/^.*(GraphQL.*)$/, '\1')
156
- nr_segment_stack << NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: seg_partial_name, category: :web)
159
+ prev_segment = Fiber[:graphql_nr_previous_segment]
160
+ Fiber[:graphql_nr_previous_segment] = nil
161
+ if prev_segment
162
+ seg_partial_name = prev_segment.name.sub(/^.*(GraphQL.*)$/, '\1')
163
+ start_segment(partial_name: seg_partial_name, category: :web)
164
+ end
157
165
  super
158
166
  end
159
167
 
160
168
  private
161
169
 
162
- def nr_segment_stack
163
- Fiber[:graphql_nr_segment_stack] ||= []
170
+ def start_segment(...)
171
+ Fiber[:graphql_nr_segment] = NewRelic::Agent::Tracer.start_transaction_or_segment(...)
172
+ end
173
+
174
+ def finish_segment
175
+ segment = Fiber[:graphql_nr_segment]
176
+ if segment
177
+ segment.finish
178
+ Fiber[:graphql_nr_segment] = nil
179
+ segment
180
+ end
164
181
  end
165
182
 
166
183
  def transaction_name(query)
@@ -16,6 +16,8 @@ module GraphQL
16
16
  super
17
17
  end
18
18
 
19
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
20
+
19
21
  {
20
22
  "lex" => "lex.graphql",
21
23
  "parse" => "parse.graphql",
@@ -39,6 +41,8 @@ module GraphQL
39
41
  RUBY
40
42
  end
41
43
 
44
+ # rubocop:enable Development/NoEvalCop
45
+
42
46
  include PlatformTrace
43
47
  end
44
48
  end
@@ -39,6 +39,9 @@ module GraphQL
39
39
  include(BaseKeyCache)
40
40
  }
41
41
  child_class.const_set(:KeyCache, key_methods_class)
42
+
43
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
44
+
42
45
  [:execute_field, :execute_field_lazy].each do |field_trace_method|
43
46
  if !child_class.method_defined?(field_trace_method)
44
47
  child_class.module_eval <<-RUBY, __FILE__, __LINE__
@@ -91,6 +94,8 @@ module GraphQL
91
94
  end
92
95
  RUBY
93
96
  end
97
+
98
+ # rubocop:enable Development/NoEvalCop
94
99
  end
95
100
  end
96
101
 
@@ -40,6 +40,8 @@ module GraphQL
40
40
  super(**rest)
41
41
  end
42
42
 
43
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
44
+
43
45
  {
44
46
  'lex' => "graphql.lex",
45
47
  'parse' => "graphql.parse",
@@ -57,6 +59,8 @@ module GraphQL
57
59
  RUBY
58
60
  end
59
61
 
62
+ # rubocop:enable Development/NoEvalCop
63
+
60
64
  def platform_execute_field(platform_key, &block)
61
65
  instrument_prometheus_execution(platform_key, "execute_field", &block)
62
66
  end
@@ -24,6 +24,8 @@ module GraphQL
24
24
  super
25
25
  end
26
26
 
27
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
28
+
27
29
  {
28
30
  "lex" => "lex.graphql",
29
31
  "parse" => "parse.graphql",
@@ -53,6 +55,7 @@ module GraphQL
53
55
  end
54
56
  RUBY
55
57
  end
58
+ # rubocop:enable Development/NoEvalCop
56
59
 
57
60
  def platform_execute_field(platform_key, &block)
58
61
  self.class.instrument("GraphQL", platform_key, INSTRUMENT_OPTS, &block)
@@ -30,6 +30,8 @@ module GraphQL
30
30
  instrument_sentry_execution("graphql.execute", "execute_query", data) { super }
31
31
  end
32
32
 
33
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
34
+
33
35
  {
34
36
  "lex" => "graphql.lex",
35
37
  "parse" => "graphql.parse",
@@ -46,6 +48,8 @@ module GraphQL
46
48
  RUBY
47
49
  end
48
50
 
51
+ # rubocop:enable Development/NoEvalCop
52
+
49
53
  def platform_execute_field(platform_key, &block)
50
54
  instrument_sentry_execution(platform_key, "execute_field", &block)
51
55
  end
@@ -22,6 +22,8 @@ module GraphQL
22
22
  super(**rest)
23
23
  end
24
24
 
25
+ # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
26
+
25
27
  {
26
28
  'lex' => "graphql.lex",
27
29
  'parse' => "graphql.parse",
@@ -41,6 +43,8 @@ module GraphQL
41
43
  RUBY
42
44
  end
43
45
 
46
+ # rubocop:enable Development/NoEvalCop
47
+
44
48
  def platform_execute_field(platform_key, &block)
45
49
  @statsd.time(platform_key, &block)
46
50
  end
@@ -13,7 +13,7 @@ module GraphQL
13
13
  child_class.node_nullable(true)
14
14
  child_class.edges_nullable(true)
15
15
  child_class.edge_nullable(true)
16
- child_class.module_eval {
16
+ child_class.module_exec {
17
17
  self.edge_type = nil
18
18
  self.node_type = nil
19
19
  self.edge_class = nil
@@ -8,7 +8,7 @@ module GraphQL
8
8
  child_class.description("An edge in a connection.")
9
9
  child_class.field(:cursor, String, null: false, description: "A cursor for use in pagination.")
10
10
  child_class.extend(ClassMethods)
11
- child_class.class_eval { self.node_type = nil }
11
+ child_class.class_exec { self.node_type = nil }
12
12
  child_class.node_nullable(true)
13
13
  child_class.default_broadcastable(nil)
14
14
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.4.11"
3
+ VERSION = "2.4.15"
4
4
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.11
4
+ version: 2.4.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-02-28 00:00:00.000000000 Z
10
+ date: 2025-03-19 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -247,34 +247,6 @@ dependencies:
247
247
  - - ">="
248
248
  - !ruby/object:Gem::Version
249
249
  version: '0'
250
- - !ruby/object:Gem::Dependency
251
- name: pronto
252
- requirement: !ruby/object:Gem::Requirement
253
- requirements:
254
- - - ">="
255
- - !ruby/object:Gem::Version
256
- version: '0'
257
- type: :development
258
- prerelease: false
259
- version_requirements: !ruby/object:Gem::Requirement
260
- requirements:
261
- - - ">="
262
- - !ruby/object:Gem::Version
263
- version: '0'
264
- - !ruby/object:Gem::Dependency
265
- name: pronto-undercover
266
- requirement: !ruby/object:Gem::Requirement
267
- requirements:
268
- - - ">="
269
- - !ruby/object:Gem::Version
270
- version: '0'
271
- type: :development
272
- prerelease: false
273
- version_requirements: !ruby/object:Gem::Requirement
274
- requirements:
275
- - - ">="
276
- - !ruby/object:Gem::Version
277
- version: '0'
278
250
  - !ruby/object:Gem::Dependency
279
251
  name: jekyll
280
252
  requirement: !ruby/object:Gem::Requirement
@@ -808,7 +780,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
808
780
  - !ruby/object:Gem::Version
809
781
  version: '0'
810
782
  requirements: []
811
- rubygems_version: 3.6.3
783
+ rubygems_version: 3.6.6
812
784
  specification_version: 4
813
785
  summary: A GraphQL language and runtime for Ruby
814
786
  test_files: []