graphql-metrics 4.0.1 → 4.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45de407a0b5642ad74d27cdb4ab00635590a38d8b719fc448a3e94d6244d7daf
4
- data.tar.gz: cae841292ce06f25031974127696594b426b41f469e4f7f74f37f1f3a8c8f521
3
+ metadata.gz: 2af911e9031c446b604b9c296caef2c89f00cb968ecf15350a6a196d6cab08d7
4
+ data.tar.gz: 94e65ae882fd6222bf3b4ed9395f32dfc395ec00c85e061a458cb5fe54b9dc67
5
5
  SHA512:
6
- metadata.gz: 861b2728422d3f8c314024084497ef761c4ca83491f3967ccffa2d540ced0de524d318a380f7966b6555a539fd30ffdfaec83cafee42f020813875148434f734
7
- data.tar.gz: 83bde1129c7492cd92ffc097e3072275f179262530a5fccbe6e61b5c485a08bb231a3af8e29ddf88a6f0f3cdfdf5bd7101f0266e042afe37d19232a07195d922
6
+ metadata.gz: aa3ffe4208e67594c3e65786a0a0477cdcee71506dea37988db388433eb155175d87f92e30082931e5e8c493937876e9a5a4043327b74e9e17bc474d58bd4ed9
7
+ data.tar.gz: e876e9f5907cff0863a6ead3e319f34ab238b1904d0f72c8874420fdf50b5cb2941cb0f77fcfbefac35968c2bb86ec6364c5e338842dcee591eb165ee2ed14d6
@@ -1,3 +1,7 @@
1
+ 4.0.2
2
+ -----
3
+ - [25](https://github.com/Shopify/graphql-metrics/pull/25) Safely handle interrupted runtime metrics.
4
+
1
5
  4.0.1
2
6
  -----
3
7
  - [24](https://github.com/Shopify/graphql-metrics/pull/24) Safely call `arguments_for` to handle arguments which may
data/README.md CHANGED
@@ -5,6 +5,8 @@
5
5
  Extract as much much detail as you want from GraphQL queries, served up from your Ruby app and the [`graphql` gem](https://github.com/rmosolgo/graphql-ruby).
6
6
  Compatible with the [`graphql-batch` gem](https://github.com/Shopify/graphql-batch), to extract batch-loaded fields resolution timings.
7
7
 
8
+ Be sure to read the [CHANGELOG](CHANGELOG.md) to stay updated on feature additions, breaking changes made to this gem.
9
+
8
10
  ## Installation
9
11
 
10
12
  Add this line to your application's Gemfile:
@@ -42,6 +44,13 @@ etc.
42
44
 
43
45
  What you do with these captured metrics is up to you!
44
46
 
47
+ **NOTE**: Runtime metrics on for queries (like `query_duration`, `parsing_start_time_offset` etc.) as well as field
48
+ resolver timings (like `resolver_timings`, `lazy_resolver_timings`) may not be present in the extracted `metrics` hash,
49
+ even if you opt to collect them by using `GraphQL::Metrics::Analyzer` and `GraphQL::Metrics::Tracer`.
50
+
51
+ More specifically, if any non-`graphql-ruby` gem-related exceptions occur in your application during query document
52
+ parsing and validation runtime metrics will not be added to the `metrics` hash.
53
+
45
54
  ### Define your own analyzer subclass
46
55
 
47
56
  ```ruby
@@ -173,7 +182,7 @@ class Schema < GraphQL::Schema
173
182
  use GraphQL::Analysis::AST # Required.
174
183
 
175
184
  query_analyzer SimpleAnalyzer
176
-
185
+
177
186
  instrument :query, GraphQL::Metrics::Instrumentation.new # Both of these are required if either is used.
178
187
  tracer GraphQL::Metrics::Tracer.new # <-- Note!
179
188
 
@@ -61,17 +61,20 @@ module GraphQL
61
61
  end
62
62
  end
63
63
 
64
- def extract_fields_with_runtime_metrics
64
+ def extract_fields(with_runtime_metrics: true)
65
65
  return if query.context[SKIP_FIELD_AND_ARGUMENT_METRICS]
66
66
 
67
67
  ns = query.context.namespace(CONTEXT_NAMESPACE)
68
68
 
69
69
  @static_field_metrics.each do |static_metrics|
70
- resolver_timings = ns[GraphQL::Metrics::INLINE_FIELD_TIMINGS][static_metrics[:path]]
71
- lazy_resolver_timings = ns[GraphQL::Metrics::LAZY_FIELD_TIMINGS][static_metrics[:path]]
72
70
 
73
- static_metrics[:resolver_timings] = resolver_timings || []
74
- static_metrics[:lazy_resolver_timings] = lazy_resolver_timings || []
71
+ if with_runtime_metrics
72
+ resolver_timings = ns[GraphQL::Metrics::INLINE_FIELD_TIMINGS][static_metrics[:path]]
73
+ lazy_resolver_timings = ns[GraphQL::Metrics::LAZY_FIELD_TIMINGS][static_metrics[:path]]
74
+
75
+ static_metrics[:resolver_timings] = resolver_timings || []
76
+ static_metrics[:lazy_resolver_timings] = lazy_resolver_timings || []
77
+ end
75
78
 
76
79
  field_extracted(static_metrics)
77
80
  end
@@ -25,23 +25,31 @@ module GraphQL
25
25
  return if query.context[GraphQL::Metrics::SKIP_GRAPHQL_METRICS_ANALYSIS]
26
26
 
27
27
  ns = query.context.namespace(CONTEXT_NAMESPACE)
28
+ analyzer = ns[GraphQL::Metrics::ANALYZER_INSTANCE_KEY]
28
29
 
29
- # NOTE: The start time stored at `ns[GraphQL::Metrics::QUERY_START_TIME_MONOTONIC]` is captured during query
30
- # parsing, which occurs before `Instrumentation#before_query`.
31
- query_duration = GraphQL::Metrics.current_time_monotonic - ns[GraphQL::Metrics::QUERY_START_TIME_MONOTONIC]
30
+ if runtime_metrics_interrupted?(ns)
31
+ # If runtime metrics were interrupted, then it's most likely that the application raised an exception and that
32
+ # query parsing (which is instrumented by GraphQL::Metrics::Tracer) was abruptly stopped.
33
+ #
34
+ # In this scenario, we still attempt to log whatever static query metrics we've collected, with runtime
35
+ # metrics (like query, field resolver timings) excluded.
36
+ analyzer.extract_fields(with_runtime_metrics: false)
37
+ analyzer.extract_query
38
+ else
39
+ query_duration = GraphQL::Metrics.current_time_monotonic - ns[GraphQL::Metrics::QUERY_START_TIME_MONOTONIC]
32
40
 
33
- runtime_query_metrics = {
34
- query_start_time: ns[GraphQL::Metrics::QUERY_START_TIME],
35
- query_duration: query_duration,
36
- parsing_start_time_offset: ns[GraphQL::Metrics::PARSING_START_TIME_OFFSET],
37
- parsing_duration: ns[GraphQL::Metrics::PARSING_DURATION],
38
- validation_start_time_offset: ns[GraphQL::Metrics::VALIDATION_START_TIME_OFFSET],
39
- validation_duration: ns[GraphQL::Metrics::VALIDATION_DURATION],
40
- }
41
+ runtime_query_metrics = {
42
+ query_start_time: ns[GraphQL::Metrics::QUERY_START_TIME],
43
+ query_duration: query_duration,
44
+ parsing_start_time_offset: ns[GraphQL::Metrics::PARSING_START_TIME_OFFSET],
45
+ parsing_duration: ns[GraphQL::Metrics::PARSING_DURATION],
46
+ validation_start_time_offset: ns[GraphQL::Metrics::VALIDATION_START_TIME_OFFSET],
47
+ validation_duration: ns[GraphQL::Metrics::VALIDATION_DURATION],
48
+ }
41
49
 
42
- analyzer = ns[GraphQL::Metrics::ANALYZER_INSTANCE_KEY]
43
- analyzer.extract_fields_with_runtime_metrics
44
- analyzer.extract_query(runtime_query_metrics: runtime_query_metrics)
50
+ analyzer.extract_fields
51
+ analyzer.extract_query(runtime_query_metrics: runtime_query_metrics)
52
+ end
45
53
  end
46
54
 
47
55
  private
@@ -51,6 +59,12 @@ module GraphQL
51
59
  # which did not reject "empty" documents in its parser.
52
60
  query.valid? && !query.selected_operation.nil?
53
61
  end
62
+
63
+ def runtime_metrics_interrupted?(context_namespace)
64
+ # NOTE: The start time stored at `ns[GraphQL::Metrics::QUERY_START_TIME_MONOTONIC]` is captured during query
65
+ # parsing, which occurs before `Instrumentation#before_query`.
66
+ context_namespace.key?(GraphQL::Metrics::QUERY_START_TIME_MONOTONIC) == false
67
+ end
54
68
  end
55
69
  end
56
70
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module Metrics
5
- VERSION = "4.0.1"
5
+ VERSION = "4.0.2"
6
6
  end
7
7
  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: 4.0.1
4
+ version: 4.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Butcher
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-05 00:00:00.000000000 Z
11
+ date: 2020-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql