toga-ai 1.0.619 → 1.0.620
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.
|
@@ -6,7 +6,7 @@ project: Worker
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-08-
|
|
9
|
+
updated: 2026-08-19
|
|
10
10
|
owners: [jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- worker2/Worker/Infrastructure/CloudWatch.php
|
|
@@ -28,7 +28,10 @@ OneUptime string-matches — OneUptime cannot compare numbers on a pushed body.
|
|
|
28
28
|
|
|
29
29
|
The load-bearing design decision this doc records is the **paging (alarm) criteria**: page
|
|
30
30
|
on EB `Degraded`/`Severe`, but **suppress the common "an occasional HTTP 500 tripped
|
|
31
|
-
Degraded" false alarm** unless 5xx errors actually dominate the request mix
|
|
31
|
+
Degraded/Severe" false alarm** unless 5xx errors actually dominate the request mix (by
|
|
32
|
+
share) or reach a real absolute volume. The 5xx gate applies to **both** `Degraded` and
|
|
33
|
+
`Severe`, and only when EB attributes the problem **solely** to 5xx — a mixed cause always
|
|
34
|
+
pages.
|
|
32
35
|
|
|
33
36
|
**Critical behavior:** the method is **non-fatal and never throws** — it always returns a
|
|
34
37
|
string. worker2 has **no DLQ and a 3600s SQS visibility timeout**, so any uncaught 500
|
|
@@ -53,15 +56,33 @@ itself runs non-fatal.
|
|
|
53
56
|
Per environment, `alarm=HIGH` (page) when the EB `HealthStatus` is `Degraded` **or**
|
|
54
57
|
`Severe`. `Suspended` never pages.
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
**
|
|
62
|
-
- **
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
The **5xx gate applies to both `Degraded` and `Severe`.** A non-5xx or mixed-cause
|
|
60
|
+
`Degraded`/`Severe` — and any env with no stated cause — **always pages**; the gate only
|
|
61
|
+
ever suppresses an env EB attributes **solely** to 5xx.
|
|
62
|
+
|
|
63
|
+
- **Non-5xx or mixed-cause `Degraded`/`Severe`** (latency, instances down, a failed deploy,
|
|
64
|
+
or a 5xx trickle *alongside* a real non-5xx failure) **always pages.**
|
|
65
|
+
- **Solely-5xx `Degraded`/`Severe` pages only on a genuine flood** — either:
|
|
66
|
+
- the **absolute** 5xx count in the window is at/above `HTTP_5XX_ALARM_ABSOLUTE_COUNT`
|
|
67
|
+
(default 20), **or**
|
|
68
|
+
- the **5xx share** of requests is at/above `HTTP_5XX_ALARM_RATIO` (default 0.80).
|
|
69
|
+
- **Zero requests in the window → no page** (nothing observed; also avoids divide-by-zero).
|
|
70
|
+
|
|
71
|
+
**Why the gate now covers `Severe` too:** EB escalates an environment to `Severe` precisely
|
|
72
|
+
when the 5xx share is high, so real 5xx floods reach `Severe` *first* and never touch the
|
|
73
|
+
gated `Degraded` branch. When the gate applied only to `Degraded`, the 80% threshold was
|
|
74
|
+
effectively dead — a real 50%-5xx `Severe` event paged despite the setting. Gating both
|
|
75
|
+
tiers makes the threshold actually govern.
|
|
76
|
+
|
|
77
|
+
**Why "solely" 5xx, not "any" 5xx cause:** a mixed-cause env (a 5xx trickle plus a real
|
|
78
|
+
non-5xx failure such as a failed deploy) must not be silenced by a sub-threshold ratio. The
|
|
79
|
+
ratio gate only applies when **every** stated cause references 5xx (and there is at least
|
|
80
|
+
one); anything else pages.
|
|
81
|
+
|
|
82
|
+
**Why an absolute floor in addition to the ratio:** the ratio alone is magnitude-blind —
|
|
83
|
+
60k failing out of 100k reads as 60% and would be suppressed, though it is plainly a flood.
|
|
84
|
+
`HTTP_5XX_ALARM_ABSOLUTE_COUNT` pages such an env regardless of share; tune it to the busiest
|
|
85
|
+
monitored environment's request volume.
|
|
65
86
|
|
|
66
87
|
### Fail-safe: a blind read pages, never reads healthy
|
|
67
88
|
|
|
@@ -76,18 +97,23 @@ signal — same alarm-vs-probe split as the multi-client monitors in
|
|
|
76
97
|
| Constant | Default | Meaning |
|
|
77
98
|
|---|---|---|
|
|
78
99
|
| `HEALTH_ALARM_STATUSES` | `['Degraded','Severe']` | HealthStatus values that page |
|
|
79
|
-
| `HTTP_5XX_ALARM_RATIO` | `0.80` | 5xx share (0.0–1.0) at/above which a 5xx
|
|
80
|
-
| `
|
|
100
|
+
| `HTTP_5XX_ALARM_RATIO` | `0.80` | 5xx share (0.0–1.0) at/above which a solely-5xx `Degraded`/`Severe` pages |
|
|
101
|
+
| `HTTP_5XX_ALARM_ABSOLUTE_COUNT` | `20` | Absolute 5xx count in the window at/above which a solely-5xx `Degraded`/`Severe` pages regardless of share |
|
|
81
102
|
| `HTTP_5XX_CAUSE_MARKERS` | `['5xx','http 5']` | Case-insensitive substrings identifying a 5xx-attributed EB `Cause` |
|
|
82
103
|
|
|
83
104
|
### Implementation shape
|
|
84
105
|
|
|
85
106
|
- `shouldPageForHealth(healthStatus, causes, applicationMetrics): [bool, ?float]` — returns
|
|
86
107
|
the page decision and the observed 5xx ratio.
|
|
87
|
-
- `
|
|
88
|
-
the
|
|
108
|
+
- `causesAttributeSolelyTo5xx(causes): bool` — true only when **every** EB `Cause` references
|
|
109
|
+
5xx **and there is at least one** cause. Replaces the former `causesAttributeTo5xx()`, which
|
|
110
|
+
returned true if *any* cause mentioned 5xx and so let a mixed-cause env be gated.
|
|
111
|
+
- `causeIsFivexx(cause): bool` — helper that substring-matches `HTTP_5XX_CAUSE_MARKERS`
|
|
112
|
+
against a single EB `Cause` string (case-insensitive); `causesAttributeSolelyTo5xx` requires
|
|
113
|
+
it to hold for all causes.
|
|
89
114
|
- The ratio is computed as `StatusCodes.Status5xx / RequestCount` from `ApplicationMetrics`
|
|
90
|
-
(raw counts — see below), **not** by parsing the percentage out of the `Causes` text.
|
|
115
|
+
(raw counts — see below), **not** by parsing the percentage out of the `Causes` text. The
|
|
116
|
+
absolute-count floor reads `StatusCodes.Status5xx` directly.
|
|
91
117
|
- `describeEnvironmentHealth` is called with
|
|
92
118
|
`AttributeNames = ['HealthStatus','Status','Color','Causes','ApplicationMetrics']`.
|
|
93
119
|
- Per-environment report + OneUptime payload now include the per-env `alarm` token and the
|
|
@@ -147,9 +173,10 @@ iteration:** a deploy that fails fast *without ever degrading health* is not cau
|
|
|
147
173
|
**whole run** via the outer backstop instead of paging just that region's envs as blind.
|
|
148
174
|
Candidate follow-up now that blind reads page.
|
|
149
175
|
- **No first-party test harness exists in worker2** (all tests are vendor/).
|
|
150
|
-
`shouldPageForHealth()` and `
|
|
151
|
-
(ratio at exactly 0.80; count 19 vs 20; `Severe` over a 5xx cause;
|
|
152
|
-
metrics) — deferred pending a
|
|
176
|
+
`shouldPageForHealth()` and `causesAttributeSolelyTo5xx()` are pure and ideal to unit-test
|
|
177
|
+
(ratio at exactly 0.80; absolute count 19 vs 20; `Severe` over a solely-5xx cause; a
|
|
178
|
+
mixed 5xx + non-5xx cause; empty causes; null metrics; zero requests) — deferred pending a
|
|
179
|
+
harness.
|
|
153
180
|
|
|
154
181
|
## Gotchas / known issues
|
|
155
182
|
|
|
@@ -164,8 +191,28 @@ iteration:** a deploy that fails fast *without ever degrading health* is not cau
|
|
|
164
191
|
— never parse the percentage out of `Causes`.**
|
|
165
192
|
- **`oneuptimeUrl` is a push credential** — it arrives as a cron parameter; never log it or
|
|
166
193
|
record its value in a doc.
|
|
194
|
+
- **Near-idle ratio edge (residual, accepted).** With the tiny-sample guard removed, a
|
|
195
|
+
near-idle env whose window holds a tiny all-error sample (e.g. its only request being a
|
|
196
|
+
500 = 100%) still trips the ratio and pages. Optional future guard: require a minimum 5xx
|
|
197
|
+
count before the ratio applies (the absolute floor gates high volume, not this low-volume
|
|
198
|
+
edge).
|
|
167
199
|
|
|
168
200
|
## Change history
|
|
201
|
+
- 2026-08-19 — Overhauled the 5xx alarm gating in `shouldPageForHealth()`. The 80% share
|
|
202
|
+
gate now applies to **both** `Degraded` and `Severe` (was `Degraded`-only, which left the
|
|
203
|
+
threshold dead because EB escalates real 5xx floods straight to `Severe` — a 50%-5xx
|
|
204
|
+
`Severe` had been paging despite the 0.80 setting). This Severe-gating trade-off was made
|
|
205
|
+
deliberately with an independent architecture second opinion on record (cto returned
|
|
206
|
+
DISAGREE-WITH-ALTERNATIVE; developer accepted). Narrowed 5xx classification: replaced
|
|
207
|
+
`causesAttributeTo5xx()` (any cause mentions 5xx) with `causesAttributeSolelyTo5xx()` (every
|
|
208
|
+
cause references 5xx, ≥1) + a `causeIsFivexx()` helper, so a mixed cause (5xx trickle beside
|
|
209
|
+
a real non-5xx failure) always pages — a security-review gap the Severe change would have
|
|
210
|
+
widened. Added `HTTP_5XX_ALARM_ABSOLUTE_COUNT` (20): a solely-5xx env pages regardless of
|
|
211
|
+
share once the absolute 5xx count reaches the floor (closes the ratio's magnitude-blindness,
|
|
212
|
+
e.g. 60k of 100k). Removed `HTTP_5XX_MIN_REQUEST_COUNT` (was 20) and its tiny-sample
|
|
213
|
+
page-anyway guard — a small number of 5xx is now judged purely on the ratio; below the
|
|
214
|
+
absolute floor, page only if share ≥ 0.80, and zero requests → no page. Accepted residual:
|
|
215
|
+
a near-idle env with a tiny all-error sample still trips the ratio. (jcardinal)
|
|
169
216
|
- 2026-08-17 — Created. Documented the `ElasticBeanstalkHealth` alarm/paging criteria (page
|
|
170
217
|
on `Degraded`/`Severe`; suppress a 5xx-driven `Degraded` unless the 5xx share ≥
|
|
171
218
|
`HTTP_5XX_ALARM_RATIO` 0.80 with an `HTTP_5XX_MIN_REQUEST_COUNT` 20 tiny-sample guard;
|
|
@@ -178,5 +225,3 @@ iteration:** a deploy that fails fast *without ever degrading health* is not cau
|
|
|
178
225
|
covers the reads). Recorded the reverted `['Severe']`-only + deployment-failure-detector
|
|
179
226
|
direction and the accepted residual gap (a deploy that fails without degrading health).
|
|
180
227
|
(jcardinal)
|
|
181
|
-
</content>
|
|
182
|
-
</invoke>
|
package/package.json
CHANGED