Skill 12 · Authoring Log Alerts
Subchapter 12.1
references/threshold-defaults.mdMarkdown4 KBView on GitHub
The math here is implemented in ../scripts/baseline_stats.py. The agent
should not reproduce these calculations inline — pipe the posthog:logs-count-ranges response into the script and
read . This section explains , so you can
sanity-check its output and reason about edge cases.
suggested_threshold_countThe bucket-level threshold takes the max of three terms:
The bucket-level threshold is then rate-scaled to the alert window — a 7h bucket with a threshold of 1000 errors equals ~12 errors per 5-minute window. The script does this scaling; the rationale field shows the math.
The scaling assumes errors arrive uniformly within a bucket, which is rarely true — a real spike can pack
the entire bucket’s count into a single 5-minute window. That’s exactly why posthog:logs-alerts-simulate-create is the
final arbiter: it replays the alert state machine against actual per-minute history, not the rate-scaled
average.
The default minimum. Reasons to go higher:
Allowed: 5, 10, 15, 30, 60. Don’t pick a value not on this list — the API rejects it.
N-of-M is the cheap, high-signal way to dampen flap. 2-of-3 means: out of the last 3 check intervals, at least 2 must breach to fire. A single noisy interval doesn’t trip the alert. A sustained problem still does.
When to deviate:
After a fire, suppress repeat fires for 30 minutes. This avoids paging the same channel every check interval during an ongoing incident — once the alert is firing, the user already knows.
Use 0 for snapshot-style alerts where every breach is independently interesting (rare).
threshold_operator: below without justification. Below-threshold alerts measure absence — useful for
“service stopped logging” but easy to misuse. If the service has any quiet hours (overnight, weekends),
a below-threshold alert will fire at 3am every night. See volume-floor-alerts.md.searchTerm or message icontains). Brittle to log format changes.
Prefer a structured attribute (http.status_code, error.type) when one exists.trace_id/span_id. Not useful in alerts — these are per-request and never repeat at a
rate that crosses a meaningful threshold.