60ebb75cd2
Each incident gets a signature: the alert name plus the group labels that
say what is broken, minus the ones that only say where it ran (instance,
pod, container, ...). GET /api/incidents/{id}/similar returns resolved
incidents in the same team with the same signature that have notes.
Notes can be marked as the resolution note, "what fixed it", either with a
resolution field on resolve or pinned on a note. Those lead the similar
list, show on the incident page as "Seen before", and the triggered
notification carries the latest one.
Claude-Session: https://claude.ai/code/session_01MMados3BD1oSjevHxbmVqU
24 lines
1.1 KiB
SQL
24 lines
1.1 KiB
SQL
-- Similar incidents: a signature per incident, so "has this happened before"
|
|
-- is an indexed equality instead of a search.
|
|
--
|
|
-- The signature is the alert name plus the group labels that identify WHAT is
|
|
-- broken, minus the ones that only say WHERE it happened to run this time
|
|
-- (instance, pod, ...). Two incidents with the same signature in the same team
|
|
-- are the same problem for a responder's purposes.
|
|
--
|
|
-- Computed in Go for new incidents (incidentSignature in incident_store.go).
|
|
-- The backfill below MUST produce the same string; keep the volatile list in
|
|
-- both places in step.
|
|
ALTER TABLE incidents ADD COLUMN signature TEXT NOT NULL DEFAULT '';
|
|
|
|
UPDATE incidents SET signature =
|
|
COALESCE(NULLIF(group_labels->>'alertname', ''), title) || '|' ||
|
|
COALESCE((
|
|
SELECT string_agg(e.k || '=' || e.v, ',' ORDER BY e.k)
|
|
FROM jsonb_each_text(incidents.group_labels) AS e(k, v)
|
|
WHERE e.k <> 'alertname'
|
|
AND e.k NOT IN ('instance', 'pod', 'pod_name', 'pod_ip', 'container', 'container_name', 'endpoint')
|
|
), '');
|
|
|
|
CREATE INDEX incidents_signature_idx ON incidents(team_id, signature, triggered_at DESC);
|