yabeda-graphql 0.1.0 → 0.2.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.
@@ -0,0 +1,483 @@
1
+ {
2
+ "__inputs": [
3
+ {
4
+ "name": "DS_PROMETHEUS",
5
+ "label": "Prometheus",
6
+ "description": "",
7
+ "type": "datasource",
8
+ "pluginId": "prometheus",
9
+ "pluginName": "Prometheus"
10
+ }
11
+ ],
12
+ "__requires": [
13
+ {
14
+ "type": "grafana",
15
+ "id": "grafana",
16
+ "name": "Grafana",
17
+ "version": "6.6.0"
18
+ },
19
+ {
20
+ "type": "panel",
21
+ "id": "graph",
22
+ "name": "Graph",
23
+ "version": ""
24
+ },
25
+ {
26
+ "type": "datasource",
27
+ "id": "prometheus",
28
+ "name": "Prometheus",
29
+ "version": "1.0.0"
30
+ }
31
+ ],
32
+ "annotations": {
33
+ "list": [
34
+ {
35
+ "builtIn": 1,
36
+ "datasource": "-- Grafana --",
37
+ "enable": true,
38
+ "hide": true,
39
+ "iconColor": "rgba(0, 211, 255, 1)",
40
+ "name": "Annotations & Alerts",
41
+ "type": "dashboard"
42
+ }
43
+ ]
44
+ },
45
+ "description": "Example dashboard for metrics provided by yabeda-graphql gem for monitoring of APIs powered by GraphQL-Ruby.",
46
+ "editable": true,
47
+ "gnetId": null,
48
+ "graphTooltip": 0,
49
+ "id": null,
50
+ "links": [
51
+ {
52
+ "asDropdown": false,
53
+ "icon": "doc",
54
+ "includeVars": false,
55
+ "keepTime": false,
56
+ "tags": [],
57
+ "targetBlank": true,
58
+ "title": "yabeda-graphql",
59
+ "tooltip": "Open yabeda-graphql page on GitHub",
60
+ "type": "link",
61
+ "url": "https://github.com/yabeda-rb/yabeda-graphql/"
62
+ }
63
+ ],
64
+ "panels": [
65
+ {
66
+ "aliasColors": {},
67
+ "bars": false,
68
+ "dashLength": 10,
69
+ "dashes": false,
70
+ "datasource": null,
71
+ "fieldConfig": {
72
+ "defaults": {},
73
+ "overrides": []
74
+ },
75
+ "fill": 1,
76
+ "fillGradient": 0,
77
+ "gridPos": {
78
+ "h": 9,
79
+ "w": 24,
80
+ "x": 0,
81
+ "y": 0
82
+ },
83
+ "hiddenSeries": false,
84
+ "id": 2,
85
+ "legend": {
86
+ "alignAsTable": true,
87
+ "avg": false,
88
+ "current": true,
89
+ "hideEmpty": true,
90
+ "hideZero": true,
91
+ "max": true,
92
+ "min": false,
93
+ "rightSide": true,
94
+ "show": true,
95
+ "sort": "max",
96
+ "sortDesc": true,
97
+ "total": false,
98
+ "values": true
99
+ },
100
+ "lines": true,
101
+ "linewidth": 1,
102
+ "nullPointMode": "null",
103
+ "options": {
104
+ "alertThreshold": true
105
+ },
106
+ "percentage": false,
107
+ "pluginVersion": "7.5.3",
108
+ "pointradius": 2,
109
+ "points": false,
110
+ "renderer": "flot",
111
+ "seriesOverrides": [],
112
+ "spaceLength": 10,
113
+ "stack": false,
114
+ "steppedLine": false,
115
+ "targets": [
116
+ {
117
+ "exemplar": true,
118
+ "expr": "histogram_quantile(0.95, sum(rate(graphql_field_resolve_runtime_seconds_bucket[1m])) by (type,field,le))",
119
+ "interval": "",
120
+ "legendFormat": "{{type}}.{{field}}",
121
+ "queryType": "randomWalk",
122
+ "refId": "A"
123
+ }
124
+ ],
125
+ "thresholds": [],
126
+ "timeFrom": null,
127
+ "timeRegions": [],
128
+ "timeShift": null,
129
+ "title": "Field resolve time (95th percentile)",
130
+ "tooltip": {
131
+ "shared": true,
132
+ "sort": 2,
133
+ "value_type": "individual"
134
+ },
135
+ "type": "graph",
136
+ "xaxis": {
137
+ "buckets": null,
138
+ "mode": "time",
139
+ "name": null,
140
+ "show": true,
141
+ "values": []
142
+ },
143
+ "yaxes": [
144
+ {
145
+ "format": "s",
146
+ "label": null,
147
+ "logBase": 1,
148
+ "max": null,
149
+ "min": null,
150
+ "show": true
151
+ },
152
+ {
153
+ "format": "short",
154
+ "label": null,
155
+ "logBase": 1,
156
+ "max": null,
157
+ "min": null,
158
+ "show": false
159
+ }
160
+ ],
161
+ "yaxis": {
162
+ "align": false,
163
+ "alignLevel": null
164
+ }
165
+ },
166
+ {
167
+ "aliasColors": {},
168
+ "bars": false,
169
+ "dashLength": 10,
170
+ "dashes": false,
171
+ "datasource": null,
172
+ "fieldConfig": {
173
+ "defaults": {},
174
+ "overrides": []
175
+ },
176
+ "fill": 1,
177
+ "fillGradient": 0,
178
+ "gridPos": {
179
+ "h": 8,
180
+ "w": 9,
181
+ "x": 0,
182
+ "y": 9
183
+ },
184
+ "hiddenSeries": false,
185
+ "id": 6,
186
+ "legend": {
187
+ "alignAsTable": true,
188
+ "avg": false,
189
+ "current": true,
190
+ "hideEmpty": true,
191
+ "max": true,
192
+ "min": false,
193
+ "rightSide": true,
194
+ "show": true,
195
+ "sort": "current",
196
+ "sortDesc": true,
197
+ "total": false,
198
+ "values": true
199
+ },
200
+ "lines": true,
201
+ "linewidth": 1,
202
+ "nullPointMode": "null",
203
+ "options": {
204
+ "alertThreshold": true
205
+ },
206
+ "percentage": false,
207
+ "pluginVersion": "7.5.3",
208
+ "pointradius": 2,
209
+ "points": false,
210
+ "renderer": "flot",
211
+ "seriesOverrides": [],
212
+ "spaceLength": 10,
213
+ "stack": false,
214
+ "steppedLine": false,
215
+ "targets": [
216
+ {
217
+ "exemplar": true,
218
+ "expr": "sum(rate(graphql_query_fields_count[1m])) by (name)",
219
+ "interval": "",
220
+ "legendFormat": "{{name}}",
221
+ "refId": "A"
222
+ }
223
+ ],
224
+ "thresholds": [],
225
+ "timeFrom": null,
226
+ "timeRegions": [],
227
+ "timeShift": null,
228
+ "title": "Queries throughput",
229
+ "tooltip": {
230
+ "shared": true,
231
+ "sort": 2,
232
+ "value_type": "individual"
233
+ },
234
+ "type": "graph",
235
+ "xaxis": {
236
+ "buckets": null,
237
+ "mode": "time",
238
+ "name": null,
239
+ "show": true,
240
+ "values": []
241
+ },
242
+ "yaxes": [
243
+ {
244
+ "decimals": 0,
245
+ "format": "reqps",
246
+ "label": null,
247
+ "logBase": 1,
248
+ "max": null,
249
+ "min": "0",
250
+ "show": true
251
+ },
252
+ {
253
+ "format": "short",
254
+ "label": null,
255
+ "logBase": 1,
256
+ "max": null,
257
+ "min": null,
258
+ "show": false
259
+ }
260
+ ],
261
+ "yaxis": {
262
+ "align": false,
263
+ "alignLevel": null
264
+ }
265
+ },
266
+ {
267
+ "aliasColors": {},
268
+ "bars": false,
269
+ "dashLength": 10,
270
+ "dashes": false,
271
+ "datasource": null,
272
+ "fieldConfig": {
273
+ "defaults": {},
274
+ "overrides": []
275
+ },
276
+ "fill": 1,
277
+ "fillGradient": 0,
278
+ "gridPos": {
279
+ "h": 8,
280
+ "w": 9,
281
+ "x": 9,
282
+ "y": 9
283
+ },
284
+ "hiddenSeries": false,
285
+ "id": 8,
286
+ "legend": {
287
+ "alignAsTable": true,
288
+ "avg": false,
289
+ "current": true,
290
+ "hideEmpty": true,
291
+ "max": true,
292
+ "min": false,
293
+ "rightSide": true,
294
+ "show": true,
295
+ "sort": "current",
296
+ "sortDesc": true,
297
+ "total": false,
298
+ "values": true
299
+ },
300
+ "lines": true,
301
+ "linewidth": 1,
302
+ "nullPointMode": "null",
303
+ "options": {
304
+ "alertThreshold": true
305
+ },
306
+ "percentage": false,
307
+ "pluginVersion": "7.5.3",
308
+ "pointradius": 2,
309
+ "points": false,
310
+ "renderer": "flot",
311
+ "seriesOverrides": [],
312
+ "spaceLength": 10,
313
+ "stack": false,
314
+ "steppedLine": false,
315
+ "targets": [
316
+ {
317
+ "exemplar": true,
318
+ "expr": "sum(rate(graphql_mutation_fields_count[1m])) by (name)",
319
+ "interval": "",
320
+ "legendFormat": "{{name}}",
321
+ "refId": "A"
322
+ }
323
+ ],
324
+ "thresholds": [],
325
+ "timeFrom": null,
326
+ "timeRegions": [],
327
+ "timeShift": null,
328
+ "title": "Mutations throughput",
329
+ "tooltip": {
330
+ "shared": true,
331
+ "sort": 2,
332
+ "value_type": "individual"
333
+ },
334
+ "type": "graph",
335
+ "xaxis": {
336
+ "buckets": null,
337
+ "mode": "time",
338
+ "name": null,
339
+ "show": true,
340
+ "values": []
341
+ },
342
+ "yaxes": [
343
+ {
344
+ "decimals": 0,
345
+ "format": "reqps",
346
+ "label": null,
347
+ "logBase": 1,
348
+ "max": null,
349
+ "min": "0",
350
+ "show": true
351
+ },
352
+ {
353
+ "format": "short",
354
+ "label": null,
355
+ "logBase": 1,
356
+ "max": null,
357
+ "min": null,
358
+ "show": false
359
+ }
360
+ ],
361
+ "yaxis": {
362
+ "align": false,
363
+ "alignLevel": null
364
+ }
365
+ },
366
+ {
367
+ "aliasColors": {},
368
+ "bars": false,
369
+ "dashLength": 10,
370
+ "dashes": false,
371
+ "datasource": null,
372
+ "decimals": 0,
373
+ "fieldConfig": {
374
+ "defaults": {},
375
+ "overrides": []
376
+ },
377
+ "fill": 1,
378
+ "fillGradient": 0,
379
+ "gridPos": {
380
+ "h": 8,
381
+ "w": 6,
382
+ "x": 18,
383
+ "y": 9
384
+ },
385
+ "hiddenSeries": false,
386
+ "id": 4,
387
+ "legend": {
388
+ "alignAsTable": true,
389
+ "avg": false,
390
+ "current": false,
391
+ "hideEmpty": true,
392
+ "hideZero": false,
393
+ "max": false,
394
+ "min": false,
395
+ "rightSide": true,
396
+ "show": true,
397
+ "total": false,
398
+ "values": false
399
+ },
400
+ "lines": true,
401
+ "linewidth": 1,
402
+ "nullPointMode": "null",
403
+ "options": {
404
+ "alertThreshold": true
405
+ },
406
+ "percentage": false,
407
+ "pluginVersion": "7.5.3",
408
+ "pointradius": 2,
409
+ "points": false,
410
+ "renderer": "flot",
411
+ "seriesOverrides": [],
412
+ "spaceLength": 10,
413
+ "stack": false,
414
+ "steppedLine": false,
415
+ "targets": [
416
+ {
417
+ "exemplar": true,
418
+ "expr": "sum(rate(graphql_fields_request_count{deprecated=\"true\"}[1m])) by (type, field)",
419
+ "interval": "",
420
+ "legendFormat": "{{type}}.{{field}}",
421
+ "refId": "A"
422
+ }
423
+ ],
424
+ "thresholds": [],
425
+ "timeFrom": null,
426
+ "timeRegions": [],
427
+ "timeShift": null,
428
+ "title": "Deprecated fields usage",
429
+ "tooltip": {
430
+ "shared": true,
431
+ "sort": 0,
432
+ "value_type": "individual"
433
+ },
434
+ "type": "graph",
435
+ "xaxis": {
436
+ "buckets": null,
437
+ "mode": "time",
438
+ "name": null,
439
+ "show": true,
440
+ "values": []
441
+ },
442
+ "yaxes": [
443
+ {
444
+ "decimals": 0,
445
+ "format": "reqps",
446
+ "label": null,
447
+ "logBase": 1,
448
+ "max": null,
449
+ "min": "0",
450
+ "show": true
451
+ },
452
+ {
453
+ "format": "short",
454
+ "label": null,
455
+ "logBase": 1,
456
+ "max": null,
457
+ "min": null,
458
+ "show": false
459
+ }
460
+ ],
461
+ "yaxis": {
462
+ "align": false,
463
+ "alignLevel": null
464
+ }
465
+ }
466
+ ],
467
+ "refresh": "10s",
468
+ "schemaVersion": 27,
469
+ "style": "dark",
470
+ "tags": [],
471
+ "templating": {
472
+ "list": []
473
+ },
474
+ "time": {
475
+ "from": "now-6h",
476
+ "to": "now"
477
+ },
478
+ "timepicker": {},
479
+ "timezone": "",
480
+ "title": "GraphQL API",
481
+ "uid": "yabeda-graphql",
482
+ "version": 1
483
+ }
@@ -0,0 +1,27 @@
1
+ module Yabeda
2
+ module GraphQL
3
+ class Instrumentation
4
+ def before_query(query)
5
+ reset_cache!(query)
6
+ end
7
+
8
+ def after_query(query)
9
+ cache(query).each do |_path, options|
10
+ Yabeda.graphql.field_resolve_runtime.measure(options[:tags], options[:duration])
11
+ Yabeda.graphql.fields_request_count.increment(options[:tags])
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def cache(query)
18
+ query.context.namespace(Yabeda::GraphQL)[:field_call_cache]
19
+ end
20
+
21
+ def reset_cache!(query)
22
+ query.context.namespace(Yabeda::GraphQL)[:field_call_cache] =
23
+ Hash.new { |h,k| h[k] = { tags: {}, duration: 0.0 } }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -26,10 +26,10 @@ module Yabeda
26
26
  when "execute_field", "execute_field_lazy"
27
27
  field, path, query = extract_field_trace_data(data)
28
28
 
29
- return result if key == "execute_field" && query.schema.lazy?(result)
30
-
31
29
  tags = extract_field_tags(field)
32
30
  if path.length == 1
31
+ return result if key == "execute_field" && query.schema.lazy?(result)
32
+
33
33
  if query.query?
34
34
  instrument_query_execution(tags)
35
35
  elsif query.mutation?
@@ -38,7 +38,7 @@ module Yabeda
38
38
  # Not implemented yet
39
39
  end
40
40
  else
41
- instrument_field_execution(tags, duration)
41
+ instrument_field_execution(query, path, tags, duration)
42
42
  end
43
43
  end
44
44
 
@@ -63,9 +63,9 @@ module Yabeda
63
63
  }
64
64
  end
65
65
 
66
- def instrument_field_execution(tags, duration)
67
- Yabeda.graphql.field_resolve_runtime.measure(tags, duration)
68
- Yabeda.graphql.fields_request_count.increment(tags)
66
+ def instrument_field_execution(query, path, tags, duration)
67
+ cache(query)[path][:tags] = tags
68
+ cache(query)[path][:duration] += duration
69
69
  end
70
70
 
71
71
  def instrument_mutation_execution(tags)
@@ -78,6 +78,10 @@ module Yabeda
78
78
  Yabeda.graphql.query_fields_count.increment(tags)
79
79
  end
80
80
 
81
+ def cache(query)
82
+ query.context.namespace(Yabeda::GraphQL)[:field_call_cache]
83
+ end
84
+
81
85
  def platform_field_key(type, field)
82
86
  "#{type.graphql_name}.#{field.graphql_name}"
83
87
  end
@@ -1,5 +1,5 @@
1
1
  module Yabeda
2
2
  module GraphQL
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.2"
4
4
  end
5
5
  end
@@ -1,13 +1,14 @@
1
1
  require "yabeda"
2
2
  require "yabeda/graphql/version"
3
3
  require "yabeda/graphql/tracing"
4
+ require "yabeda/graphql/instrumentation"
4
5
 
5
6
  module Yabeda
6
7
  module GraphQL
7
8
  class Error < StandardError; end
8
9
 
9
10
  REQUEST_BUCKETS = [
10
- 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10,
11
+ 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10,
11
12
  ].freeze
12
13
 
13
14
  Yabeda.configure do
@@ -27,5 +28,10 @@ module Yabeda
27
28
  counter :mutation_fields_count, comment: "A counter for mutation root fields",
28
29
  tags: %i[name deprecated]
29
30
  end
31
+
32
+ def self.use(schema)
33
+ schema.instrument(:query, Instrumentation.new)
34
+ schema.use Tracing, trace_scalars: true
35
+ end
30
36
  end
31
37
  end
Binary file
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.require_paths = ["lib"]
25
25
 
26
26
  spec.add_runtime_dependency "yabeda", "~> 0.2"
27
- spec.add_runtime_dependency "graphql", "~> 1.9"
27
+ spec.add_runtime_dependency "graphql", ">= 1.9", "< 3"
28
28
 
29
29
  spec.add_development_dependency "bundler"
30
30
  spec.add_development_dependency "rake", "~> 13.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yabeda-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Novikov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-17 00:00:00.000000000 Z
11
+ date: 2022-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yabeda
@@ -28,16 +28,22 @@ dependencies:
28
28
  name: graphql
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.9'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '3'
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - "~>"
41
+ - - ">="
39
42
  - !ruby/object:Gem::Version
40
43
  version: '1.9'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '3'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: bundler
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -102,10 +108,12 @@ executables: []
102
108
  extensions: []
103
109
  extra_rdoc_files: []
104
110
  files:
111
+ - ".github/workflows/build-release.yml"
112
+ - ".github/workflows/test.yml"
105
113
  - ".gitignore"
106
114
  - ".rspec"
107
- - ".travis.yml"
108
115
  - Appraisals
116
+ - CHANGELOG.md
109
117
  - Gemfile
110
118
  - Gemfile.lock
111
119
  - LICENSE.txt
@@ -116,11 +124,22 @@ files:
116
124
  - gemfiles/.bundle/config
117
125
  - gemfiles/graphql_1.10.gemfile
118
126
  - gemfiles/graphql_1.10.gemfile.lock
127
+ - gemfiles/graphql_1.11.gemfile
128
+ - gemfiles/graphql_1.11.gemfile.lock
129
+ - gemfiles/graphql_1.12.gemfile
130
+ - gemfiles/graphql_1.12.gemfile.lock
131
+ - gemfiles/graphql_1.13.gemfile
132
+ - gemfiles/graphql_1.13.gemfile.lock
119
133
  - gemfiles/graphql_1.9.gemfile
120
134
  - gemfiles/graphql_1.9.gemfile.lock
135
+ - gemfiles/graphql_2.0.gemfile
136
+ - gemfiles/graphql_2.0.gemfile.lock
137
+ - grafana-dashboard.json
121
138
  - lib/yabeda/graphql.rb
139
+ - lib/yabeda/graphql/instrumentation.rb
122
140
  - lib/yabeda/graphql/tracing.rb
123
141
  - lib/yabeda/graphql/version.rb
142
+ - yabeda-graphql-logo.png
124
143
  - yabeda-graphql.gemspec
125
144
  homepage: http://github.com/yabeda-rb/yabeda-graphql
126
145
  licenses:
@@ -142,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
161
  - !ruby/object:Gem::Version
143
162
  version: '0'
144
163
  requirements: []
145
- rubygems_version: 3.1.2
164
+ rubygems_version: 3.1.6
146
165
  signing_key:
147
166
  specification_version: 4
148
167
  summary: Collects metrics to monitor execution of your GraphQL queries
data/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.0
6
- gemfile:
7
- - gemfiles/graphql_1.10.gemfile
8
- - gemfiles/graphql_1.9.gemfile
9
- env:
10
- - GRAPHQL_RUBY_INTERPRETER=yes
11
- - GRAPHQL_RUBY_INTERPRETER=no
12
- before_install: gem install bundler -v 2.1.4