@forgecart/flight-observability 0.202608221935.0 → 0.202609190800.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.
|
@@ -25,6 +25,42 @@ pg_idle_in_tx:
|
|
|
25
25
|
usage: GAUGE
|
|
26
26
|
description: Number of idle-in-transaction backends
|
|
27
27
|
|
|
28
|
+
# Attribution for the FcIdleInTxAge class (run 32930565055 forensics: a 9.7min
|
|
29
|
+
# idle-in-tx squatter blocked a scope boot and nothing named the owner). Top-1
|
|
30
|
+
# oldest idle-in-tx session WITH identity labels. Cardinality is safe by
|
|
31
|
+
# construction: zero rows — and therefore ZERO series — whenever no squatter
|
|
32
|
+
# exists; during an incident exactly one label tuple lives for the session's
|
|
33
|
+
# lifetime. query_head is whitespace-collapsed and truncated so a label value
|
|
34
|
+
# can never carry a full statement.
|
|
35
|
+
pg_idle_in_tx_top:
|
|
36
|
+
query: >-
|
|
37
|
+
SELECT
|
|
38
|
+
COALESCE(datname, '') AS datname,
|
|
39
|
+
COALESCE(usename, '') AS usename,
|
|
40
|
+
COALESCE(application_name, '') AS application_name,
|
|
41
|
+
COALESCE(left(regexp_replace(query, '\s+', ' ', 'g'), 60), '') AS query_head,
|
|
42
|
+
EXTRACT(EPOCH FROM (now() - xact_start))::float AS age_seconds
|
|
43
|
+
FROM pg_stat_activity
|
|
44
|
+
WHERE backend_type = 'client backend' AND state = 'idle in transaction'
|
|
45
|
+
ORDER BY xact_start ASC
|
|
46
|
+
LIMIT 1
|
|
47
|
+
metrics:
|
|
48
|
+
- datname:
|
|
49
|
+
usage: LABEL
|
|
50
|
+
description: Database of the oldest idle-in-transaction session
|
|
51
|
+
- usename:
|
|
52
|
+
usage: LABEL
|
|
53
|
+
description: Role of the oldest idle-in-transaction session
|
|
54
|
+
- application_name:
|
|
55
|
+
usage: LABEL
|
|
56
|
+
description: application_name of the oldest idle-in-transaction session
|
|
57
|
+
- query_head:
|
|
58
|
+
usage: LABEL
|
|
59
|
+
description: First 60 chars of the session's last statement (whitespace-collapsed)
|
|
60
|
+
- age_seconds:
|
|
61
|
+
usage: GAUGE
|
|
62
|
+
description: Age of the oldest idle-in-transaction session (seconds)
|
|
63
|
+
|
|
28
64
|
pg_citus_backends:
|
|
29
65
|
query: >-
|
|
30
66
|
SELECT
|
|
@@ -62,3 +98,25 @@ pg_outbox:
|
|
|
62
98
|
- oldest_unsent_seconds:
|
|
63
99
|
usage: GAUGE
|
|
64
100
|
description: Age of the oldest due-but-unsent outbox row (seconds)
|
|
101
|
+
|
|
102
|
+
# Marketing-event flush health (#1074) — the sensor run 32584944772 lacked: a
|
|
103
|
+
# batch consumed with zero dispatch was invisible. WHERE-form ON PURPOSE, not
|
|
104
|
+
# pg_outbox's FILTER shape: FILTER predicates are evaluated at the aggregate
|
|
105
|
+
# node over an unqualified scan, so on the unreaped firehose table every
|
|
106
|
+
# scrape would seq-scan ALL rows; the WHERE form is served by the partial
|
|
107
|
+
# index IDX_marketing_event_outbox_unflushed and stays O(backlog) — the 097
|
|
108
|
+
# shop_outbox_metrics() precedent. Column names quoted (TypeORM camelCase).
|
|
109
|
+
pg_marketing_outbox:
|
|
110
|
+
query: >-
|
|
111
|
+
SELECT
|
|
112
|
+
count(*)::float AS backlog,
|
|
113
|
+
COALESCE(EXTRACT(EPOCH FROM (now() - min("ingestedAt"))), 0)::float AS oldest_pending_seconds
|
|
114
|
+
FROM marketing_event_outbox
|
|
115
|
+
WHERE "flushedAt" IS NULL
|
|
116
|
+
metrics:
|
|
117
|
+
- backlog:
|
|
118
|
+
usage: GAUGE
|
|
119
|
+
description: Pending (unflushed) marketing-event outbox rows
|
|
120
|
+
- oldest_pending_seconds:
|
|
121
|
+
usage: GAUGE
|
|
122
|
+
description: Age of the oldest pending marketing-event outbox row (seconds)
|
package/dist/rules/fc-alerts.yml
CHANGED
|
@@ -54,7 +54,7 @@ groups:
|
|
|
54
54
|
severity: warning
|
|
55
55
|
annotations:
|
|
56
56
|
summary: 'Idle-in-transaction backend older than 120s'
|
|
57
|
-
description: 'Oldest idle-in-tx = {{ $value }}s — a held-open transaction pins a real coordinator connection through the pooler (tech-debt #10).'
|
|
57
|
+
description: 'Oldest idle-in-tx = {{ $value }}s — a held-open transaction pins a real coordinator connection through the pooler (tech-debt #10). Owner: db={{ with query "topk(1, pg_idle_in_tx_top_age_seconds)" }}{{ . | first | label "datname" }} user={{ . | first | label "usename" }} app={{ . | first | label "application_name" }} q="{{ . | first | label "query_head" }}"{{ end }}'
|
|
58
58
|
|
|
59
59
|
- name: fc-alerts-pooler
|
|
60
60
|
rules:
|
|
@@ -156,6 +156,14 @@ groups:
|
|
|
156
156
|
annotations:
|
|
157
157
|
summary: 'Oldest due-but-unsent outbox row over 120s'
|
|
158
158
|
description: 'oldest = {{ $value }}s, backlog = {{ with query "fc:outbox:backlog" }}{{ . | first | value }}{{ end }} — the relay is stalled or the broker is refusing publishes.'
|
|
159
|
+
- alert: FcMarketingFlushLag
|
|
160
|
+
expr: fc:marketing:flush_lag_seconds > 60
|
|
161
|
+
for: 5m
|
|
162
|
+
labels:
|
|
163
|
+
severity: warning
|
|
164
|
+
annotations:
|
|
165
|
+
summary: 'Oldest pending marketing-event outbox row over 60s'
|
|
166
|
+
description: 'oldest = {{ $value }}s, backlog = {{ with query "fc:marketing:backlog" }}{{ . | first | value }}{{ end }} — flush workers stalled, claim starvation, or every claimer erroring (#1074).'
|
|
159
167
|
|
|
160
168
|
- name: fc-alerts-doctrine
|
|
161
169
|
rules:
|
|
@@ -224,6 +224,12 @@ groups:
|
|
|
224
224
|
# F4: the REAL effective prefetch — the HOL-utilisation divisor.
|
|
225
225
|
- record: fc:mq:prefetch_effective
|
|
226
226
|
expr: max by (service) (fc_mq_prefetch_effective)
|
|
227
|
+
# #1172: AMQP liveness per service — min, so ANY disconnected replica
|
|
228
|
+
# drags the series to 0 (the loud direction). The cause line under an
|
|
229
|
+
# outbox mute: eligible depth climbing at 0 = genuine broker mute;
|
|
230
|
+
# climbing at 1 = a claim/delivery defect.
|
|
231
|
+
- record: fc:mq:connected
|
|
232
|
+
expr: min by (service) (fc_mq_connected)
|
|
227
233
|
# The register-trigger meter (debt #3 ≥1k, debt #2/Kafka ≥5-10k): the
|
|
228
234
|
# 1k/5k reference lines live on the dashboard panel.
|
|
229
235
|
- record: fc:ingest:events_per_second
|
|
@@ -240,6 +246,16 @@ groups:
|
|
|
240
246
|
expr: max by (service, target) (fc_grpc_ready)
|
|
241
247
|
- record: fc:grpc:inflight
|
|
242
248
|
expr: sum by (service, target) (fc_grpc_inflight)
|
|
249
|
+
# Ads gateway closure (#933, register #10): staleness/lag/depth gauges + the
|
|
250
|
+
# re-auth counter rate — bounded provider label by construction.
|
|
251
|
+
- record: fc:ads:spend_sync_staleness_seconds
|
|
252
|
+
expr: max by (service, provider) (fc_ads_spend_sync_staleness_seconds)
|
|
253
|
+
- record: fc:ads:audience_watermark_lag_seconds
|
|
254
|
+
expr: max by (service, provider) (fc_ads_audience_watermark_lag_seconds)
|
|
255
|
+
- record: fc:ads:conversion_dlq_depth
|
|
256
|
+
expr: max by (service) (fc_ads_conversion_dlq_depth)
|
|
257
|
+
- record: fc:ads:token_refresh_failure_rate
|
|
258
|
+
expr: sum by (provider, reason) (rate(fc_ads_token_refresh_failures_total[5m]))
|
|
243
259
|
- record: fc:grpc:transient_failure_rate
|
|
244
260
|
expr: sum by (service, target) (rate(fc_grpc_transient_failure_seconds_total[5m]))
|
|
245
261
|
# Model-provider limit rejections (run 32571110796's invisible class):
|
|
@@ -388,6 +404,40 @@ groups:
|
|
|
388
404
|
expr: max(pg_outbox_oldest_unsent_seconds)
|
|
389
405
|
- record: fc:outbox:backlog
|
|
390
406
|
expr: max(pg_outbox_backlog)
|
|
407
|
+
# #1172: the relay's own lane-scoped census — the ELIGIBILITY-AWARE
|
|
408
|
+
# truth. The pg_outbox_* pair above is eligibility-blind by construction
|
|
409
|
+
# (it counts future-dated re-arm slots and foreign-prefix CI orphans,
|
|
410
|
+
# and ages rows from birth — the 2026-08-29 false "hard-mute"): keep it
|
|
411
|
+
# for exporter parity, but alert predicates belong on THESE series.
|
|
412
|
+
- record: fc:outbox:eligible_depth
|
|
413
|
+
expr: max by (service) (fc_outbox_eligible_depth)
|
|
414
|
+
- record: fc:outbox:scheduled_depth
|
|
415
|
+
expr: max by (service) (fc_outbox_scheduled_depth)
|
|
416
|
+
- record: fc:outbox:retrying_depth
|
|
417
|
+
expr: max by (service) (fc_outbox_retrying_depth)
|
|
418
|
+
- record: fc:outbox:dead_depth
|
|
419
|
+
expr: max by (service) (fc_outbox_dead_depth)
|
|
420
|
+
- record: fc:outbox:oldest_eligible_seconds
|
|
421
|
+
expr: max by (service) (fc_outbox_oldest_eligible_seconds)
|
|
422
|
+
- record: fc:outbox:dead_lettered_rate
|
|
423
|
+
expr: sum by (service) (rate(fc_outbox_dead_lettered_total[5m]))
|
|
424
|
+
- name: fc-marketing
|
|
425
|
+
interval: 15s
|
|
426
|
+
rules:
|
|
427
|
+
# Marketing-event flush health (#1074) — pg_marketing_outbox is the
|
|
428
|
+
# WHERE-form probe (partial-index-served; never the FILTER full-scan).
|
|
429
|
+
- record: fc:marketing:backlog
|
|
430
|
+
expr: max(pg_marketing_outbox_backlog)
|
|
431
|
+
- record: fc:marketing:flush_lag_seconds
|
|
432
|
+
expr: max(pg_marketing_outbox_oldest_pending_seconds)
|
|
433
|
+
# Planned-vs-fired imbalance panel — both counters at-least-once, so
|
|
434
|
+
# panels read rate trends, never exact equality (#1074).
|
|
435
|
+
- record: fc:automation:planned_match_rate
|
|
436
|
+
expr: sum(rate(fc_automation_dispatch_matches_total[5m]))
|
|
437
|
+
- record: fc:automation:fire_rate
|
|
438
|
+
expr: sum by (outcome) (rate(fc_automation_fire_total[5m]))
|
|
439
|
+
- record: fc:automation:rule_cache_rate
|
|
440
|
+
expr: sum by (outcome) (rate(fc_automation_rule_cache_total[5m]))
|
|
391
441
|
- name: fc-workspace
|
|
392
442
|
interval: 15s
|
|
393
443
|
rules:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgecart/flight-observability",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.202609190800.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Flight Deck dashboards, fc: recording/alert rules, and the pg-custom-queries contract — the version-pinned sync artifact between shop-beta and forgecart/cloud (launch#46 P4).",
|
|
6
6
|
"files": [
|