Skip to content

feat: lock an incident after a configurable max window#6621

Open
aditya-786 wants to merge 1 commit into
keephq:mainfrom
aditya-786:feat/incident-max-window
Open

feat: lock an incident after a configurable max window#6621
aditya-786 wants to merge 1 commit into
keephq:mainfrom
aditya-786:feat/incident-max-window

Conversation

@aditya-786

Copy link
Copy Markdown
Contributor

Summary

Closes #5175

A correlation rule keeps extending the same incident for as long as matching alerts keep arriving within the rule timeframe. For a condition that trickles alerts indefinitely, that means a single incident can stay open forever and grow without bound, with no way to cap how long one incident represents.

This adds an optional per-rule max incident window (in seconds). Once an incident is older than the window, measured from its creation time, the next matching alert opens a fresh incident instead of extending the old one. The field is nullable and defaults to off, so existing rules behave exactly as before.

How it works

The decision already exists: get_incident_for_grouping_rule in keep/api/core/db.py computes an is_incident_expired flag, and the rules engine already creates a fresh incident (linked via same_incident_in_the_past_id) whenever that flag is set. This change adds one more way for an incident to be considered expired.

  • The expiry logic is extracted into a small pure helper, compute_incident_expired in keep/api/utils/incident_expiry.py, which reproduces the existing checks (resolved/merged/deleted status, or last alert older than the timeframe) and adds the new one (max_window set and now - creation_time past the window). It depends only on datetime, so it is unit-tested in isolation.
  • get_incident_for_grouping_rule now calls that helper. When max_incident_window is None, the result is identical to today.
  • Rule gains a nullable max_incident_window column (with an additive Alembic migration), threaded through create_rule / update_rule and the rules API (maxIncidentWindow). The window is anchored on the incident creation time; resolution logic is untouched.

Tests

tests/test_incident_max_window.py unit-tests compute_incident_expired (runs under pytest --noconftest, no DB):

  • backward compatibility: with max_window=None it expires only on terminal status or a last alert older than the timeframe
  • the new lock: with the window elapsed it expires even when the latest alert is still within the timeframe
  • within the window it does not expire; terminal status short-circuits; the exact boundary is not yet expired

Fail-before / pass-after verified locally (neutering the new clause fails the lock test), and the existing tests/test_rules_engine.py correlation/grouping suite passes unchanged against the modified get_incident_for_grouping_rule.

Notes

Anchored on incident creation time (not first-alert), which is the simplest and most predictable semantics; happy to switch the anchor if maintainers prefer. Correlation rules are not part of the env/file provisioning path, so no provisioning changes are needed. UI wiring for the rule builder can follow; the backend enforces the window regardless of how the rule is created.

A correlation rule keeps extending the same incident while matching alerts
keep arriving within the timeframe, so a long-running condition can live in a
single incident forever. This adds an optional per-rule max_incident_window
(seconds): once an incident is older than the window, measured from its
creation time, the next matching alert opens a fresh incident instead. The
field is nullable and defaults off, so existing rules are unchanged.
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. Feature A new feature labels Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature A new feature size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[➕ Feature]: Lock/Freeze an incident after a user defined max window time

1 participant