pgbus 0.9.5 → 0.9.7

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +56 -3
  3. data/app/controllers/pgbus/dead_letter_controller.rb +5 -1
  4. data/app/helpers/pgbus/application_helper.rb +8 -6
  5. data/app/views/pgbus/dashboard/_recent_failures.html.erb +1 -1
  6. data/app/views/pgbus/dashboard/_stats_cards.html.erb +1 -0
  7. data/app/views/pgbus/dead_letter/_messages_table.html.erb +33 -1
  8. data/app/views/pgbus/insights/show.html.erb +1 -1
  9. data/app/views/pgbus/jobs/_failed_table.html.erb +1 -1
  10. data/app/views/pgbus/jobs/show.html.erb +1 -1
  11. data/app/views/pgbus/queues/show.html.erb +3 -0
  12. data/config/locales/da.yml +7 -0
  13. data/config/locales/de.yml +7 -0
  14. data/config/locales/en.yml +7 -0
  15. data/config/locales/es.yml +7 -0
  16. data/config/locales/fi.yml +7 -0
  17. data/config/locales/fr.yml +7 -0
  18. data/config/locales/it.yml +7 -0
  19. data/config/locales/ja.yml +7 -0
  20. data/config/locales/nb.yml +7 -0
  21. data/config/locales/nl.yml +7 -0
  22. data/config/locales/pt.yml +7 -0
  23. data/config/locales/sv.yml +7 -0
  24. data/lib/pgbus/configuration.rb +5 -2
  25. data/lib/pgbus/integrations/appsignal/dashboard.json +353 -0
  26. data/lib/pgbus/integrations/appsignal/dashboards/pgbus_health.json +224 -85
  27. data/lib/pgbus/integrations/appsignal/dashboards/pgbus_streams.json +154 -63
  28. data/lib/pgbus/integrations/appsignal/dashboards/pgbus_throughput.json +218 -79
  29. data/lib/pgbus/integrations/appsignal/probe.rb +17 -2
  30. data/lib/pgbus/integrations/appsignal.rb +17 -0
  31. data/lib/pgbus/version.rb +1 -1
  32. data/lib/pgbus/web/data_source.rb +21 -0
  33. data/lib/pgbus/web/payload_filter.rb +68 -0
  34. metadata +3 -1
@@ -109,7 +109,8 @@ module Pgbus
109
109
  # Web dashboard
110
110
  attr_accessor :web_auth, :web_refresh_interval, :web_per_page, :web_live_updates, :web_data_source,
111
111
  :insights_default_minutes, :base_controller_class, :return_to_app_url,
112
- :metrics_enabled
112
+ :metrics_enabled,
113
+ :dashboard_filter_parameters, :dashboard_filter_sensitive
113
114
 
114
115
  # Streams (turbo-rails replacement, SSE-based)
115
116
  attr_accessor :streams_enabled, :streams_path, :streams_queue_prefix, :streams_signed_name_secret,
@@ -216,10 +217,12 @@ module Pgbus
216
217
  @web_per_page = 25
217
218
  @web_live_updates = true
218
219
  @web_data_source = nil
219
- @insights_default_minutes = 30 * 24 * 60 # 30 days
220
+ @insights_default_minutes = 60 # 1 hour
220
221
  @base_controller_class = "::ActionController::Base"
221
222
  @return_to_app_url = nil
222
223
  @metrics_enabled = true
224
+ @dashboard_filter_parameters = nil # nil = auto-detect from Rails, then fall back to defaults
225
+ @dashboard_filter_sensitive = true
223
226
 
224
227
  @streams_enabled = true
225
228
  @streams_path = nil
@@ -0,0 +1,353 @@
1
+ {
2
+ "metric_keys": [
3
+ "pgbus_queue_job_count"
4
+ ],
5
+ "dashboard": {
6
+ "title": "Pgbus",
7
+ "description": "PostgreSQL-native job processing and event bus built on PGMQ.\nMonitor job throughput, queue depth, latency, dead letter queues,\nworker processes, event handlers, and stream broadcasts.\n",
8
+ "visuals": [
9
+ {
10
+ "type": "timeseries",
11
+ "display": "LINE",
12
+ "title": "Job status per queue",
13
+ "description": "Processed, failed, and dead-lettered jobs per queue.",
14
+ "line_label": "%queue% - %status%",
15
+ "format": "number",
16
+ "draw_null_as_zero": true,
17
+ "metrics": [
18
+ {
19
+ "name": "pgbus_queue_job_count",
20
+ "fields": [
21
+ {
22
+ "field": "COUNTER"
23
+ }
24
+ ],
25
+ "tags": [
26
+ {
27
+ "key": "queue",
28
+ "value": "*"
29
+ },
30
+ {
31
+ "key": "status",
32
+ "value": "*"
33
+ }
34
+ ]
35
+ }
36
+ ]
37
+ },
38
+ {
39
+ "type": "timeseries",
40
+ "display": "LINE",
41
+ "title": "Throughput per job class",
42
+ "description": "Number of jobs executed per job class.",
43
+ "line_label": "%namespace% - %action%",
44
+ "format": "number",
45
+ "draw_null_as_zero": true,
46
+ "metrics": [
47
+ {
48
+ "name": "transaction_duration",
49
+ "fields": [
50
+ {
51
+ "field": "count"
52
+ }
53
+ ],
54
+ "tags": [
55
+ {
56
+ "key": "namespace",
57
+ "value": "background"
58
+ },
59
+ {
60
+ "key": "action",
61
+ "value": "*"
62
+ }
63
+ ]
64
+ }
65
+ ]
66
+ },
67
+ {
68
+ "type": "timeseries",
69
+ "display": "LINE",
70
+ "title": "Duration per job class",
71
+ "description": "Mean execution time per job class.",
72
+ "line_label": "%namespace% - %action%",
73
+ "format": "duration",
74
+ "draw_null_as_zero": true,
75
+ "metrics": [
76
+ {
77
+ "name": "transaction_duration",
78
+ "fields": [
79
+ {
80
+ "field": "mean"
81
+ }
82
+ ],
83
+ "tags": [
84
+ {
85
+ "key": "namespace",
86
+ "value": "background"
87
+ },
88
+ {
89
+ "key": "action",
90
+ "value": "*"
91
+ }
92
+ ]
93
+ }
94
+ ]
95
+ },
96
+ {
97
+ "type": "timeseries",
98
+ "display": "LINE",
99
+ "title": "Queue depth",
100
+ "description": "Total messages waiting in each queue.",
101
+ "line_label": "%queue%",
102
+ "format": "number",
103
+ "draw_null_as_zero": true,
104
+ "metrics": [
105
+ {
106
+ "name": "pgbus_queue_depth",
107
+ "fields": [
108
+ {
109
+ "field": "gauge"
110
+ }
111
+ ],
112
+ "tags": [
113
+ {
114
+ "key": "queue",
115
+ "value": "*"
116
+ }
117
+ ]
118
+ }
119
+ ]
120
+ },
121
+ {
122
+ "type": "timeseries",
123
+ "display": "LINE",
124
+ "title": "Queue latency",
125
+ "description": "Age of the oldest message in each queue (milliseconds). High latency means consumers can't keep up.",
126
+ "line_label": "%queue%",
127
+ "format": "duration",
128
+ "draw_null_as_zero": true,
129
+ "metrics": [
130
+ {
131
+ "name": "pgbus_queue_latency",
132
+ "fields": [
133
+ {
134
+ "field": "gauge"
135
+ }
136
+ ],
137
+ "tags": [
138
+ {
139
+ "key": "queue",
140
+ "value": "*"
141
+ }
142
+ ]
143
+ }
144
+ ]
145
+ },
146
+ {
147
+ "type": "timeseries",
148
+ "display": "LINE",
149
+ "title": "Dead letter queue depth",
150
+ "description": "Messages that exceeded max retries and were routed to the DLQ.",
151
+ "line_label": "DLQ depth",
152
+ "format": "number",
153
+ "draw_null_as_zero": true,
154
+ "metrics": [
155
+ {
156
+ "name": "pgbus_dlq_depth",
157
+ "fields": [
158
+ {
159
+ "field": "gauge"
160
+ }
161
+ ],
162
+ "tags": []
163
+ }
164
+ ]
165
+ },
166
+ {
167
+ "type": "timeseries",
168
+ "display": "LINE",
169
+ "title": "Worker / Process count",
170
+ "description": "Active pgbus supervisor processes per host.",
171
+ "line_label": "%hostname%",
172
+ "format": "number",
173
+ "draw_null_as_zero": true,
174
+ "metrics": [
175
+ {
176
+ "name": "pgbus_active_processes",
177
+ "fields": [
178
+ {
179
+ "field": "gauge"
180
+ }
181
+ ],
182
+ "tags": [
183
+ {
184
+ "key": "hostname",
185
+ "value": "*"
186
+ }
187
+ ]
188
+ }
189
+ ]
190
+ },
191
+ {
192
+ "type": "timeseries",
193
+ "display": "LINE",
194
+ "title": "Messages sent / read",
195
+ "description": "PGMQ message throughput: enqueue and dequeue rates.",
196
+ "line_label": "%name% - %queue%",
197
+ "format": "number",
198
+ "draw_null_as_zero": true,
199
+ "metrics": [
200
+ {
201
+ "name": "pgbus_messages_sent",
202
+ "fields": [
203
+ {
204
+ "field": "COUNTER"
205
+ }
206
+ ],
207
+ "tags": [
208
+ {
209
+ "key": "queue",
210
+ "value": "*"
211
+ }
212
+ ]
213
+ },
214
+ {
215
+ "name": "pgbus_messages_read",
216
+ "fields": [
217
+ {
218
+ "field": "COUNTER"
219
+ }
220
+ ],
221
+ "tags": [
222
+ {
223
+ "key": "queue",
224
+ "value": "*"
225
+ }
226
+ ]
227
+ }
228
+ ]
229
+ },
230
+ {
231
+ "type": "timeseries",
232
+ "display": "LINE",
233
+ "title": "Event handler status",
234
+ "description": "Processed and failed event handler invocations.",
235
+ "line_label": "%handler% - %status%",
236
+ "format": "number",
237
+ "draw_null_as_zero": true,
238
+ "metrics": [
239
+ {
240
+ "name": "pgbus_event_count",
241
+ "fields": [
242
+ {
243
+ "field": "COUNTER"
244
+ }
245
+ ],
246
+ "tags": [
247
+ {
248
+ "key": "handler",
249
+ "value": "*"
250
+ },
251
+ {
252
+ "key": "status",
253
+ "value": "*"
254
+ }
255
+ ]
256
+ }
257
+ ]
258
+ },
259
+ {
260
+ "type": "timeseries",
261
+ "display": "LINE",
262
+ "title": "Worker recycling",
263
+ "description": "Worker recycle events by reason (max_jobs, max_memory, max_lifetime).",
264
+ "line_label": "%reason%",
265
+ "format": "number",
266
+ "draw_null_as_zero": true,
267
+ "metrics": [
268
+ {
269
+ "name": "pgbus_worker_recycled",
270
+ "fields": [
271
+ {
272
+ "field": "COUNTER"
273
+ }
274
+ ],
275
+ "tags": [
276
+ {
277
+ "key": "reason",
278
+ "value": "*"
279
+ }
280
+ ]
281
+ }
282
+ ]
283
+ },
284
+ {
285
+ "type": "timeseries",
286
+ "display": "LINE",
287
+ "title": "Database health",
288
+ "description": "Dead tuples, tables needing vacuum, and oldest transaction age — indicators of MVCC pressure on queue tables.",
289
+ "line_label": "%name%",
290
+ "format": "number",
291
+ "draw_null_as_zero": true,
292
+ "metrics": [
293
+ {
294
+ "name": "pgbus_total_dead_tuples",
295
+ "fields": [
296
+ {
297
+ "field": "gauge"
298
+ }
299
+ ],
300
+ "tags": []
301
+ },
302
+ {
303
+ "name": "pgbus_tables_needing_vacuum",
304
+ "fields": [
305
+ {
306
+ "field": "gauge"
307
+ }
308
+ ],
309
+ "tags": []
310
+ },
311
+ {
312
+ "name": "pgbus_oldest_transaction_age_seconds",
313
+ "fields": [
314
+ {
315
+ "field": "gauge"
316
+ }
317
+ ],
318
+ "tags": []
319
+ }
320
+ ]
321
+ },
322
+ {
323
+ "type": "timeseries",
324
+ "display": "LINE",
325
+ "title": "Stream broadcasts",
326
+ "description": "Turbo Stream broadcast count and active SSE connections.",
327
+ "line_label": "%name%",
328
+ "format": "number",
329
+ "draw_null_as_zero": true,
330
+ "metrics": [
331
+ {
332
+ "name": "pgbus_stream_broadcasts_60m",
333
+ "fields": [
334
+ {
335
+ "field": "gauge"
336
+ }
337
+ ],
338
+ "tags": []
339
+ },
340
+ {
341
+ "name": "pgbus_stream_active_connections",
342
+ "fields": [
343
+ {
344
+ "field": "gauge"
345
+ }
346
+ ],
347
+ "tags": []
348
+ }
349
+ ]
350
+ }
351
+ ]
352
+ }
353
+ }