72 lines
2.6 KiB
Python
72 lines
2.6 KiB
Python
import unittest
|
||
|
||
from detector.converger import AlertConverger
|
||
from detector.models import Event
|
||
from detector.storage import InMemoryAlertStore, InMemoryCache, InMemoryMessageBus
|
||
|
||
|
||
def make_event(status="firing", host_id="h-1", rule_id="r-1", fired_at=100.0):
|
||
return Event(
|
||
event_id=f"e-{status}-{host_id}",
|
||
host_id=host_id,
|
||
rule_id=rule_id,
|
||
metric="cpu_usage",
|
||
agg_value=95.0,
|
||
threshold=90.0,
|
||
operator="gt",
|
||
status=status,
|
||
severity="critical",
|
||
fired_at=fired_at,
|
||
)
|
||
|
||
|
||
class TestAlertConverger(unittest.TestCase):
|
||
def setUp(self):
|
||
self.store = InMemoryAlertStore()
|
||
self.cache = InMemoryCache()
|
||
self.bus = InMemoryMessageBus()
|
||
self.converger = AlertConverger(
|
||
self.store, self.cache, self.bus, dedup_window="5m", aggregate_window="1m",
|
||
host_group_resolver=lambda h: "web",
|
||
)
|
||
|
||
def test_dedup_suppresses_duplicate(self):
|
||
first = self.converger.handle_event(make_event())
|
||
self.assertIsNotNone(first)
|
||
second = self.converger.handle_event(make_event())
|
||
self.assertIsNone(second)
|
||
self.assertEqual(len(self.store.list_alerts()[1]), 1)
|
||
|
||
def test_resolve_clears_dedup(self):
|
||
self.converger.handle_event(make_event(fired_at=100.0))
|
||
resolved = self.converger.handle_event(make_event(status="resolved", fired_at=200.0))
|
||
self.assertIsNotNone(resolved)
|
||
self.assertEqual(resolved.status, "resolved")
|
||
|
||
# 去重键已清除,恢复后再次 firing 可以产生新告警
|
||
again = self.converger.handle_event(make_event(fired_at=300.0))
|
||
self.assertIsNotNone(again)
|
||
|
||
def test_aggregate_same_bucket(self):
|
||
a1 = self.converger.handle_event(make_event(host_id="h-1", fired_at=100.0))
|
||
a2 = self.converger.handle_event(make_event(host_id="h-2", fired_at=110.0))
|
||
self.assertIsNotNone(a1)
|
||
self.assertIsNotNone(a2)
|
||
alerts = self.store.list_alerts()[1]
|
||
# 同一 aggregate_key(同 bucket/severity/rule/group)聚合为一条
|
||
self.assertEqual(len(alerts), 1)
|
||
self.assertEqual(alerts[0].count, 2)
|
||
self.assertIn("h-1", alerts[0].detail["hosts"])
|
||
self.assertIn("h-2", alerts[0].detail["hosts"])
|
||
|
||
def test_publish_to_bus(self):
|
||
self.converger.handle_event(make_event())
|
||
self.assertEqual(len(self.bus.messages), 1)
|
||
topic, key, value = self.bus.messages[0]
|
||
self.assertEqual(topic, "alerts.converged")
|
||
self.assertIn("alert_id", value)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|