@forgecart/flight-observability 0.202608220925.0 → 0.202608300703.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:
|
|
@@ -123,6 +123,20 @@ groups:
|
|
|
123
123
|
summary: 'Transaction p99 above 80% of TRANSACTION_TIME_BUDGET_MS'
|
|
124
124
|
description: 'p99 = {{ $value }}s vs the budget gauge — client-paced spans are drifting toward the kill window.'
|
|
125
125
|
|
|
126
|
+
- name: fc-alerts-model
|
|
127
|
+
rules:
|
|
128
|
+
# Run 32571110796's invisible class: account starvation fails live-model
|
|
129
|
+
# turns FAST behind generic fallbacks while every dashboard reads
|
|
130
|
+
# healthy — this is the loud surface. Fires on the FIRST rejection
|
|
131
|
+
# (usage limits persist for a billing window; there is no flap to damp).
|
|
132
|
+
- alert: FcModelUsageLimit
|
|
133
|
+
expr: sum(increase(fc_model_rate_limited_total{reason="usage_limit"}[10m])) > 0
|
|
134
|
+
labels:
|
|
135
|
+
severity: warning
|
|
136
|
+
annotations:
|
|
137
|
+
summary: 'Model account usage limit — live-model turns are being rejected'
|
|
138
|
+
description: 'Agent turns are failing fast on provider usage limits; resetsAt rides the agent log "Claude Code cannot serve". Live-model specs will red until the window resets or the limit is raised.'
|
|
139
|
+
|
|
126
140
|
- name: fc-alerts-probes
|
|
127
141
|
rules:
|
|
128
142
|
- alert: FcDnsProbeFailing
|
|
@@ -142,6 +156,14 @@ groups:
|
|
|
142
156
|
annotations:
|
|
143
157
|
summary: 'Oldest due-but-unsent outbox row over 120s'
|
|
144
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).'
|
|
145
167
|
|
|
146
168
|
- name: fc-alerts-doctrine
|
|
147
169
|
rules:
|
|
@@ -242,6 +242,10 @@ groups:
|
|
|
242
242
|
expr: sum by (service, target) (fc_grpc_inflight)
|
|
243
243
|
- record: fc:grpc:transient_failure_rate
|
|
244
244
|
expr: sum by (service, target) (rate(fc_grpc_transient_failure_seconds_total[5m]))
|
|
245
|
+
# Model-provider limit rejections (run 32571110796's invisible class):
|
|
246
|
+
# reasons are a bounded set by construction (deriveModelLimitReason).
|
|
247
|
+
- record: fc:model:rate_limited_rate
|
|
248
|
+
expr: sum by (reason) (rate(fc_model_rate_limited_total[5m]))
|
|
245
249
|
|
|
246
250
|
- name: fc-pgbouncer
|
|
247
251
|
interval: 15s
|
|
@@ -384,6 +388,23 @@ groups:
|
|
|
384
388
|
expr: max(pg_outbox_oldest_unsent_seconds)
|
|
385
389
|
- record: fc:outbox:backlog
|
|
386
390
|
expr: max(pg_outbox_backlog)
|
|
391
|
+
- name: fc-marketing
|
|
392
|
+
interval: 15s
|
|
393
|
+
rules:
|
|
394
|
+
# Marketing-event flush health (#1074) — pg_marketing_outbox is the
|
|
395
|
+
# WHERE-form probe (partial-index-served; never the FILTER full-scan).
|
|
396
|
+
- record: fc:marketing:backlog
|
|
397
|
+
expr: max(pg_marketing_outbox_backlog)
|
|
398
|
+
- record: fc:marketing:flush_lag_seconds
|
|
399
|
+
expr: max(pg_marketing_outbox_oldest_pending_seconds)
|
|
400
|
+
# Planned-vs-fired imbalance panel — both counters at-least-once, so
|
|
401
|
+
# panels read rate trends, never exact equality (#1074).
|
|
402
|
+
- record: fc:automation:planned_match_rate
|
|
403
|
+
expr: sum(rate(fc_automation_dispatch_matches_total[5m]))
|
|
404
|
+
- record: fc:automation:fire_rate
|
|
405
|
+
expr: sum by (outcome) (rate(fc_automation_fire_total[5m]))
|
|
406
|
+
- record: fc:automation:rule_cache_rate
|
|
407
|
+
expr: sum by (outcome) (rate(fc_automation_rule_cache_total[5m]))
|
|
387
408
|
- name: fc-workspace
|
|
388
409
|
interval: 15s
|
|
389
410
|
rules:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgecart/flight-observability",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.202608300703.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": [
|