graphql-metrics 2.0.1 → 3.0.0

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.
metadata CHANGED
@@ -1,29 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Butcher
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-20 00:00:00.000000000 Z
11
+ date: 2020-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: concurrent-ruby
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: graphql
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.9.15
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.9.15
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: bundler
15
43
  requirement: !ruby/object:Gem::Requirement
16
44
  requirements:
17
45
  - - "~>"
18
46
  - !ruby/object:Gem::Version
19
- version: '1.16'
47
+ version: 2.0.2
20
48
  type: :development
21
49
  prerelease: false
22
50
  version_requirements: !ruby/object:Gem::Requirement
23
51
  requirements:
24
52
  - - "~>"
25
53
  - !ruby/object:Gem::Version
26
- version: '1.16'
54
+ version: 2.0.2
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: rake
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -67,35 +95,35 @@ dependencies:
67
95
  - !ruby/object:Gem::Version
68
96
  version: '0'
69
97
  - !ruby/object:Gem::Dependency
70
- name: graphql
98
+ name: activesupport
71
99
  requirement: !ruby/object:Gem::Requirement
72
100
  requirements:
73
101
  - - "~>"
74
102
  - !ruby/object:Gem::Version
75
- version: 1.8.2
103
+ version: 5.1.5
76
104
  type: :development
77
105
  prerelease: false
78
106
  version_requirements: !ruby/object:Gem::Requirement
79
107
  requirements:
80
108
  - - "~>"
81
109
  - !ruby/object:Gem::Version
82
- version: 1.8.2
110
+ version: 5.1.5
83
111
  - !ruby/object:Gem::Dependency
84
- name: activesupport
112
+ name: pry
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
- - - "~>"
115
+ - - ">="
88
116
  - !ruby/object:Gem::Version
89
- version: 5.1.5
117
+ version: '0'
90
118
  type: :development
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
93
121
  requirements:
94
- - - "~>"
122
+ - - ">="
95
123
  - !ruby/object:Gem::Version
96
- version: 5.1.5
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
- name: pry
126
+ name: pry-byebug
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
129
  - - ">="
@@ -109,7 +137,7 @@ dependencies:
109
137
  - !ruby/object:Gem::Version
110
138
  version: '0'
111
139
  - !ruby/object:Gem::Dependency
112
- name: pry-byebug
140
+ name: mocha
113
141
  requirement: !ruby/object:Gem::Requirement
114
142
  requirements:
115
143
  - - ">="
@@ -123,7 +151,7 @@ dependencies:
123
151
  - !ruby/object:Gem::Version
124
152
  version: '0'
125
153
  - !ruby/object:Gem::Dependency
126
- name: mocha
154
+ name: diffy
127
155
  requirement: !ruby/object:Gem::Requirement
128
156
  requirements:
129
157
  - - ">="
@@ -137,7 +165,7 @@ dependencies:
137
165
  - !ruby/object:Gem::Version
138
166
  version: '0'
139
167
  - !ruby/object:Gem::Dependency
140
- name: diffy
168
+ name: hashdiff
141
169
  requirement: !ruby/object:Gem::Requirement
142
170
  requirements:
143
171
  - - ">="
@@ -187,8 +215,12 @@ executables: []
187
215
  extensions: []
188
216
  extra_rdoc_files: []
189
217
  files:
218
+ - ".github/workflows/ruby.yml"
190
219
  - ".gitignore"
191
- - ".travis.yml"
220
+ - ".rubocop-http---shopify-github-io-ruby-style-guide-rubocop-yml"
221
+ - ".rubocop.yml"
222
+ - ".ruby-version"
223
+ - CHANGELOG.md
192
224
  - CODE_OF_CONDUCT.md
193
225
  - Gemfile
194
226
  - Gemfile.lock
@@ -198,11 +230,11 @@ files:
198
230
  - bin/console
199
231
  - bin/setup
200
232
  - graphql_metrics.gemspec
201
- - lib/graphql_metrics.rb
202
- - lib/graphql_metrics/extractor.rb
203
- - lib/graphql_metrics/instrumentation.rb
204
- - lib/graphql_metrics/timed_batch_executor.rb
205
- - lib/graphql_metrics/version.rb
233
+ - lib/graphql/metrics.rb
234
+ - lib/graphql/metrics/analyzer.rb
235
+ - lib/graphql/metrics/instrumentation.rb
236
+ - lib/graphql/metrics/tracer.rb
237
+ - lib/graphql/metrics/version.rb
206
238
  homepage: https://github.com/Shopify/graphql-metrics
207
239
  licenses:
208
240
  - MIT
@@ -222,8 +254,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
254
  - !ruby/object:Gem::Version
223
255
  version: '0'
224
256
  requirements: []
225
- rubyforge_project:
226
- rubygems_version: 2.5.2.3
257
+ rubygems_version: 3.0.3
227
258
  signing_key:
228
259
  specification_version: 4
229
260
  summary: GraphQL Metrics Extractor
@@ -1,5 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.4.2
5
- before_install: gem install bundler -v 1.16.1
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "graphql_metrics/version"
4
- require "graphql_metrics/instrumentation"
5
- require "graphql_metrics/extractor"
6
- require "graphql_metrics/timed_batch_executor"
@@ -1,277 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GraphQLMetrics
4
- class Extractor
5
- class DummyInstrumentor
6
- def after_query_start_and_end_time
7
- [nil, nil]
8
- end
9
-
10
- def after_query_resolver_times(_ast_node)
11
- []
12
- end
13
-
14
- def ctx_namespace
15
- {}
16
- end
17
- end
18
-
19
- EXPLICIT_NULL = 'EXPLICIT_NULL'
20
- IMPLICIT_NULL = 'IMPLICIT_NULL'
21
- NON_NULL = 'NON_NULL'
22
-
23
- attr_reader :query
24
-
25
- def initialize(instrumentor = DummyInstrumentor.new)
26
- @instrumentor = instrumentor
27
- end
28
-
29
- def instrumentor
30
- @instrumentor ||= DummyInstrumentor.new
31
- end
32
-
33
- def extract!(query)
34
- @query = query
35
-
36
- return unless query.valid?
37
- return unless query.irep_selection
38
-
39
- extract_query
40
-
41
- used_variables = extract_used_variables
42
-
43
- query.operations.each_value do |operation|
44
- extract_variables(operation, used_variables)
45
- end
46
-
47
- extract_node(query.irep_selection)
48
- extract_batch_loaders
49
- end
50
-
51
- def extractor_defines_any_visitors?
52
- [self, instrumentor].any? do |extractor_definer|
53
- extractor_definer.respond_to?(:query_extracted) ||
54
- extractor_definer.respond_to?(:field_extracted) ||
55
- extractor_definer.respond_to?(:argument_extracted) ||
56
- extractor_definer.respond_to?(:variable_extracted) ||
57
- extractor_definer.respond_to?(:batch_loaded_field_extracted) ||
58
- extractor_definer.respond_to?(:before_query_extracted)
59
- end
60
- end
61
-
62
- def handle_extraction_exception(ex)
63
- raise ex
64
- end
65
-
66
- private
67
-
68
- def extract_batch_loaders
69
- return unless batch_loaded_field_extracted_method = extraction_method(:batch_loaded_field_extracted)
70
-
71
- TimedBatchExecutor.timings.each do |key, resolve_meta|
72
- key, identifiers = TimedBatchExecutor.serialize_loader_key(key)
73
-
74
- batch_loaded_field_extracted_method.call(
75
- {
76
- key: key,
77
- identifiers: identifiers,
78
- times: resolve_meta[:times],
79
- perform_queue_sizes: resolve_meta[:perform_queue_sizes],
80
- },
81
- {
82
- query: query,
83
- }
84
- )
85
- end
86
- rescue StandardError => ex
87
- handle_extraction_exception(ex)
88
- ensure
89
- TimedBatchExecutor.clear_timings
90
- end
91
-
92
- def extract_query
93
- return unless query_extracted_method = extraction_method(:query_extracted)
94
-
95
- start_time, end_time = instrumentor.after_query_start_and_end_time
96
- duration = start_time && end_time ? end_time - start_time : nil
97
-
98
- query_extracted_method.call(
99
- {
100
- query_string: query.document.to_query_string,
101
- operation_type: query.selected_operation.operation_type,
102
- operation_name: query.selected_operation_name,
103
- duration: duration
104
- },
105
- {
106
- query: query,
107
- start_time: start_time,
108
- end_time: end_time
109
- }
110
- )
111
- rescue StandardError => ex
112
- handle_extraction_exception(ex)
113
- end
114
-
115
- def extract_field(irep_node)
116
- return unless field_extracted_method = extraction_method(:field_extracted)
117
- return unless irep_node.definition
118
-
119
- resolver_times = instrumentor.after_query_resolver_times(irep_node.ast_node)
120
-
121
- field_extracted_method.call(
122
- {
123
- type_name: irep_node.owner_type.name,
124
- field_name: irep_node.definition.name,
125
- deprecated: irep_node.definition.deprecation_reason.present?,
126
- resolver_times: resolver_times || [],
127
- },
128
- {
129
- irep_node: irep_node,
130
- query: query,
131
- ctx_namespace: instrumentor.ctx_namespace
132
- }
133
- )
134
-
135
- rescue StandardError => ex
136
- handle_extraction_exception(ex)
137
- end
138
-
139
- def extract_argument(value, irep_node, types)
140
- return unless argument_extracted_method = extraction_method(:argument_extracted)
141
-
142
- argument_extracted_method.call(
143
- {
144
- name: value.definition.expose_as,
145
- type: value.definition.type.unwrap.to_s,
146
- value_is_null: value.value.nil?,
147
- default_used: value.default_used?,
148
- parent_input_type: types.map(&:unwrap).last&.to_s,
149
- field_name: irep_node.definition.name,
150
- field_base_type: irep_node&.owner_type.to_s
151
- },
152
- {
153
- query: query,
154
- irep_node: irep_node,
155
- value: value,
156
- }
157
- )
158
- rescue StandardError => ex
159
- handle_extraction_exception(ex)
160
- end
161
-
162
- def extract_variables(operation, used_variables)
163
- return unless variable_extracted_method = extraction_method(:variable_extracted)
164
-
165
- operation.variables.each do |variable|
166
- value_provided = query.provided_variables.key?(variable.name)
167
-
168
- default_value_type = case variable.default_value
169
- when GraphQL::Language::Nodes::NullValue
170
- EXPLICIT_NULL
171
- when nil
172
- IMPLICIT_NULL
173
- else
174
- NON_NULL
175
- end
176
-
177
- default_used = !value_provided && default_value_type != IMPLICIT_NULL
178
-
179
- variable_extracted_method.call(
180
- {
181
- operation_name: operation.name,
182
- unwrapped_type_name: unwrapped_type(variable.type),
183
- type: variable.type.to_query_string,
184
- default_value_type: default_value_type,
185
- provided_value: value_provided,
186
- default_used: default_used,
187
- used_in_operation: used_variables.include?(variable.name)
188
- },
189
- {
190
- query: query
191
- }
192
- )
193
- end
194
- rescue StandardError => ex
195
- handle_extraction_exception(ex)
196
- end
197
-
198
- def extract_used_variables
199
- query.irep_selection.ast_node.variables.each_with_object(Set.new) { |v, set| set << v.name }
200
- end
201
-
202
- def extract_arguments(irep_node)
203
- return unless irep_node.ast_node.is_a?(GraphQL::Language::Nodes::Field)
204
-
205
- traverse_arguments(irep_node.arguments.argument_values.values, irep_node)
206
- rescue GraphQL::ExecutionError
207
- # no-op. See https://github.com/rmosolgo/graphql-ruby/issues/982.
208
- nil
209
- rescue StandardError => ex
210
- handle_extraction_exception(ex)
211
- end
212
-
213
- def extract_node(irep_node)
214
- extract_field(irep_node)
215
- extract_arguments(irep_node)
216
-
217
- irep_node.scoped_children.each_value do |children|
218
- children.each_value do |child_irep_node|
219
- extract_node(child_irep_node)
220
- end
221
- end
222
- rescue StandardError => ex
223
- handle_extraction_exception(ex)
224
- end
225
-
226
- def traverse_arguments(value, irep_node, types = [])
227
- case value
228
- when Array
229
- value.each do |v|
230
- traverse_arguments(v, irep_node, types)
231
- end
232
- when Hash
233
- value.each_value do |v|
234
- traverse_arguments(v, irep_node, types)
235
- end
236
- when ::GraphQL::Query::Arguments
237
- value.each_value do |arg_val|
238
- traverse_arguments(arg_val, irep_node, types)
239
- end
240
- when ::GraphQL::Query::Arguments::ArgumentValue
241
- extract_argument(value, irep_node, types)
242
- traverse_arguments(value.value, irep_node, types + [value.definition.type])
243
- when ::GraphQL::Schema::InputObject
244
- traverse_arguments(value.arguments.argument_values.values, irep_node, types)
245
- end
246
- rescue StandardError => ex
247
- handle_extraction_exception(ex)
248
- end
249
-
250
- def unwrapped_type(type)
251
- if type.is_a?(GraphQL::Language::Nodes::WrapperType)
252
- unwrapped_type(type.of_type)
253
- else
254
- type.name
255
- end
256
- rescue StandardError => ex
257
- handle_extraction_exception(ex)
258
- end
259
-
260
- def extraction_method(method_name)
261
- @extraction_method_cache ||= {}
262
- return @extraction_method_cache[method_name] if @extraction_method_cache.has_key?(method_name)
263
-
264
- method = if respond_to?(method_name)
265
- method(method_name)
266
- elsif instrumentor && instrumentor.respond_to?(method_name)
267
- instrumentor.method(method_name)
268
- else
269
- nil
270
- end
271
-
272
- method.tap do |method|
273
- @extraction_method_cache[method_name] = method
274
- end
275
- end
276
- end
277
- end