pgbus 0.9.5 → 0.9.6

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,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
+ }
@@ -1,87 +1,226 @@
1
1
  {
2
- "title": "Pgbus — Health",
3
- "description": "Backlog, dead-letter activity, dead-tuple growth, and MVCC horizon. The 'should I page someone?' dashboard.",
4
- "graphs": [
5
- {
6
- "title": "Queue depth (visible vs total)",
7
- "description": "Visible depth excludes messages whose VT hasn't expired. A divergence between the two means workers are slow but the queue isn't growing.",
8
- "line_label": "%queue",
9
- "format": "number",
10
- "kind": "timeseries",
11
- "metrics": [
12
- { "name": "pgbus_queue_depth", "fields": ["GAUGE"], "tags": [] },
13
- { "name": "pgbus_queue_visible_depth", "fields": ["GAUGE"], "tags": [] }
14
- ]
15
- },
16
- {
17
- "title": "Oldest message age (seconds)",
18
- "description": "Per-queue head-of-line waiting time. If this climbs while queue depth stays flat, a single poison message is stuck in the VT loop.",
19
- "line_label": "%queue",
20
- "format": "duration",
21
- "format_input": "second",
22
- "kind": "timeseries",
23
- "metrics": [
24
- { "name": "pgbus_queue_oldest_message_age_seconds", "fields": ["GAUGE"], "tags": [] }
25
- ]
26
- },
27
- {
28
- "title": "DLQ depth + failed events",
29
- "description": "Messages that exceeded max_retries plus the failed-events table. Spikes after a deploy point at a regression.",
30
- "format": "number",
31
- "kind": "timeseries",
32
- "metrics": [
33
- { "name": "pgbus_dlq_depth", "fields": ["GAUGE"], "tags": [] },
34
- { "name": "pgbus_failed_events_total", "fields": ["GAUGE"], "tags": [] }
35
- ]
36
- },
37
- {
38
- "title": "Dead-lettered jobs per minute",
39
- "line_label": "%queue %job_class",
40
- "format": "number",
41
- "kind": "timeseries",
42
- "draw_null_as_zero": true,
43
- "metrics": [
44
- { "name": "pgbus_queue_job_count", "fields": ["COUNTER"], "tags": [{ "key": "status", "value": "dead_lettered" }] }
45
- ]
46
- },
47
- {
48
- "title": "Active processes",
49
- "description": "Workers + dispatcher + scheduler currently heartbeating into pgbus_processes.",
50
- "format": "number",
51
- "kind": "timeseries",
52
- "metrics": [
53
- { "name": "pgbus_active_processes", "fields": ["GAUGE"], "tags": [] }
54
- ]
55
- },
56
- {
57
- "title": "Dead tuples in queue/archive tables",
58
- "description": "If autovacuum can't keep up the index gets bloated and lock acquisition slows. Tune autovacuum_vacuum_scale_factor on the offending tables when this climbs.",
59
- "format": "number",
60
- "kind": "timeseries",
61
- "metrics": [
62
- { "name": "pgbus_total_dead_tuples", "fields": ["GAUGE"], "tags": [] }
63
- ]
64
- },
65
- {
66
- "title": "Oldest open transaction (seconds)",
67
- "description": "MVCC horizon pin. Long-running transactions prevent VACUUM from cleaning the dead tuples above. Anything over 60s is a smell.",
68
- "format": "duration",
69
- "format_input": "second",
70
- "kind": "timeseries",
71
- "metrics": [
72
- { "name": "pgbus_oldest_transaction_age_seconds", "fields": ["GAUGE"], "tags": [] }
73
- ]
74
- },
75
- {
76
- "title": "Worker recycles per minute",
77
- "description": "Recycles by reason. Steady max_jobs is healthy; spiking max_memory means you have a leak.",
78
- "line_label": "%reason",
79
- "format": "number",
80
- "kind": "timeseries",
81
- "draw_null_as_zero": true,
82
- "metrics": [
83
- { "name": "pgbus_worker_recycled", "fields": ["COUNTER"], "tags": [] }
84
- ]
85
- }
86
- ]
2
+ "metric_keys": [
3
+ "pgbus_queue_depth"
4
+ ],
5
+ "dashboard": {
6
+ "title": "Pgbus Health",
7
+ "description": "Backlog, dead-letter activity, dead-tuple growth, and MVCC horizon.\nThe 'should I page someone?' dashboard.\n",
8
+ "visuals": [
9
+ {
10
+ "type": "timeseries",
11
+ "display": "LINE",
12
+ "title": "Queue depth (visible vs total)",
13
+ "description": "Visible depth excludes messages whose VT hasn't expired. A divergence between the two means workers are slow but the queue isn't growing.",
14
+ "line_label": "%name% - %queue%",
15
+ "format": "number",
16
+ "draw_null_as_zero": true,
17
+ "metrics": [
18
+ {
19
+ "name": "pgbus_queue_depth",
20
+ "fields": [
21
+ {
22
+ "field": "GAUGE"
23
+ }
24
+ ],
25
+ "tags": [
26
+ {
27
+ "key": "queue",
28
+ "value": "*"
29
+ }
30
+ ]
31
+ },
32
+ {
33
+ "name": "pgbus_queue_visible_depth",
34
+ "fields": [
35
+ {
36
+ "field": "GAUGE"
37
+ }
38
+ ],
39
+ "tags": [
40
+ {
41
+ "key": "queue",
42
+ "value": "*"
43
+ }
44
+ ]
45
+ }
46
+ ]
47
+ },
48
+ {
49
+ "type": "timeseries",
50
+ "display": "LINE",
51
+ "title": "Queue latency",
52
+ "description": "Age of the oldest message per queue (milliseconds). High latency means consumers can't keep up.",
53
+ "line_label": "%queue%",
54
+ "format": "duration",
55
+ "draw_null_as_zero": true,
56
+ "metrics": [
57
+ {
58
+ "name": "pgbus_queue_latency",
59
+ "fields": [
60
+ {
61
+ "field": "GAUGE"
62
+ }
63
+ ],
64
+ "tags": [
65
+ {
66
+ "key": "queue",
67
+ "value": "*"
68
+ }
69
+ ]
70
+ }
71
+ ]
72
+ },
73
+ {
74
+ "type": "timeseries",
75
+ "display": "LINE",
76
+ "title": "DLQ depth + failed events",
77
+ "description": "Messages that exceeded max_retries plus the failed-events table. Spikes after a deploy point at a regression.",
78
+ "line_label": "%name%",
79
+ "format": "number",
80
+ "draw_null_as_zero": true,
81
+ "metrics": [
82
+ {
83
+ "name": "pgbus_dlq_depth",
84
+ "fields": [
85
+ {
86
+ "field": "GAUGE"
87
+ }
88
+ ],
89
+ "tags": []
90
+ },
91
+ {
92
+ "name": "pgbus_failed_events_total",
93
+ "fields": [
94
+ {
95
+ "field": "GAUGE"
96
+ }
97
+ ],
98
+ "tags": []
99
+ }
100
+ ]
101
+ },
102
+ {
103
+ "type": "timeseries",
104
+ "display": "LINE",
105
+ "title": "Dead-lettered jobs per minute",
106
+ "line_label": "%queue% - %job_class%",
107
+ "format": "number",
108
+ "draw_null_as_zero": true,
109
+ "metrics": [
110
+ {
111
+ "name": "pgbus_queue_job_count",
112
+ "fields": [
113
+ {
114
+ "field": "COUNTER"
115
+ }
116
+ ],
117
+ "tags": [
118
+ {
119
+ "key": "status",
120
+ "value": "dead_lettered"
121
+ },
122
+ {
123
+ "key": "queue",
124
+ "value": "*"
125
+ },
126
+ {
127
+ "key": "job_class",
128
+ "value": "*"
129
+ }
130
+ ]
131
+ }
132
+ ]
133
+ },
134
+ {
135
+ "type": "timeseries",
136
+ "display": "LINE",
137
+ "title": "Active processes",
138
+ "description": "Workers + dispatcher + scheduler currently heartbeating, scoped per host.",
139
+ "line_label": "%hostname%",
140
+ "format": "number",
141
+ "draw_null_as_zero": true,
142
+ "metrics": [
143
+ {
144
+ "name": "pgbus_active_processes",
145
+ "fields": [
146
+ {
147
+ "field": "GAUGE"
148
+ }
149
+ ],
150
+ "tags": [
151
+ {
152
+ "key": "hostname",
153
+ "value": "*"
154
+ }
155
+ ]
156
+ }
157
+ ]
158
+ },
159
+ {
160
+ "type": "timeseries",
161
+ "display": "LINE",
162
+ "title": "Dead tuples in queue/archive tables",
163
+ "description": "If autovacuum can't keep up the index gets bloated and lock acquisition slows. Tune autovacuum_vacuum_scale_factor on the offending tables when this climbs.",
164
+ "line_label": "Dead tuples",
165
+ "format": "number",
166
+ "draw_null_as_zero": true,
167
+ "metrics": [
168
+ {
169
+ "name": "pgbus_total_dead_tuples",
170
+ "fields": [
171
+ {
172
+ "field": "GAUGE"
173
+ }
174
+ ],
175
+ "tags": []
176
+ }
177
+ ]
178
+ },
179
+ {
180
+ "type": "timeseries",
181
+ "display": "LINE",
182
+ "title": "Oldest open transaction (seconds)",
183
+ "description": "MVCC horizon pin. Long-running transactions prevent VACUUM from cleaning the dead tuples above. Anything over 60s is a smell.",
184
+ "line_label": "Oldest transaction",
185
+ "format": "duration",
186
+ "draw_null_as_zero": true,
187
+ "metrics": [
188
+ {
189
+ "name": "pgbus_oldest_transaction_age_seconds",
190
+ "fields": [
191
+ {
192
+ "field": "GAUGE"
193
+ }
194
+ ],
195
+ "tags": []
196
+ }
197
+ ]
198
+ },
199
+ {
200
+ "type": "timeseries",
201
+ "display": "LINE",
202
+ "title": "Worker recycles per minute",
203
+ "description": "Recycles by reason. Steady max_jobs is healthy; spiking max_memory means you have a leak.",
204
+ "line_label": "%reason%",
205
+ "format": "number",
206
+ "draw_null_as_zero": true,
207
+ "metrics": [
208
+ {
209
+ "name": "pgbus_worker_recycled",
210
+ "fields": [
211
+ {
212
+ "field": "COUNTER"
213
+ }
214
+ ],
215
+ "tags": [
216
+ {
217
+ "key": "reason",
218
+ "value": "*"
219
+ }
220
+ ]
221
+ }
222
+ ]
223
+ }
224
+ ]
225
+ }
87
226
  }