graphql-metrics 5.0.8 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f54fe0807d964c7ddf402984339caf1c29ba21953db7090ecbf948051048e5ee
4
- data.tar.gz: 694a4221b1673386f3104cd8bc0c5e5518f95505cdbbf7330cb98ee7e555bf1a
3
+ metadata.gz: a07023fbdc4beff81a392ca7dc3ae2e5c413807be91121b49ad05bb63e9f9a20
4
+ data.tar.gz: c8c533731167efe52c0da74f1d5ee147bd69efb9e3c2eedd0a7a7302d956a187
5
5
  SHA512:
6
- metadata.gz: f35acb43fde5fdb41b00e2f5fa4e99c2d478bf062630320e521134c8190a0820d81bf0aad9edc3882690a08c5b323998fbc41d1c98542d130e726a1982211fd9
7
- data.tar.gz: 7c7d3874d910f1587e65f95c163a12d236e86b5b92b58cbaaa51061e7b0420092357c2f2af87c393fba65174e8ef76ab928a7da5fdc22d984c17740484032087
6
+ metadata.gz: e6f0d75f489119e17d55fc83d8bfe0aa0601ccb54dc5fa5e97fa435746b130ffe5dd1f95114be8c40c44f6350b2357381986c3602e317c7c76b10bc98b233c7e
7
+ data.tar.gz: 35613ab78775485ede19e0ba178f7151e2239b091e4b7832e9fcba06c7c97cba7cecddea05042cad131f426c877e96156a54cc91afee2d4c5e33973673f7bb3a
@@ -0,0 +1,20 @@
1
+ version: 2
2
+ registries:
3
+ ruby-shopify:
4
+ type: rubygems-server
5
+ url: https://pkgs.shopify.io/basic/gems/ruby
6
+ username: ${{secrets.RUBYGEMS_SERVER_PKGS_SHOPIFY_IO_USERNAME}}
7
+ password: ${{secrets.RUBYGEMS_SERVER_PKGS_SHOPIFY_IO_PASSWORD}}
8
+ github-com:
9
+ type: git
10
+ url: https://github.com
11
+ username: ${{secrets.DEPENDENCIES_GITHUB_USER}}
12
+ password: ${{secrets.DEPENDENCIES_GITHUB_TOKEN}}
13
+ updates:
14
+ - package-ecosystem: bundler
15
+ directory: "/"
16
+ schedule:
17
+ interval: weekly
18
+ open-pull-requests-limit: 100
19
+ insecure-external-code-execution: allow
20
+ registries: "*"
@@ -0,0 +1,23 @@
1
+ name: Dependabot auto-merge
2
+ on: pull_request_target
3
+
4
+ permissions:
5
+ pull-requests: write
6
+ contents: write
7
+
8
+ jobs:
9
+ dependabot:
10
+ runs-on: ubuntu-latest
11
+ if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }}
12
+ steps:
13
+ - name: Dependabot metadata
14
+ id: metadata
15
+ uses: dependabot/fetch-metadata@v2
16
+ with:
17
+ github-token: "${{ secrets.GITHUB_TOKEN }}"
18
+ - name: Enable auto-merge for Dependabot PRs
19
+ if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-patch' }}
20
+ run: gh pr merge --auto --merge "$PR_URL"
21
+ env:
22
+ PR_URL: ${{ github.event.pull_request.html_url }}
23
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -1,13 +1,17 @@
1
1
  name: Tests
2
- on: [push, pull_request]
2
+ on:
3
+ push:
4
+ pull_request:
5
+ schedule:
6
+ - cron: '0 8 * * 1'
3
7
  jobs:
4
8
  test:
5
9
  strategy:
6
10
  fail-fast: false
7
11
  matrix:
8
12
  os: [ubuntu-latest]
9
- ruby: ['2.7', '3.0', '3.1', '3.2']
10
- gemfile: ['graphql_1.13', 'graphql_2.0', 'graphql_head']
13
+ ruby: ['2.7', '3.0', '3.1', '3.2', '3.3']
14
+ gemfile: ['graphql_2.3', 'graphql_head']
11
15
  runs-on: ${{ matrix.os }}
12
16
  env:
13
17
  BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
data/.gitignore CHANGED
@@ -7,5 +7,4 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
  *.gem
10
- Gemfile.lock
11
10
  /vendor/
data/.rubocop.yml CHANGED
@@ -1,5 +1,2 @@
1
1
  inherit_from:
2
2
  - http://shopify.github.io/ruby-style-guide/rubocop.yml
3
-
4
- AllCops:
5
- TargetRubyVersion: 2.6
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.0
1
+ 3.3.1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,42 @@
1
+ 6.0.0
2
+ -----
3
+
4
+ **Usage change**
5
+ Due to Instrumentation plugins being deprecated in the `graphql` gem, `graphql-metrics` has been refactored to use the [new `Tracing` API](https://graphql-ruby.org/queries/tracing.html).
6
+ This changes how `graphql-metrics` is used in your application.
7
+
8
+ Before:
9
+ ```ruby
10
+ class MySchema < GraphQL::Schema
11
+ instrument :query, GraphQLMetrics::Instrumentation.new
12
+ query_analyzer MyMetricsAnalyzer
13
+ tracer GraphQL::Metrics::Tracer.new
14
+ end
15
+ ```
16
+
17
+ After:
18
+ ```ruby
19
+ class MySchema < GraphQL::Schema
20
+ use GraphQL::Metrics, analyzer: MyMetricsAnalyzer
21
+ end
22
+ ```
23
+
24
+ Other breaking changes:
25
+ * `graphql` >= 2.3 is now required.
26
+ * Apollo tracing spec support has been removed (the spec has been deprecated for years). All `start_time_offset` metrics have been removed.
27
+ * Support for the old tracing API has been removed.
28
+ * The `multiplex_start_time_monotonic` operation mettric has been removed.
29
+
30
+
31
+ Changes:
32
+ - [87](https://github.com/Shopify/graphql-metrics/pull/87) Migrate Instrumentation to tracing
33
+ - [88](https://github.com/Shopify/graphql-metrics/pull/88) Update `analyzer` option
34
+ - [86](https://github.com/Shopify/graphql-metrics/pull/86) Refactor static metric mode
35
+ - [85](https://github.com/Shopify/graphql-metrics/pull/85) Remove old tracing API support
36
+ - [84](https://github.com/Shopify/graphql-metrics/pull/84) Remove Apollo tracing spec support
37
+ - [80](https://github.com/Shopify/graphql-metrics/pull/80) Support new parser
38
+ - [79](https://github.com/Shopify/graphql-metrics/pull/79) Centralize Ruby Version to `.ruby-version`
39
+
1
40
  5.0.8
2
41
  -----
3
42
  - [76](https://github.com/Shopify/graphql-metrics/pull/76) Reduce object allocations
data/Gemfile.lock ADDED
@@ -0,0 +1,70 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ graphql-metrics (6.0.0)
5
+ graphql (>= 2.3)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (6.1.7.5)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 1.6, < 2)
13
+ minitest (>= 5.1)
14
+ tzinfo (~> 2.0)
15
+ zeitwerk (~> 2.3)
16
+ base64 (0.2.0)
17
+ byebug (11.1.3)
18
+ coderay (1.1.3)
19
+ concurrent-ruby (1.2.3)
20
+ diffy (3.4.2)
21
+ fakeredis (0.9.2)
22
+ redis (~> 4.8)
23
+ graphql (2.3.0)
24
+ base64
25
+ graphql-batch (0.6.0)
26
+ graphql (>= 1.12.18, < 3)
27
+ promise.rb (~> 0.7.2)
28
+ hashdiff (1.1.0)
29
+ i18n (1.14.4)
30
+ concurrent-ruby (~> 1.0)
31
+ method_source (1.0.0)
32
+ minitest (5.22.3)
33
+ minitest-focus (1.4.0)
34
+ minitest (>= 4, < 6)
35
+ mocha (2.1.0)
36
+ ruby2_keywords (>= 0.0.5)
37
+ promise.rb (0.7.4)
38
+ pry (0.14.2)
39
+ coderay (~> 1.1)
40
+ method_source (~> 1.0)
41
+ pry-byebug (3.10.1)
42
+ byebug (~> 11.0)
43
+ pry (>= 0.13, < 0.15)
44
+ rake (13.1.0)
45
+ redis (4.8.1)
46
+ ruby2_keywords (0.0.5)
47
+ tzinfo (2.0.6)
48
+ concurrent-ruby (~> 1.0)
49
+ zeitwerk (2.6.13)
50
+
51
+ PLATFORMS
52
+ arm64-darwin-23
53
+ x86_64-linux
54
+
55
+ DEPENDENCIES
56
+ activesupport (~> 6.1.7)
57
+ diffy
58
+ fakeredis
59
+ graphql-batch
60
+ graphql-metrics!
61
+ hashdiff
62
+ minitest (~> 5.0)
63
+ minitest-focus
64
+ mocha
65
+ pry
66
+ pry-byebug
67
+ rake
68
+
69
+ BUNDLED WITH
70
+ 2.4.1
data/README.md CHANGED
@@ -7,9 +7,6 @@ Compatible with the [`graphql-batch` gem](https://github.com/Shopify/graphql-bat
7
7
 
8
8
  Be sure to read the [CHANGELOG](CHANGELOG.md) to stay updated on feature additions, breaking changes made to this gem.
9
9
 
10
- **NOTE**: Not tested with graphql-ruby's multiplexing feature. Metrics may not
11
- be accurate if you execute multiple operations at once.
12
-
13
10
  ## Installation
14
11
 
15
12
  Add this line to your application's Gemfile:
@@ -42,15 +39,15 @@ Get started by defining your own Analyzer, inheriting from `GraphQL::Metrics::An
42
39
 
43
40
  The following analyzer demonstrates a simple way to capture commonly used metrics sourced from key parts of your schema
44
41
  definition, the query document being served, as well as runtime query and resolver timings. In this toy example, all of
45
- this data is simply stored on the GraphQL::Query context, under a namespace to avoid collisions with other analyzers
42
+ this data is simply stored on the `GraphQL::Query` context, under a namespace to avoid collisions with other analyzers
46
43
  etc.
47
44
 
48
45
  What you do with these captured metrics is up to you!
49
46
 
50
47
  **NOTE**: If any non-`graphql-ruby` gem-related exceptions occur in your application during query document
51
- parsing and validation, **runtime metrics** for queries (like `query_duration`, `parsing_start_time_offset` etc.) as well as field
48
+ parsing and validation, **runtime metrics** for queries (like `query_duration`, etc.) as well as field
52
49
  resolver timings (like `resolver_timings`, `lazy_resolver_timings`) **may not be present** in the extracted `metrics` hash,
53
- even if you opt to collect them by using `GraphQL::Metrics::Analyzer` and `GraphQL::Metrics::Tracer`.
50
+ even if you opt to collect them.
54
51
 
55
52
  ### Define your own analyzer subclass
56
53
 
@@ -75,15 +72,10 @@ even if you opt to collect them by using `GraphQL::Metrics::Analyzer` and `Graph
75
72
  # operation_name: "PostDetails",
76
73
  # query_start_time: 1573833076.027327,
77
74
  # query_duration: 2.0207119999686256,
78
- # lexing_start_time_offset: 0.0010339999571442604,
79
75
  # lexing_duration: 0.0008190000080503523,
80
- # parsing_start_time_offset: 0.0010339999571442604,
81
76
  # parsing_duration: 0.0008190000080503523,
82
- # validation_start_time_offset: 0.0030819999519735575,
83
77
  # validation_duration: 0.01704599999357015,
84
- # analysis_start_time_offset: 0.0010339999571442604,
85
78
  # analysis_duration: 0.0008190000080503523,
86
- # multiplex_start_time: 0.0008190000080503523,
87
79
  # }
88
80
  #
89
81
  # You can use these metrics to track high-level query performance, along with any other details you wish to
@@ -129,12 +121,10 @@ even if you opt to collect them by using `GraphQL::Metrics::Analyzer` and `Graph
129
121
  # deprecated: false,
130
122
  # path: ["post", "id"],
131
123
  # resolver_timings: [
132
- # start_time_offset: 0.011901999998372048,
133
- # duration: 5.999987479299307e-06
124
+ # 5.999987479299307e-06,
134
125
  # ],
135
126
  # lazy_resolver_timings: [
136
- # start_time_offset: 0.031901999998372048,
137
- # duration: 5.999987479299307e-06
127
+ # 5.999987479299307e-06,
138
128
  # ],
139
129
  # }
140
130
  def field_extracted(metrics)
@@ -178,12 +168,12 @@ even if you opt to collect them by using `GraphQL::Metrics::Analyzer` and `Graph
178
168
  end
179
169
  ```
180
170
 
181
- Once defined, you can opt into capturing all metrics seen above by simply including GraphQL::Metrics as a plugin on your
171
+ Once defined, you can opt into capturing all metrics seen above by simply including `GraphQL::Metrics` as a plugin on your
182
172
  schema.
183
- #### Metrics that are captured for arguments for fields and directives
184
173
 
185
- Let's have a query example
174
+ #### Metrics that are captured for arguments for fields and directives
186
175
 
176
+ Example query:
187
177
  ```graphql
188
178
  query PostDetails($postId: ID!, $commentsTags: [String!] = null, $val: Int!) @customDirective(val: $val) {
189
179
  post(id: $postId) {
@@ -242,46 +232,48 @@ These are some of the arguments that are extracted
242
232
 
243
233
  ### Make use of your analyzer
244
234
 
245
- Ensure that your schema is using the graphql-ruby 1.9+ `GraphQL::Execution::Interpreter` and `GraphQL::Analysis::AST`
246
- engine, and then simply add the below `GraphQL::Metrics` plugins.
247
-
248
- This opts you in to capturing all static and runtime metrics seen above.
235
+ Add the `GraphQL::Metrics` plugin to your schema. This opts you in to capturing all static and runtime metrics seen above.
249
236
 
250
237
  ```ruby
251
238
  class Schema < GraphQL::Schema
252
239
  query QueryRoot
253
240
  mutation MutationRoot
254
241
 
255
- query_analyzer SimpleAnalyzer
256
-
257
- instrument :query, GraphQL::Metrics::Instrumentation.new # Both of these are required if either is used.
258
- tracer GraphQL::Metrics::Tracer.new # <-- Note!
259
-
260
- use GraphQL::Batch # Optional, but highly recommended. See https://github.com/Shopify/graphql-batch/.
242
+ use GraphQL::Metrics, analyzer: SimpleAnalyzer
261
243
  end
262
244
  ```
263
245
 
264
246
  ### Optionally, only gather static metrics
265
247
 
266
- If you don't care to capture runtime metrics like query and resolver timings, you can use your analyzer a standalone
267
- analyzer without `GraphQL::Metrics::Instrumentation` and `tracer GraphQL::Metrics::Tracer`, like so:
248
+ If you don't care to capture field timings metrics, they can be disabled with the `capture_field_timings` option:
268
249
 
269
250
  ```ruby
270
251
  class Schema < GraphQL::Schema
271
252
  query QueryRoot
272
253
  mutation MutationRoot
273
254
 
274
- query_analyzer SimpleAnalyzer
255
+ use GraphQL::Metrics, analyzer: SimpleAnalyzer, capture_field_timings: false
275
256
  end
276
257
  ```
277
258
 
278
259
  Your analyzer will still be called with `query_extracted`, `field_extracted`, but with timings metrics omitted.
279
- `argument_extracted` will work exactly the same, whether instrumentation and tracing are used or not.
260
+ `argument_extracted` will work exactly the same.
261
+
262
+ And if you want to disable tracing metrics entirely, use the `capture_timings` option:
263
+
264
+ ```ruby
265
+ class Schema < GraphQL::Schema
266
+ query QueryRoot
267
+ mutation MutationRoot
268
+
269
+ use GraphQL::Metrics, analyzer: SimpleAnalyzer, capture_timings: false
270
+ end
271
+ ```
280
272
 
281
273
  ## Order of execution
282
274
 
283
275
  Because of the structure of graphql-ruby's plugin architecture, it may be difficult to build an intuition around the
284
- order in which methods defined on `GraphQL::Metrics::Instrumentation`, `GraphQL::Metrics::Tracer` and subclasses of
276
+ order in which methods defined on `GraphQL::Metrics::Instrumentation`, `GraphQL::Metrics::Trace` and subclasses of
285
277
  `GraphQL::Metrics::Analyzer` run.
286
278
 
287
279
  Although you ideally will not need to care about these details if you are simply using this gem to gather metrics in
@@ -289,30 +281,21 @@ your application as intended, here's a breakdown of the order of execution of th
289
281
 
290
282
  When used as instrumentation, an analyzer and tracing, the order of execution is usually:
291
283
 
292
- * Tracer.capture_multiplex_start_time
293
- * Tracer.capture_lexing_time
294
- * Tracer.capture_parsing_time
295
- * Instrumentation.before_query (context setup)
296
- * Tracer.capture_validation_time
297
- * Tracer.capture_analysis_time
284
+ * Instrumentation.execute_multiplex (context setup)
285
+ * Trace.capture_lexing_time
286
+ * Trace.capture_parsing_time
287
+ * Trace.capture_validation_time
288
+ * Trace.capture_analysis_time
298
289
  * Analyzer#initialize (bit more context setup, instance vars setup)
299
290
  * Analyzer#result
300
- * Tracer.capture_query_start_time
301
- * Tracer.trace_field (n times)
302
- * Instrumentation.after_query (call query and field callbacks, now that we have all static and runtime metrics
303
- gathered)
291
+ * Trace.capture_query_start_time
292
+ * Trace.trace_field (n times)
293
+ * Instrumentation.execute_multiplex (call query and field callbacks, now that we have all static and runtime metrics gathered)
304
294
  * Analyzer#extract_query
305
295
  * Analyzer#query_extracted
306
296
  * Analyzer#extract_fields_with_runtime_metrics
307
297
  * calls Analyzer#field_extracted n times
308
298
 
309
- When used as a simple analyzer, which doesn't gather or emit any runtime metrics (timings, arg values):
310
- * Analyzer#initialize
311
- * Analyzer#field_extracted n times
312
- * Analyzer#result
313
- * Analyzer#extract_query
314
- * Analyzer#query_extracted
315
-
316
299
  ## Development
317
300
 
318
301
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -2,4 +2,4 @@
2
2
 
3
3
  eval_gemfile("../Gemfile")
4
4
 
5
- gem("graphql", "~> 1.13")
5
+ gem("graphql", "~> 2.3")
@@ -14,6 +14,8 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = 'https://github.com/Shopify/graphql-metrics'
15
15
  spec.license = "MIT"
16
16
 
17
+ spec.required_ruby_version = ">= 2.7"
18
+
17
19
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
20
 
19
21
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -23,12 +25,11 @@ Gem::Specification.new do |spec|
23
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
26
  spec.require_paths = ["lib"]
25
27
 
26
- spec.add_runtime_dependency "graphql", ">= 1.12.10"
27
- spec.add_runtime_dependency "concurrent-ruby", ">= 1.1.0"
28
- spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_runtime_dependency "graphql", ">= 2.3"
29
+ spec.add_development_dependency "rake", "~> 13.2"
29
30
  spec.add_development_dependency "minitest", "~> 5.0"
30
31
  spec.add_development_dependency 'graphql-batch'
31
- spec.add_development_dependency "activesupport", "~> 5.1.5"
32
+ spec.add_development_dependency "activesupport", "~> 6.1.7"
32
33
  spec.add_development_dependency "pry"
33
34
  spec.add_development_dependency "pry-byebug"
34
35
  spec.add_development_dependency "mocha"
@@ -51,20 +51,13 @@ module GraphQL
51
51
  path: visitor.response_path,
52
52
  }
53
53
 
54
- if GraphQL::Metrics.timings_capture_enabled?(query.context)
55
- @static_field_metrics << static_metrics
56
- else
57
- field_extracted(static_metrics)
58
- end
54
+ @static_field_metrics << static_metrics
59
55
  end
60
56
 
61
57
  def extract_fields(with_runtime_metrics: true)
62
- return if query.context[SKIP_FIELD_AND_ARGUMENT_METRICS]
63
-
64
58
  ns = query.context.namespace(CONTEXT_NAMESPACE)
65
59
 
66
60
  @static_field_metrics.each do |static_metrics|
67
-
68
61
  if with_runtime_metrics
69
62
  resolver_timings = ns[GraphQL::Metrics::INLINE_FIELD_TIMINGS][static_metrics[:path]]
70
63
  lazy_resolver_timings = ns[GraphQL::Metrics::LAZY_FIELD_TIMINGS][static_metrics[:path]]
@@ -89,14 +82,6 @@ module GraphQL
89
82
  end
90
83
 
91
84
  def result
92
- return if GraphQL::Metrics.timings_capture_enabled?(query.context)
93
- return if query.context[GraphQL::Metrics::SKIP_GRAPHQL_METRICS_ANALYSIS]
94
-
95
- # NOTE: If we're running as a static analyzer (i.e. not with instrumentation and tracing), we still need to
96
- # flush static query metrics somewhere other than `after_query`.
97
- ns = query.context.namespace(CONTEXT_NAMESPACE)
98
- analyzer = ns[GraphQL::Metrics::ANALYZER_INSTANCE_KEY]
99
- analyzer.extract_query
100
85
  end
101
86
 
102
87
  private
@@ -2,28 +2,39 @@
2
2
 
3
3
  module GraphQL
4
4
  module Metrics
5
- class Instrumentation
6
- def before_query(query)
7
- unless query_present_and_valid?(query)
8
- # Setting this prevents Analyzer and Tracer from trying to gather runtime metrics for invalid queries.
9
- query.context[GraphQL::Metrics::SKIP_GRAPHQL_METRICS_ANALYSIS] = true
5
+ module Instrumentation
6
+ def initialize(capture_field_timings: true, **_options)
7
+ @capture_field_timings = capture_field_timings
8
+
9
+ super
10
+ end
11
+
12
+ def execute_multiplex(multiplex:)
13
+ return super if multiplex.context[GraphQL::Metrics::SKIP_GRAPHQL_METRICS_ANALYSIS]
14
+
15
+ result = nil
16
+
17
+ multiplex.queries.each do |query|
18
+ ns = query.context.namespace(CONTEXT_NAMESPACE)
19
+ ns[GraphQL::Metrics::TIMINGS_CAPTURE_ENABLED] = @capture_field_timings
20
+ ns[GraphQL::Metrics::INLINE_FIELD_TIMINGS] = Hash.new { |h, k| h[k] = [] }
21
+ ns[GraphQL::Metrics::LAZY_FIELD_TIMINGS] = Hash.new { |h, k| h[k] = [] }
10
22
  end
11
23
 
12
- # Even if queries are present and valid, applications may set this context value in order to opt out of
13
- # having Analyzer and Tracer gather runtime metrics.
14
- # If we're skipping runtime metrics, then both Instrumentation before_ and after_query can and should be
15
- # short-circuited as well.
16
- return if query.context[GraphQL::Metrics::SKIP_GRAPHQL_METRICS_ANALYSIS]
24
+ begin
25
+ result = super
26
+ ensure
27
+ multiplex.queries.each do |query|
28
+ handle_query(query) if query.valid?
29
+ end
30
+ end
17
31
 
18
- ns = query.context.namespace(CONTEXT_NAMESPACE)
19
- ns[GraphQL::Metrics::TIMINGS_CAPTURE_ENABLED] = true
20
- ns[GraphQL::Metrics::INLINE_FIELD_TIMINGS] = {}
21
- ns[GraphQL::Metrics::LAZY_FIELD_TIMINGS] = {}
32
+ result
22
33
  end
23
34
 
24
- def after_query(query)
25
- return if query.context[GraphQL::Metrics::SKIP_GRAPHQL_METRICS_ANALYSIS]
35
+ private
26
36
 
37
+ def handle_query(query)
27
38
  ns = query.context.namespace(CONTEXT_NAMESPACE)
28
39
  analyzer = ns[GraphQL::Metrics::ANALYZER_INSTANCE_KEY]
29
40
 
@@ -41,30 +52,19 @@ module GraphQL
41
52
  runtime_query_metrics = {
42
53
  query_start_time: ns[GraphQL::Metrics::QUERY_START_TIME],
43
54
  query_duration: query_duration,
44
- parsing_start_time_offset: ns[GraphQL::Metrics::PARSING_START_TIME_OFFSET],
45
55
  parsing_duration: ns[GraphQL::Metrics::PARSING_DURATION],
46
- validation_start_time_offset: ns[GraphQL::Metrics::VALIDATION_START_TIME_OFFSET],
47
56
  validation_duration: ns[GraphQL::Metrics::VALIDATION_DURATION],
48
- lexing_start_time_offset: ns[GraphQL::Metrics::LEXING_START_TIME_OFFSET],
49
57
  lexing_duration: ns[GraphQL::Metrics::LEXING_DURATION],
50
- analysis_start_time_offset: ns[GraphQL::Metrics::ANALYSIS_START_TIME_OFFSET],
51
58
  analysis_duration: ns[GraphQL::Metrics::ANALYSIS_DURATION],
52
- multiplex_start_time: ns[GraphQL::Metrics::MULTIPLEX_START_TIME],
53
59
  }
54
60
 
55
- analyzer.extract_fields
61
+ analyzer.extract_fields(with_runtime_metrics: @capture_field_timings)
56
62
  analyzer.extract_query(runtime_query_metrics: runtime_query_metrics)
57
63
  end
58
64
  end
59
65
 
60
66
  private
61
67
 
62
- def query_present_and_valid?(query)
63
- # Check for selected_operation as well for graphql 1.9 compatibility
64
- # which did not reject "empty" documents in its parser.
65
- query.valid? && !query.selected_operation.nil?
66
- end
67
-
68
68
  def runtime_metrics_interrupted?(context_namespace)
69
69
  # NOTE: The start time stored at `ns[GraphQL::Metrics::QUERY_START_TIME_MONOTONIC]` is captured during query
70
70
  # parsing, which occurs before `Instrumentation#before_query`.
@@ -8,6 +8,8 @@ module GraphQL
8
8
 
9
9
  query_or_multiplex = @query || @multiplex
10
10
  @skip_tracing = query_or_multiplex.context&.fetch(SKIP_GRAPHQL_METRICS_ANALYSIS, false) if query_or_multiplex
11
+ @parsing_duration = 0.0
12
+ @lexing_duration = 0.0
11
13
  end
12
14
 
13
15
  # NOTE: These methods come from the graphql ruby gem and are in "chronological" order based on the phases
@@ -15,12 +17,6 @@ module GraphQL
15
17
  # https://github.com/rmosolgo/graphql-ruby/issues/3393). Most of them can be run multiple times when
16
18
  # multiplexing multiple queries.
17
19
 
18
- # wraps everything below this line; only run once
19
- def execute_multiplex(multiplex:)
20
- return super if skip_tracing?(multiplex)
21
- capture_multiplex_start_time { super }
22
- end
23
-
24
20
  # may not trigger if the query is passed in pre-parsed
25
21
  def lex(query_string:)
26
22
  return super if @skip_tracing
@@ -34,139 +30,74 @@ module GraphQL
34
30
  end
35
31
 
36
32
  def validate(query:, validate:)
37
- return super if skip_tracing?(query)
33
+ return super if @skip_tracing
38
34
  capture_validation_time(query.context) { super }
39
35
  end
40
36
 
41
- # wraps all `analyze_query`s; only run once
42
- def analyze_multiplex(multiplex:)
43
- return super if skip_tracing?(multiplex)
44
- # Ensures that we reset potentially long-lived PreContext objects between multiplexs. We reset at this point
45
- # since all parsing and validation will be done by this point, and a GraphQL::Query::Context will exist.
46
- pre_context.reset
47
- super
48
- end
49
-
50
37
  def analyze_query(query:)
51
- return super if skip_tracing?(query)
38
+ return super if @skip_tracing
52
39
  capture_analysis_time(query.context) { super }
53
40
  end
54
41
 
55
42
  def execute_query(query:)
56
- return super if skip_tracing?(query)
43
+ return super if @skip_tracing
57
44
  capture_query_start_time(query.context) { super }
58
45
  end
59
46
 
60
47
  def execute_field(field:, query:, ast_node:, arguments:, object:)
61
- return super if skip_tracing?(query) || query.context[SKIP_FIELD_AND_ARGUMENT_METRICS]
62
- return super unless GraphQL::Metrics.timings_capture_enabled?(query.context)
48
+ return super if @skip_tracing || query.context[SKIP_FIELD_AND_ARGUMENT_METRICS]
49
+ return super unless capture_field_timings?(query.context)
63
50
  trace_field(GraphQL::Metrics::INLINE_FIELD_TIMINGS, query) { super }
64
51
  end
65
52
 
66
53
  def execute_field_lazy(field:, query:, ast_node:, arguments:, object:)
67
- return super if skip_tracing?(query) || query.context[SKIP_FIELD_AND_ARGUMENT_METRICS]
68
- return super unless GraphQL::Metrics.timings_capture_enabled?(query.context)
54
+ return super if @skip_tracing || query.context[SKIP_FIELD_AND_ARGUMENT_METRICS]
55
+ return super unless capture_field_timings?(query.context)
69
56
  trace_field(GraphQL::Metrics::LAZY_FIELD_TIMINGS, query) { super }
70
57
  end
71
58
 
72
59
  private
73
60
 
74
- def skip_tracing?(query_or_multiplex)
75
- if !defined?(@skip_tracing)
76
- @skip_tracing = query_or_multiplex.context&.fetch(SKIP_GRAPHQL_METRICS_ANALYSIS, false)
61
+ def capture_field_timings?(context)
62
+ if !defined?(@capture_field_timings)
63
+ @capture_field_timings = !!context.namespace(CONTEXT_NAMESPACE)[TIMINGS_CAPTURE_ENABLED]
77
64
  end
78
65
 
79
- @skip_tracing
80
- end
81
-
82
- PreContext = Struct.new(
83
- :multiplex_start_time,
84
- :multiplex_start_time_monotonic,
85
- :parsing_start_time_offset,
86
- :parsing_duration,
87
- :lexing_start_time_offset,
88
- :lexing_duration
89
- ) do
90
- def reset
91
- self[:multiplex_start_time] = nil
92
- self[:multiplex_start_time_monotonic] = nil
93
- self[:parsing_start_time_offset] = nil
94
- self[:parsing_duration] = nil
95
- self[:lexing_start_time_offset] = nil
96
- self[:lexing_duration] = nil
97
- end
98
- end
99
-
100
- def pre_context
101
- # NOTE: This is used to store timings from lexing, parsing, validation, before we have a context to store
102
- # values in. Uses thread-safe Concurrent::ThreadLocalVar to store a set of values per thread.
103
- @pre_context ||= Concurrent::ThreadLocalVar.new(PreContext.new)
104
- @pre_context.value
105
- end
106
-
107
- def capture_multiplex_start_time
108
- pre_context.multiplex_start_time = GraphQL::Metrics.current_time
109
- pre_context.multiplex_start_time_monotonic = GraphQL::Metrics.current_time_monotonic
110
-
111
- yield
66
+ @capture_field_timings
112
67
  end
113
68
 
114
69
  def capture_lexing_time
115
- timed_result = GraphQL::Metrics.time { yield }
116
-
117
- pre_context.lexing_start_time_offset = timed_result.start_time
118
- pre_context.lexing_duration = timed_result.duration
119
-
120
- timed_result.result
70
+ result, duration = GraphQL::Metrics.time { yield }
71
+ @lexing_duration = duration
72
+ result
121
73
  end
122
74
 
123
75
  def capture_parsing_time
124
- timed_result = GraphQL::Metrics.time { yield }
125
-
126
- pre_context.parsing_start_time_offset = timed_result.start_time
127
- pre_context.parsing_duration = timed_result.duration
128
-
129
- timed_result.result
76
+ result, duration = GraphQL::Metrics.time { yield }
77
+ @parsing_duration = duration
78
+ result
130
79
  end
131
80
 
132
- # Also consolidates parsing timings (if any) from the `pre_context`
81
+ # Also consolidates parsing timings (if any)
133
82
  def capture_validation_time(context)
134
- # Queries may already be lexed and parsed before execution (whether a single query or multiplex).
135
- # If we don't have those values, use some sane defaults.
136
- if pre_context.lexing_duration.nil?
137
- pre_context.lexing_start_time_offset = pre_context.multiplex_start_time
138
- pre_context.lexing_duration = 0.0
139
- end
140
- if pre_context.parsing_duration.nil?
141
- pre_context.parsing_start_time_offset = pre_context.multiplex_start_time
142
- pre_context.parsing_duration = 0.0
143
- end
144
-
145
- timed_result = GraphQL::Metrics.time(pre_context.multiplex_start_time_monotonic) { yield }
83
+ result, duration = GraphQL::Metrics.time { yield }
146
84
 
147
85
  ns = context.namespace(CONTEXT_NAMESPACE)
86
+ ns[LEXING_DURATION] = @lexing_duration
87
+ ns[PARSING_DURATION] = @parsing_duration
88
+ ns[VALIDATION_DURATION] = duration
148
89
 
149
- ns[MULTIPLEX_START_TIME] = pre_context.multiplex_start_time
150
- ns[MULTIPLEX_START_TIME_MONOTONIC] = pre_context.multiplex_start_time_monotonic
151
- ns[LEXING_START_TIME_OFFSET] = pre_context.lexing_start_time_offset
152
- ns[LEXING_DURATION] = pre_context.lexing_duration
153
- ns[PARSING_START_TIME_OFFSET] = pre_context.parsing_start_time_offset
154
- ns[PARSING_DURATION] = pre_context.parsing_duration
155
- ns[VALIDATION_START_TIME_OFFSET] = timed_result.time_since_offset
156
- ns[VALIDATION_DURATION] = timed_result.duration
157
-
158
- timed_result.result
90
+ result
159
91
  end
160
92
 
161
93
  def capture_analysis_time(context)
162
94
  ns = context.namespace(CONTEXT_NAMESPACE)
163
95
 
164
- timed_result = GraphQL::Metrics.time(ns[MULTIPLEX_START_TIME_MONOTONIC]) { yield }
96
+ result, duration = GraphQL::Metrics.time { yield }
165
97
 
166
- ns[ANALYSIS_START_TIME_OFFSET] = timed_result.time_since_offset
167
- ns[ANALYSIS_DURATION] = timed_result.duration
98
+ ns[ANALYSIS_DURATION] = duration
168
99
 
169
- timed_result.result
100
+ result
170
101
  end
171
102
 
172
103
  def capture_query_start_time(context)
@@ -179,20 +110,13 @@ module GraphQL
179
110
 
180
111
  def trace_field(context_key, query)
181
112
  ns = query.context.namespace(CONTEXT_NAMESPACE)
182
- offset_time = ns[GraphQL::Metrics::QUERY_START_TIME_MONOTONIC]
183
- start_time = GraphQL::Metrics.current_time_monotonic
184
113
  path = query.context[:current_path]
185
114
 
186
- result = yield
187
-
188
- duration = GraphQL::Metrics.current_time_monotonic - start_time
189
- time_since_offset = start_time - offset_time if offset_time
115
+ result, duration = GraphQL::Metrics.time { yield }
190
116
 
191
117
  path_excluding_numeric_indicies = path.select { |p| p.is_a?(String) }
192
118
  ns[context_key][path_excluding_numeric_indicies] ||= []
193
- ns[context_key][path_excluding_numeric_indicies] << {
194
- start_time_offset: time_since_offset, duration: duration
195
- }
119
+ ns[context_key][path_excluding_numeric_indicies] << duration
196
120
 
197
121
  result
198
122
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module Metrics
5
- VERSION = "5.0.8"
5
+ VERSION = "6.0.0"
6
6
  end
7
7
  end
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "concurrent"
4
3
  require "graphql/metrics/version"
5
4
  require "graphql/metrics/instrumentation"
6
5
  require "graphql/metrics/trace"
7
- require "graphql/metrics/tracer"
8
6
  require "graphql/metrics/analyzer"
9
7
 
10
8
  module GraphQL
@@ -27,22 +25,13 @@ module GraphQL
27
25
  MULTIPLEX_START_TIME_MONOTONIC = :multiplex_start_time_monotonic
28
26
  QUERY_START_TIME = :query_start_time
29
27
  QUERY_START_TIME_MONOTONIC = :query_start_time_monotonic
30
- LEXING_START_TIME_OFFSET = :lexing_start_time_offset
31
28
  LEXING_DURATION = :lexing_duration
32
- PARSING_START_TIME_OFFSET = :parsing_start_time_offset
33
29
  PARSING_DURATION = :parsing_duration
34
- VALIDATION_START_TIME_OFFSET = :validation_start_time_offset
35
30
  VALIDATION_DURATION = :validation_duration
36
- ANALYSIS_START_TIME_OFFSET = :analysis_start_time_offset
37
31
  ANALYSIS_DURATION = :analysis_duration
38
32
  INLINE_FIELD_TIMINGS = :inline_field_timings
39
33
  LAZY_FIELD_TIMINGS = :lazy_field_timings
40
34
 
41
- def self.timings_capture_enabled?(context)
42
- return false unless context
43
- !!context.namespace(CONTEXT_NAMESPACE)[TIMINGS_CAPTURE_ENABLED]
44
- end
45
-
46
35
  def self.current_time
47
36
  Process.clock_gettime(Process::CLOCK_REALTIME)
48
37
  end
@@ -51,40 +40,32 @@ module GraphQL
51
40
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
52
41
  end
53
42
 
54
- def self.time(offset_time = nil)
43
+ def self.time
55
44
  start_time = current_time_monotonic
56
45
  result = yield
57
46
  duration = current_time_monotonic - start_time
58
- time_since_offset = start_time - offset_time if offset_time
59
- TimedResult.new(start_time, duration, time_since_offset, result)
47
+ [result, duration]
60
48
  end
61
49
 
62
- class TimedResult
63
- # NOTE: `time_since_offset` is used to produce start times timed phases of execution (validation, field
64
- # resolution). These start times are relative to the executed operation's start time, which is captured at the
65
- # outset of document parsing.
66
- #
67
- # The times produced are intentionally similar to:
68
- # https://github.com/apollographql/apollo-tracing#response-format
69
- #
70
- # Taking a field resolver start offset example:
71
- #
72
- # < start offset >
73
- # |------------------|----------|--------->
74
- # OS (t=0) FS (t=1) FE (t=2)
75
- #
76
- # OS = Operation start time
77
- # FS = Field resolver start time
78
- # FE = Field resolver end time
79
- #
80
- attr_reader :result, :start_time, :duration, :time_since_offset
81
-
82
- def initialize(start_time, duration, time_since_offset, result)
83
- @start_time = start_time
84
- @duration = duration
85
- @time_since_offset = time_since_offset
86
- @result = result
50
+ def self.use(
51
+ schema_defn,
52
+ analyzer:,
53
+ tracer: GraphQL::Metrics::Trace,
54
+ capture_timings: nil,
55
+ capture_field_timings: nil,
56
+ trace_mode: :default
57
+ )
58
+ if capture_field_timings && !capture_timings
59
+ raise ArgumentError, "Cannot capture field timings without capturing query timings"
87
60
  end
61
+
62
+ capture_timings = true if capture_timings.nil?
63
+ capture_field_timings = true if capture_field_timings.nil?
64
+ capture_field_timings = false if !capture_timings
65
+
66
+ schema_defn.trace_with(GraphQL::Metrics::Instrumentation, capture_field_timings: capture_field_timings)
67
+ schema_defn.trace_with(tracer, mode: trace_mode) if capture_timings
68
+ schema_defn.query_analyzer(analyzer)
88
69
  end
89
70
  end
90
71
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.8
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Butcher
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-06 00:00:00.000000000 Z
11
+ date: 2024-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -16,42 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.12.10
19
+ version: '2.3'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 1.12.10
27
- - !ruby/object:Gem::Dependency
28
- name: concurrent-ruby
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.1.0
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: 1.1.0
26
+ version: '2.3'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rake
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - "~>"
46
32
  - !ruby/object:Gem::Version
47
- version: '10.0'
33
+ version: '13.2'
48
34
  type: :development
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
38
  - - "~>"
53
39
  - !ruby/object:Gem::Version
54
- version: '10.0'
40
+ version: '13.2'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: minitest
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +72,14 @@ dependencies:
86
72
  requirements:
87
73
  - - "~>"
88
74
  - !ruby/object:Gem::Version
89
- version: 5.1.5
75
+ version: 6.1.7
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
- version: 5.1.5
82
+ version: 6.1.7
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: pry
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -201,7 +187,9 @@ executables: []
201
187
  extensions: []
202
188
  extra_rdoc_files: []
203
189
  files:
190
+ - ".github/dependabot.yml"
204
191
  - ".github/workflows/cla.yml"
192
+ - ".github/workflows/dependabot_auto_merge.yml"
205
193
  - ".github/workflows/ruby.yml"
206
194
  - ".gitignore"
207
195
  - ".rubocop-http---shopify-github-io-ruby-style-guide-rubocop-yml"
@@ -210,28 +198,27 @@ files:
210
198
  - CHANGELOG.md
211
199
  - CODE_OF_CONDUCT.md
212
200
  - Gemfile
201
+ - Gemfile.lock
213
202
  - LICENSE.txt
214
203
  - README.md
215
204
  - RELEASING
216
205
  - Rakefile
217
206
  - bin/console
218
207
  - bin/setup
219
- - gemfiles/graphql_1.13.gemfile
220
- - gemfiles/graphql_2.0.gemfile
208
+ - gemfiles/graphql_2.3.gemfile
221
209
  - gemfiles/graphql_head.gemfile
222
210
  - graphql_metrics.gemspec
223
211
  - lib/graphql/metrics.rb
224
212
  - lib/graphql/metrics/analyzer.rb
225
213
  - lib/graphql/metrics/instrumentation.rb
226
214
  - lib/graphql/metrics/trace.rb
227
- - lib/graphql/metrics/tracer.rb
228
215
  - lib/graphql/metrics/version.rb
229
216
  homepage: https://github.com/Shopify/graphql-metrics
230
217
  licenses:
231
218
  - MIT
232
219
  metadata:
233
220
  allowed_push_host: https://rubygems.org
234
- post_install_message:
221
+ post_install_message:
235
222
  rdoc_options: []
236
223
  require_paths:
237
224
  - lib
@@ -239,15 +226,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
239
226
  requirements:
240
227
  - - ">="
241
228
  - !ruby/object:Gem::Version
242
- version: '0'
229
+ version: '2.7'
243
230
  required_rubygems_version: !ruby/object:Gem::Requirement
244
231
  requirements:
245
232
  - - ">="
246
233
  - !ruby/object:Gem::Version
247
234
  version: '0'
248
235
  requirements: []
249
- rubygems_version: 3.4.22
250
- signing_key:
236
+ rubygems_version: 3.5.18
237
+ signing_key:
251
238
  specification_version: 4
252
239
  summary: GraphQL Metrics Extractor
253
240
  test_files: []
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- eval_gemfile("../Gemfile")
4
-
5
- gem("graphql", "~> 2.0")
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GraphQL
4
- module Metrics
5
- class Tracer
6
- # NOTE: These constants come from the graphql ruby gem and are in "chronological" order based on the phases
7
- # of execution of the graphql-ruby gem, though old versions of the gem aren't always consistent about this (see
8
- # https://github.com/rmosolgo/graphql-ruby/issues/3393). Most of them can be run multiple times when
9
- # multiplexing multiple queries.
10
- GRAPHQL_GEM_EXECUTE_MULTIPLEX_KEY = 'execute_multiplex' # wraps everything below this line; only run once
11
- GRAPHQL_GEM_LEXING_KEY = 'lex' # may not trigger if the query is passed in pre-parsed
12
- GRAPHQL_GEM_PARSING_KEY = 'parse' # may not trigger if the query is passed in pre-parsed
13
- GRAPHQL_GEM_VALIDATION_KEY = 'validate'
14
- GRAPHQL_GEM_ANALYZE_MULTIPLEX_KEY = 'analyze_multiplex' # wraps all `analyze_query`s; only run once
15
- GRAPHQL_GEM_ANALYZE_QUERY_KEY = 'analyze_query'
16
- GRAPHQL_GEM_EXECUTE_QUERY_KEY = 'execute_query'
17
- GRAPHQL_GEM_TRACING_FIELD_KEYS = [
18
- GRAPHQL_GEM_TRACING_FIELD_KEY = 'execute_field',
19
- GRAPHQL_GEM_TRACING_LAZY_FIELD_KEY = 'execute_field_lazy'
20
- ]
21
-
22
- include GraphQL::Metrics::Trace
23
-
24
- def initialize
25
- # no-op, but don't want the behavior from GraphQL::Metrics::Trace
26
- end
27
-
28
- def trace(key, data, &block)
29
- # NOTE: Context doesn't exist yet during lexing, parsing.
30
- context = data[:query]&.context
31
- skip_tracing = context&.fetch(GraphQL::Metrics::SKIP_GRAPHQL_METRICS_ANALYSIS, false)
32
- return yield if skip_tracing
33
-
34
- case key
35
- when GRAPHQL_GEM_EXECUTE_MULTIPLEX_KEY
36
- return capture_multiplex_start_time(&block)
37
- when GRAPHQL_GEM_LEXING_KEY
38
- return capture_lexing_time(&block)
39
- when GRAPHQL_GEM_PARSING_KEY
40
- return capture_parsing_time(&block)
41
- when GRAPHQL_GEM_VALIDATION_KEY
42
- return capture_validation_time(context, &block)
43
- when GRAPHQL_GEM_ANALYZE_MULTIPLEX_KEY
44
- # Ensures that we reset potentially long-lived PreContext objects between multiplexs. We reset at this point
45
- # since all parsing and validation will be done by this point, and a GraphQL::Query::Context will exist.
46
- pre_context.reset
47
- return yield
48
- when GRAPHQL_GEM_ANALYZE_QUERY_KEY
49
- return capture_analysis_time(context, &block)
50
- when GRAPHQL_GEM_EXECUTE_QUERY_KEY
51
- capture_query_start_time(context, &block)
52
- when *GRAPHQL_GEM_TRACING_FIELD_KEYS
53
- return yield if context[SKIP_FIELD_AND_ARGUMENT_METRICS]
54
- return yield unless GraphQL::Metrics.timings_capture_enabled?(data[:query].context)
55
-
56
- context_key = case key
57
- when GRAPHQL_GEM_TRACING_FIELD_KEY
58
- GraphQL::Metrics::INLINE_FIELD_TIMINGS
59
- when GRAPHQL_GEM_TRACING_LAZY_FIELD_KEY
60
- GraphQL::Metrics::LAZY_FIELD_TIMINGS
61
- end
62
-
63
- trace_field(context_key, data[:query], &block)
64
- else
65
- return yield
66
- end
67
- end
68
- end
69
- end
70
- end