graphql-metrics 4.0.1 → 4.0.2

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: 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