An alert is a decision to draw attention to observed or imminent impact. A supported failure fraction can indicate that requests are failing; it does not identify the mechanism. A database warning may be a clue, an intermediate effect or unrelated noise. Keep the symptom, possible explanations and evidence needed to distinguish those explanations separate.
The local policy uses already adjacent equal-duration windows, each with request counts, error counts and a coverage flag. It asks three questions in order: was the population observed, is support large enough, and does the failure fraction meet the threshold? A sustained breach increments a streak. This is an executable policy model, not a deployed rule or notification system.
Threshold equality counts as a breach here: one failure out of twenty requests meets a 5% threshold. With two required consecutive windows, the first breach is pending and the second is firing. A supported good window resets the streak. An unavailable window reports unknown and also resets continuity; it does not prove recovery. Low volume reports insufficient support while retaining a defined ratio, such as 1/1, so the observation remains visible.
streak = 0
for total, errors in [(20, 1), (20, 1), (20, 0)]:
streak = streak + 1 if errors / total >= .05 else 0
print(streak)Actual alert choices also depend on service objectives, user impact, urgency and who can take a useful action. A capacity signal may warn about imminent trouble before a failure ratio rises. Neither “page on every internal error” nor “ignore all cause-oriented signals” is a universal policy. This build teaches one precise rule so boundaries can be tested; it does not choose a production error budget, paging route or escalation agreement.
Triage starts by checking scope and signal validity: which service, interval, population and collection coverage? Compare retained examples and related signals, then choose a discriminating observation. A trace can show whether a slow dependency lies on relevant work; a deployment comparison can test whether failures precede the change. Correlation supports a hypothesis but remains weaker than a demonstrated mechanism.
Sharing evidence introduces another boundary. Our redactor copies a finite JSON-like tree and replaces values under an exact case-insensitive secret-key vocabulary. The original retained fixture stays unchanged. Recursive copying matters because a shallow dictionary copy still aliases nested lists and dictionaries. Validation also covers values below secret keys: an unsupported object should not silently become an accepted input merely because its field will be hidden.
This narrow policy is intentionally incomplete. A message can contain an unclassified token, an unknown field can contain personal information, and identifiers can themselves be sensitive. Key-based masking does not guarantee a publishable incident report. Use the explicit limitations and apply context-specific review before real sharing.
The exercises cover missing data, small denominators, threshold ties and nested mixed-case keys. Success demonstrates deterministic local analysis and careful context handling. It neither sends an alert nor authorizes operational changes to a live service.