← Questions

Alert routing service with silences and escalation

0
OpenAICoding

Build the routing core of an alerting service. The monitoring system calls fire(labels, now) for an active alert on every evaluation cycle (every 30 seconds or so) and resolve(labels, now) once when it clears. Your router decides who gets notified. Every method takes the current time; time never goes backwards. Methods return the notifications to send as (receiver, kind, fingerprint) tuples, where fingerprint is the alert's labels sorted by key and joined as k=v with commas.

Part 1: routing. Routes are an ordered list of {"match": {label: value}, "receiver": str, "continue": bool}. An alert matches a route when every matcher equals the alert's label. The first matching route wins; if it has continue: true, keep walking and collect more receivers. No match: the default receiver. Implement route(labels) -> [receiver] (no duplicates).

Part 2: dedupe and resolve. fire notifies each receiver (kind = "firing") unless that receiver already heard about this alert less than repeat_interval seconds ago. Label order must not matter. resolve sends "resolved" only to receivers that were notified, then forgets the alert; resolving an unknown alert sends nothing.

Part 3: silences, ack, escalation. silence(matchers, start, end) -> id mutes matching alerts while start <= now < end; expire_silence(id) ends one early. An empty matcher set is rejected. A route may have "escalate": {"after": seconds, "to": receiver}: tick(now) pages to once (kind = "escalated") if the alert is still active, not acked and not silenced, after seconds after its first notification. ack(labels) stops escalation. Escalation receivers also get the resolve.

class AlertRouter:
    def __init__(self, routes: list, default_receiver: str, repeat_interval: int): ...
    def route(self, labels: dict) -> list: ...
    def fire(self, labels: dict, now: int) -> list: ...
    def resolve(self, labels: dict, now: int) -> list: ...
    def silence(self, matchers: dict, start: int, end: int) -> int: ...
    def expire_silence(self, silence_id: int) -> bool: ...
    def ack(self, labels: dict) -> bool: ...
    def tick(self, now: int) -> list: ...
Write and test your solution herePython in your browser, the question's tests level by level, every submission kept for you.Sign in to start coding