lepus 0.0.1.rc2 → 0.1.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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock +12 -1
  5. data/README.md +179 -0
  6. data/config.ru +14 -0
  7. data/docs/README.md +80 -0
  8. data/docs/cli.md +108 -0
  9. data/docs/configuration.md +171 -0
  10. data/docs/consumers.md +168 -0
  11. data/docs/getting-started.md +136 -0
  12. data/docs/images/lepus-web.png +0 -0
  13. data/docs/middleware.md +240 -0
  14. data/docs/producers.md +173 -0
  15. data/docs/prometheus.md +112 -0
  16. data/docs/rails.md +161 -0
  17. data/docs/supervisor.md +112 -0
  18. data/docs/testing.md +141 -0
  19. data/docs/web.md +85 -0
  20. data/examples/grafana-dashboard.json +450 -0
  21. data/gemfiles/Gemfile.rails-5.2 +1 -0
  22. data/gemfiles/Gemfile.rails-5.2.lock +59 -46
  23. data/gemfiles/Gemfile.rails-6.1 +1 -0
  24. data/gemfiles/Gemfile.rails-6.1.lock +72 -58
  25. data/gemfiles/Gemfile.rails-7.2.lock +8 -1
  26. data/gemfiles/Gemfile.rails-8.0.lock +8 -1
  27. data/lepus.gemspec +5 -1
  28. data/lib/lepus/cli.rb +24 -0
  29. data/lib/lepus/configuration.rb +42 -0
  30. data/lib/lepus/consumer.rb +12 -0
  31. data/lib/lepus/consumers/handler.rb +3 -1
  32. data/lib/lepus/consumers/stats.rb +70 -0
  33. data/lib/lepus/consumers/stats_registry.rb +29 -0
  34. data/lib/lepus/consumers/worker.rb +7 -6
  35. data/lib/lepus/process.rb +4 -4
  36. data/lib/lepus/process_registry/backend.rb +49 -0
  37. data/lib/lepus/process_registry/file_backend.rb +108 -0
  38. data/lib/lepus/process_registry/message_builder.rb +72 -0
  39. data/lib/lepus/process_registry/rabbitmq_backend.rb +153 -0
  40. data/lib/lepus/process_registry.rb +28 -67
  41. data/lib/lepus/prometheus/collector.rb +149 -0
  42. data/lib/lepus/prometheus/instrumentation.rb +168 -0
  43. data/lib/lepus/prometheus.rb +48 -0
  44. data/lib/lepus/publisher.rb +3 -1
  45. data/lib/lepus/supervisor.rb +9 -2
  46. data/lib/lepus/version.rb +1 -1
  47. data/lib/lepus/web/aggregator.rb +154 -0
  48. data/lib/lepus/web/api.rb +132 -0
  49. data/lib/lepus/web/app.rb +37 -0
  50. data/lib/lepus/web/management_api.rb +192 -0
  51. data/lib/lepus/web/respond_with.rb +28 -0
  52. data/lib/lepus/web.rb +238 -0
  53. data/lib/lepus.rb +5 -0
  54. data/test_offline.html +189 -0
  55. data/web/assets/css/styles.css +635 -0
  56. data/web/assets/js/app.js +6 -0
  57. data/web/assets/js/bootstrap.js +20 -0
  58. data/web/assets/js/controllers/connection_controller.js +44 -0
  59. data/web/assets/js/controllers/dashboard_controller.js +499 -0
  60. data/web/assets/js/controllers/queue_controller.js +17 -0
  61. data/web/assets/js/controllers/theme_controller.js +31 -0
  62. data/web/assets/js/offline-manager.js +233 -0
  63. data/web/assets/js/service-worker-manager.js +65 -0
  64. data/web/index.html +159 -0
  65. data/web/sw.js +144 -0
  66. metadata +103 -5
@@ -0,0 +1,450 @@
1
+ {
2
+ "annotations": {
3
+ "list": [
4
+ {
5
+ "builtIn": 1,
6
+ "datasource": {
7
+ "type": "grafana",
8
+ "uid": "-- Grafana --"
9
+ },
10
+ "enable": true,
11
+ "hide": true,
12
+ "iconColor": "rgba(0, 211, 255, 1)",
13
+ "name": "Annotations & Alerts",
14
+ "type": "dashboard"
15
+ }
16
+ ]
17
+ },
18
+ "description": "Lepus RabbitMQ consumers/producer dashboard. Reads metrics exposed by the `lepus/prometheus/collector` running inside a prometheus_exporter process.",
19
+ "editable": true,
20
+ "fiscalYearStartMonth": 0,
21
+ "graphTooltip": 1,
22
+ "id": null,
23
+ "links": [],
24
+ "liveNow": false,
25
+ "panels": [
26
+ {
27
+ "collapsed": false,
28
+ "gridPos": {"h": 1, "w": 24, "x": 0, "y": 0},
29
+ "id": 100,
30
+ "panels": [],
31
+ "title": "Throughput",
32
+ "type": "row"
33
+ },
34
+ {
35
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
36
+ "description": "Per-consumer delivery rate, split by outcome (ack / reject / nack / requeue).",
37
+ "fieldConfig": {
38
+ "defaults": {
39
+ "color": {"mode": "palette-classic"},
40
+ "custom": {
41
+ "axisCenteredZero": false,
42
+ "axisColorMode": "text",
43
+ "axisLabel": "msg/s",
44
+ "axisPlacement": "auto",
45
+ "barAlignment": 0,
46
+ "drawStyle": "line",
47
+ "fillOpacity": 10,
48
+ "gradientMode": "opacity",
49
+ "lineInterpolation": "smooth",
50
+ "lineWidth": 2,
51
+ "pointSize": 4,
52
+ "scaleDistribution": {"type": "linear"},
53
+ "showPoints": "never",
54
+ "spanNulls": false,
55
+ "stacking": {"group": "A", "mode": "normal"}
56
+ },
57
+ "unit": "cps"
58
+ },
59
+ "overrides": []
60
+ },
61
+ "gridPos": {"h": 8, "w": 12, "x": 0, "y": 1},
62
+ "id": 1,
63
+ "options": {
64
+ "legend": {"calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true},
65
+ "tooltip": {"mode": "multi", "sort": "desc"}
66
+ },
67
+ "targets": [
68
+ {
69
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
70
+ "expr": "sum by (consumer, result) (rate(lepus_messages_processed_total[$__rate_interval]))",
71
+ "legendFormat": "{{consumer}} · {{result}}",
72
+ "refId": "A"
73
+ }
74
+ ],
75
+ "title": "Consumer throughput",
76
+ "type": "timeseries"
77
+ },
78
+ {
79
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
80
+ "description": "Per-exchange publish rate.",
81
+ "fieldConfig": {
82
+ "defaults": {
83
+ "color": {"mode": "palette-classic"},
84
+ "custom": {
85
+ "axisLabel": "msg/s",
86
+ "drawStyle": "line",
87
+ "fillOpacity": 10,
88
+ "lineInterpolation": "smooth",
89
+ "lineWidth": 2,
90
+ "stacking": {"group": "A", "mode": "normal"}
91
+ },
92
+ "unit": "cps"
93
+ },
94
+ "overrides": []
95
+ },
96
+ "gridPos": {"h": 8, "w": 12, "x": 12, "y": 1},
97
+ "id": 2,
98
+ "options": {
99
+ "legend": {"calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true},
100
+ "tooltip": {"mode": "multi", "sort": "desc"}
101
+ },
102
+ "targets": [
103
+ {
104
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
105
+ "expr": "sum by (exchange) (rate(lepus_messages_published_total[$__rate_interval]))",
106
+ "legendFormat": "{{exchange}}",
107
+ "refId": "A"
108
+ }
109
+ ],
110
+ "title": "Publish throughput",
111
+ "type": "timeseries"
112
+ },
113
+ {
114
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
115
+ "description": "Share of failed deliveries (reject / nack / requeue) over total delivered.",
116
+ "fieldConfig": {
117
+ "defaults": {
118
+ "color": {"mode": "thresholds"},
119
+ "mappings": [],
120
+ "max": 1,
121
+ "min": 0,
122
+ "thresholds": {
123
+ "mode": "percentage",
124
+ "steps": [
125
+ {"color": "green", "value": null},
126
+ {"color": "yellow", "value": 1},
127
+ {"color": "red", "value": 5}
128
+ ]
129
+ },
130
+ "unit": "percentunit"
131
+ },
132
+ "overrides": []
133
+ },
134
+ "gridPos": {"h": 6, "w": 8, "x": 0, "y": 9},
135
+ "id": 3,
136
+ "options": {
137
+ "colorMode": "value",
138
+ "graphMode": "area",
139
+ "justifyMode": "auto",
140
+ "orientation": "horizontal",
141
+ "reduceOptions": {"calcs": ["lastNotNull"], "fields": "", "values": false},
142
+ "textMode": "auto"
143
+ },
144
+ "targets": [
145
+ {
146
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
147
+ "expr": "sum(rate(lepus_messages_processed_total{result!=\"ack\"}[$__rate_interval])) / clamp_min(sum(rate(lepus_messages_processed_total[$__rate_interval])), 1)",
148
+ "legendFormat": "failure ratio",
149
+ "refId": "A"
150
+ }
151
+ ],
152
+ "title": "Failure ratio (non-ack / total)",
153
+ "type": "stat"
154
+ },
155
+ {
156
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
157
+ "description": "p50/p95/p99 message delivery latency (time spent in consumer).",
158
+ "fieldConfig": {
159
+ "defaults": {
160
+ "color": {"mode": "palette-classic"},
161
+ "custom": {
162
+ "axisLabel": "seconds",
163
+ "drawStyle": "line",
164
+ "fillOpacity": 5,
165
+ "lineInterpolation": "smooth",
166
+ "lineWidth": 2
167
+ },
168
+ "unit": "s"
169
+ },
170
+ "overrides": []
171
+ },
172
+ "gridPos": {"h": 6, "w": 16, "x": 8, "y": 9},
173
+ "id": 4,
174
+ "options": {
175
+ "legend": {"calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true},
176
+ "tooltip": {"mode": "multi", "sort": "desc"}
177
+ },
178
+ "targets": [
179
+ {
180
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
181
+ "expr": "histogram_quantile(0.50, sum by (le, consumer) (rate(lepus_delivery_duration_seconds_bucket[$__rate_interval])))",
182
+ "legendFormat": "p50 {{consumer}}",
183
+ "refId": "A"
184
+ },
185
+ {
186
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
187
+ "expr": "histogram_quantile(0.95, sum by (le, consumer) (rate(lepus_delivery_duration_seconds_bucket[$__rate_interval])))",
188
+ "legendFormat": "p95 {{consumer}}",
189
+ "refId": "B"
190
+ },
191
+ {
192
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
193
+ "expr": "histogram_quantile(0.99, sum by (le, consumer) (rate(lepus_delivery_duration_seconds_bucket[$__rate_interval])))",
194
+ "legendFormat": "p99 {{consumer}}",
195
+ "refId": "C"
196
+ }
197
+ ],
198
+ "title": "Delivery latency (consumer processing time)",
199
+ "type": "timeseries"
200
+ },
201
+ {
202
+ "collapsed": false,
203
+ "gridPos": {"h": 1, "w": 24, "x": 0, "y": 15},
204
+ "id": 101,
205
+ "panels": [],
206
+ "title": "Queues",
207
+ "type": "row"
208
+ },
209
+ {
210
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
211
+ "description": "Backlog per queue: messages ready to be delivered.",
212
+ "fieldConfig": {
213
+ "defaults": {
214
+ "color": {"mode": "palette-classic"},
215
+ "custom": {
216
+ "drawStyle": "line",
217
+ "fillOpacity": 15,
218
+ "lineInterpolation": "stepAfter",
219
+ "lineWidth": 2
220
+ },
221
+ "unit": "short"
222
+ },
223
+ "overrides": []
224
+ },
225
+ "gridPos": {"h": 8, "w": 12, "x": 0, "y": 16},
226
+ "id": 5,
227
+ "options": {
228
+ "legend": {"calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true},
229
+ "tooltip": {"mode": "multi", "sort": "desc"}
230
+ },
231
+ "targets": [
232
+ {
233
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
234
+ "expr": "lepus_queue_messages_ready",
235
+ "legendFormat": "{{name}}",
236
+ "refId": "A"
237
+ }
238
+ ],
239
+ "title": "Messages ready",
240
+ "type": "timeseries"
241
+ },
242
+ {
243
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
244
+ "description": "Messages delivered but not yet acknowledged (in-flight).",
245
+ "fieldConfig": {
246
+ "defaults": {
247
+ "color": {"mode": "palette-classic"},
248
+ "custom": {
249
+ "drawStyle": "line",
250
+ "fillOpacity": 15,
251
+ "lineInterpolation": "stepAfter",
252
+ "lineWidth": 2
253
+ },
254
+ "unit": "short"
255
+ },
256
+ "overrides": []
257
+ },
258
+ "gridPos": {"h": 8, "w": 12, "x": 12, "y": 16},
259
+ "id": 6,
260
+ "options": {
261
+ "legend": {"calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true},
262
+ "tooltip": {"mode": "multi", "sort": "desc"}
263
+ },
264
+ "targets": [
265
+ {
266
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
267
+ "expr": "lepus_queue_messages_unacknowledged",
268
+ "legendFormat": "{{name}}",
269
+ "refId": "A"
270
+ }
271
+ ],
272
+ "title": "Messages unacknowledged",
273
+ "type": "timeseries"
274
+ },
275
+ {
276
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
277
+ "description": "Active consumer count per queue.",
278
+ "fieldConfig": {
279
+ "defaults": {
280
+ "color": {"mode": "palette-classic"},
281
+ "custom": {
282
+ "drawStyle": "line",
283
+ "fillOpacity": 5,
284
+ "lineInterpolation": "stepAfter",
285
+ "lineWidth": 2
286
+ },
287
+ "unit": "short"
288
+ },
289
+ "overrides": []
290
+ },
291
+ "gridPos": {"h": 8, "w": 12, "x": 0, "y": 24},
292
+ "id": 7,
293
+ "options": {
294
+ "legend": {"calcs": ["last"], "displayMode": "table", "placement": "right", "showLegend": true},
295
+ "tooltip": {"mode": "multi", "sort": "desc"}
296
+ },
297
+ "targets": [
298
+ {
299
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
300
+ "expr": "lepus_queue_consumers",
301
+ "legendFormat": "{{name}}",
302
+ "refId": "A"
303
+ }
304
+ ],
305
+ "title": "Consumers per queue",
306
+ "type": "timeseries"
307
+ },
308
+ {
309
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
310
+ "description": "RabbitMQ queue memory usage.",
311
+ "fieldConfig": {
312
+ "defaults": {
313
+ "color": {"mode": "palette-classic"},
314
+ "custom": {
315
+ "drawStyle": "line",
316
+ "fillOpacity": 5,
317
+ "lineInterpolation": "smooth",
318
+ "lineWidth": 2
319
+ },
320
+ "unit": "bytes"
321
+ },
322
+ "overrides": []
323
+ },
324
+ "gridPos": {"h": 8, "w": 12, "x": 12, "y": 24},
325
+ "id": 8,
326
+ "options": {
327
+ "legend": {"calcs": ["last", "max"], "displayMode": "table", "placement": "right", "showLegend": true},
328
+ "tooltip": {"mode": "multi", "sort": "desc"}
329
+ },
330
+ "targets": [
331
+ {
332
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
333
+ "expr": "lepus_queue_memory_bytes",
334
+ "legendFormat": "{{name}}",
335
+ "refId": "A"
336
+ }
337
+ ],
338
+ "title": "Queue memory",
339
+ "type": "timeseries"
340
+ },
341
+ {
342
+ "collapsed": false,
343
+ "gridPos": {"h": 1, "w": 24, "x": 0, "y": 32},
344
+ "id": 102,
345
+ "panels": [],
346
+ "title": "Processes",
347
+ "type": "row"
348
+ },
349
+ {
350
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
351
+ "description": "RSS memory per Lepus process (worker / supervisor).",
352
+ "fieldConfig": {
353
+ "defaults": {
354
+ "color": {"mode": "palette-classic"},
355
+ "custom": {
356
+ "drawStyle": "line",
357
+ "fillOpacity": 10,
358
+ "lineInterpolation": "smooth",
359
+ "lineWidth": 2
360
+ },
361
+ "unit": "bytes"
362
+ },
363
+ "overrides": []
364
+ },
365
+ "gridPos": {"h": 8, "w": 16, "x": 0, "y": 33},
366
+ "id": 9,
367
+ "options": {
368
+ "legend": {"calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true},
369
+ "tooltip": {"mode": "multi", "sort": "desc"}
370
+ },
371
+ "targets": [
372
+ {
373
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
374
+ "expr": "lepus_process_rss_memory_bytes",
375
+ "legendFormat": "{{kind}} {{name}} · pid {{pid}}",
376
+ "refId": "A"
377
+ }
378
+ ],
379
+ "title": "Process RSS memory",
380
+ "type": "timeseries"
381
+ },
382
+ {
383
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
384
+ "description": "Running Lepus processes by kind.",
385
+ "fieldConfig": {
386
+ "defaults": {
387
+ "color": {"mode": "thresholds"},
388
+ "mappings": [],
389
+ "thresholds": {
390
+ "mode": "absolute",
391
+ "steps": [
392
+ {"color": "red", "value": null},
393
+ {"color": "green", "value": 1}
394
+ ]
395
+ }
396
+ },
397
+ "overrides": []
398
+ },
399
+ "gridPos": {"h": 8, "w": 8, "x": 16, "y": 33},
400
+ "id": 10,
401
+ "options": {
402
+ "colorMode": "value",
403
+ "graphMode": "area",
404
+ "justifyMode": "auto",
405
+ "orientation": "auto",
406
+ "reduceOptions": {"calcs": ["lastNotNull"], "fields": "", "values": false},
407
+ "textMode": "value_and_name"
408
+ },
409
+ "targets": [
410
+ {
411
+ "datasource": {"type": "prometheus", "uid": "${DS_PROMETHEUS}"},
412
+ "expr": "count by (kind) (lepus_process_rss_memory_bytes)",
413
+ "legendFormat": "{{kind}}",
414
+ "refId": "A"
415
+ }
416
+ ],
417
+ "title": "Processes by kind",
418
+ "type": "stat"
419
+ }
420
+ ],
421
+ "refresh": "30s",
422
+ "schemaVersion": 38,
423
+ "style": "dark",
424
+ "tags": ["lepus", "rabbitmq", "ruby"],
425
+ "templating": {
426
+ "list": [
427
+ {
428
+ "current": {"selected": false, "text": "Prometheus", "value": "Prometheus"},
429
+ "hide": 0,
430
+ "includeAll": false,
431
+ "label": "Prometheus",
432
+ "multi": false,
433
+ "name": "DS_PROMETHEUS",
434
+ "options": [],
435
+ "query": "prometheus",
436
+ "refresh": 1,
437
+ "regex": "",
438
+ "skipUrlSync": false,
439
+ "type": "datasource"
440
+ }
441
+ ]
442
+ },
443
+ "time": {"from": "now-1h", "to": "now"},
444
+ "timepicker": {},
445
+ "timezone": "",
446
+ "title": "Lepus",
447
+ "uid": "lepus-overview",
448
+ "version": 1,
449
+ "weekStart": ""
450
+ }
@@ -4,3 +4,4 @@ gemspec path: ".."
4
4
 
5
5
  gem "rails", "~> 5.2", ">= 5.2.8.1"
6
6
  gem "connection_pool", "< 3"
7
+ gem "prometheus_exporter", "= 2.1.0"
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- lepus (0.0.1.rc2)
4
+ lepus (0.1.0)
5
+ base64
5
6
  bunny
6
7
  concurrent-ruby
7
8
  multi_json
@@ -52,25 +53,26 @@ GEM
52
53
  i18n (>= 0.7, < 2)
53
54
  minitest (~> 5.1)
54
55
  tzinfo (~> 1.1)
55
- addressable (2.8.7)
56
- public_suffix (>= 2.0.2, < 7.0)
57
- amq-protocol (2.5.1)
56
+ addressable (2.9.0)
57
+ public_suffix (>= 2.0.2, < 8.0)
58
+ amq-protocol (2.7.0)
58
59
  arel (9.0.0)
59
60
  ast (2.4.3)
60
61
  base64 (0.3.0)
61
- bigdecimal (3.2.3)
62
+ bigdecimal (4.1.1)
62
63
  builder (3.3.0)
63
- bunny (2.24.0)
64
- amq-protocol (~> 2.3)
64
+ bunny (3.0.0)
65
+ amq-protocol (~> 2.7)
66
+ logger (~> 1, >= 1.7)
65
67
  sorted_set (~> 1, >= 1.0.2)
66
68
  coderay (1.1.3)
67
- concurrent-ruby (1.3.5)
69
+ concurrent-ruby (1.3.6)
68
70
  connection_pool (2.5.5)
69
- crack (1.0.0)
71
+ crack (1.0.1)
70
72
  bigdecimal
71
73
  rexml
72
74
  crass (1.0.6)
73
- date (3.4.1)
75
+ date (3.5.1)
74
76
  de-dupe (0.0.2)
75
77
  redis
76
78
  zeitwerk
@@ -80,17 +82,19 @@ GEM
80
82
  erubi (1.13.1)
81
83
  globalid (1.1.0)
82
84
  activesupport (>= 5.0)
83
- hashdiff (1.2.0)
84
- i18n (1.14.7)
85
+ hashdiff (1.2.1)
86
+ i18n (1.14.8)
85
87
  concurrent-ruby (~> 1.0)
86
- json (2.13.2)
88
+ io-console (0.8.2)
89
+ json (2.19.3)
87
90
  language_server-protocol (3.17.0.5)
88
91
  lint_roller (1.1.0)
89
92
  logger (1.7.0)
90
- loofah (2.24.1)
93
+ loofah (2.25.1)
91
94
  crass (~> 1.0.2)
92
95
  nokogiri (>= 1.12.0)
93
- mail (2.8.1)
96
+ mail (2.9.0)
97
+ logger
94
98
  mini_mime (>= 0.1.1)
95
99
  net-imap
96
100
  net-pop
@@ -98,9 +102,9 @@ GEM
98
102
  marcel (1.0.4)
99
103
  method_source (1.1.0)
100
104
  mini_mime (1.1.5)
101
- minitest (5.25.5)
105
+ minitest (5.26.1)
102
106
  multi_json (1.15.0)
103
- net-imap (0.4.22)
107
+ net-imap (0.4.23)
104
108
  date
105
109
  net-protocol
106
110
  net-pop (0.1.2)
@@ -109,20 +113,23 @@ GEM
109
113
  timeout
110
114
  net-smtp (0.5.1)
111
115
  net-protocol
112
- nio4r (2.7.4)
116
+ nio4r (2.7.5)
113
117
  nokogiri (1.15.7-x86_64-linux)
114
118
  racc (~> 1.4)
115
- parallel (1.27.0)
116
- parser (3.3.9.0)
119
+ parallel (1.28.0)
120
+ parser (3.3.11.1)
117
121
  ast (~> 2.4.1)
118
122
  racc
119
- prism (1.4.0)
120
- pry (0.15.2)
123
+ prism (1.9.0)
124
+ prometheus_exporter (2.1.0)
125
+ webrick
126
+ pry (0.16.0)
121
127
  coderay (~> 1.1)
122
128
  method_source (~> 1.0)
129
+ reline (>= 0.6.0)
123
130
  public_suffix (5.1.1)
124
131
  racc (1.8.1)
125
- rack (2.2.17)
132
+ rack (2.2.23)
126
133
  rack-test (2.2.0)
127
134
  rack (>= 1.3)
128
135
  rails (5.2.8.1)
@@ -142,8 +149,8 @@ GEM
142
149
  activesupport (>= 5.0.0)
143
150
  minitest
144
151
  nokogiri (>= 1.6)
145
- rails-html-sanitizer (1.6.2)
146
- loofah (~> 2.21)
152
+ rails-html-sanitizer (1.7.0)
153
+ loofah (~> 2.25)
147
154
  nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
148
155
  railties (5.2.8.1)
149
156
  actionpack (= 5.2.8.1)
@@ -152,47 +159,49 @@ GEM
152
159
  rake (>= 0.8.7)
153
160
  thor (>= 0.19.0, < 2.0)
154
161
  rainbow (3.1.1)
155
- rake (13.3.0)
162
+ rake (13.4.2)
156
163
  rbtree (0.4.6)
157
164
  redis (5.4.1)
158
165
  redis-client (>= 0.22.0)
159
- redis-client (0.27.0)
166
+ redis-client (0.28.0)
160
167
  connection_pool
161
- regexp_parser (2.11.2)
162
- rexml (3.4.2)
163
- rspec (3.13.1)
168
+ regexp_parser (2.12.0)
169
+ reline (0.6.3)
170
+ io-console (~> 0.5)
171
+ rexml (3.4.4)
172
+ rspec (3.13.2)
164
173
  rspec-core (~> 3.13.0)
165
174
  rspec-expectations (~> 3.13.0)
166
175
  rspec-mocks (~> 3.13.0)
167
- rspec-core (3.13.5)
176
+ rspec-core (3.13.6)
168
177
  rspec-support (~> 3.13.0)
169
178
  rspec-expectations (3.13.5)
170
179
  diff-lcs (>= 1.2.0, < 2.0)
171
180
  rspec-support (~> 3.13.0)
172
- rspec-mocks (3.13.5)
181
+ rspec-mocks (3.13.8)
173
182
  diff-lcs (>= 1.2.0, < 2.0)
174
183
  rspec-support (~> 3.13.0)
175
- rspec-support (3.13.5)
176
- rubocop (1.80.2)
184
+ rspec-support (3.13.7)
185
+ rubocop (1.86.1)
177
186
  json (~> 2.3)
178
187
  language_server-protocol (~> 3.17.0.2)
179
188
  lint_roller (~> 1.1.0)
180
- parallel (~> 1.10)
189
+ parallel (>= 1.10)
181
190
  parser (>= 3.3.0.2)
182
191
  rainbow (>= 2.2.2, < 4.0)
183
192
  regexp_parser (>= 2.9.3, < 3.0)
184
- rubocop-ast (>= 1.46.0, < 2.0)
193
+ rubocop-ast (>= 1.49.0, < 2.0)
185
194
  ruby-progressbar (~> 1.7)
186
195
  unicode-display_width (>= 2.4.0, < 4.0)
187
- rubocop-ast (1.46.0)
196
+ rubocop-ast (1.49.1)
188
197
  parser (>= 3.3.7.2)
189
- prism (~> 1.4)
198
+ prism (~> 1.7)
190
199
  rubocop-performance (1.21.1)
191
200
  rubocop (>= 1.48.1, < 2.0)
192
201
  rubocop-ast (>= 1.31.1, < 2.0)
193
- rubocop-rspec (3.7.0)
202
+ rubocop-rspec (3.9.0)
194
203
  lint_roller (~> 1.1)
195
- rubocop (~> 1.72, >= 1.72.1)
204
+ rubocop (~> 1.81)
196
205
  ruby-progressbar (1.13.0)
197
206
  simplecov (0.22.0)
198
207
  docile (~> 1.1)
@@ -222,18 +231,19 @@ GEM
222
231
  standard-performance (1.4.0)
223
232
  lint_roller (~> 1.1)
224
233
  rubocop-performance (~> 1.21.0)
225
- thor (1.4.0)
234
+ thor (1.5.0)
226
235
  thread_safe (0.3.6)
227
- timeout (0.4.3)
236
+ timeout (0.6.1)
228
237
  tzinfo (1.2.11)
229
238
  thread_safe (~> 0.1)
230
- unicode-display_width (3.1.5)
231
- unicode-emoji (~> 4.0, >= 4.0.4)
232
- unicode-emoji (4.0.4)
233
- webmock (3.25.1)
239
+ unicode-display_width (3.2.0)
240
+ unicode-emoji (~> 4.1)
241
+ unicode-emoji (4.2.0)
242
+ webmock (3.26.2)
234
243
  addressable (>= 2.8.0)
235
244
  crack (>= 0.3.2)
236
245
  hashdiff (>= 0.4.0, < 2.0.0)
246
+ webrick (1.9.2)
237
247
  websocket-driver (0.8.0)
238
248
  base64
239
249
  websocket-extensions (>= 0.1.0)
@@ -248,7 +258,10 @@ DEPENDENCIES
248
258
  de-dupe
249
259
  dotenv
250
260
  lepus!
261
+ prometheus_exporter (= 2.1.0)
251
262
  pry
263
+ rack (>= 2.2)
264
+ rack-test
252
265
  rails (~> 5.2, >= 5.2.8.1)
253
266
  rspec
254
267
  rubocop
@@ -4,3 +4,4 @@ gemspec path: ".."
4
4
 
5
5
  gem "rails", "~> 6.1", ">= 6.1.7.10"
6
6
  gem "connection_pool", "< 3"
7
+ gem "prometheus_exporter", "< 2.3"