73 lines
2.6 KiB
Python
73 lines
2.6 KiB
Python
import _bootstrap # noqa: F401
|
|
|
|
import unittest
|
|
from datetime import datetime, timezone
|
|
|
|
from fault_log_analyzer.models import Event, FaultLog, FaultType
|
|
from fault_log_analyzer.storage import (
|
|
InMemoryEventRepository,
|
|
InMemoryFaultLogRepository,
|
|
InMemoryFaultTypeRepository,
|
|
InMemoryRootCauseRepository,
|
|
)
|
|
from fault_log_analyzer.workers import ClusteringWorker, RootCauseWorker
|
|
|
|
|
|
def make_log(fid, message, host="h-1"):
|
|
return FaultLog(
|
|
fault_log_id=fid,
|
|
host_id=host,
|
|
fingerprint=f"fp-{fid}",
|
|
level="ERROR",
|
|
message=message,
|
|
occurred_at=datetime(2025, 1, 1, 10, 0, 0, tzinfo=timezone.utc),
|
|
)
|
|
|
|
|
|
class TestClusteringWorker(unittest.TestCase):
|
|
def test_run_classifies_and_persists(self):
|
|
fl_repo = InMemoryFaultLogRepository()
|
|
ft_repo = InMemoryFaultTypeRepository([FaultType(fault_type="disk_full", name="磁盘满", pattern=r"no space")])
|
|
worker = ClusteringWorker(fl_repo, ft_repo, eps=0.75, min_samples=1)
|
|
logs = [make_log("fl1", "No space left on device")]
|
|
out = worker.run(logs)
|
|
self.assertEqual(out[0].fault_type, "disk_full")
|
|
self.assertNotEqual(out[0].cluster_id, "")
|
|
persisted = fl_repo.get("fl1")
|
|
self.assertEqual(persisted.fault_type, "disk_full")
|
|
self.assertEqual(persisted.cluster_id, out[0].cluster_id)
|
|
|
|
def test_run_empty(self):
|
|
worker = ClusteringWorker(InMemoryFaultLogRepository(), InMemoryFaultTypeRepository())
|
|
self.assertEqual(worker.run([]), [])
|
|
|
|
def test_guess_candidate_when_no_type_matches(self):
|
|
fl_repo = InMemoryFaultLogRepository()
|
|
worker = ClusteringWorker(fl_repo, InMemoryFaultTypeRepository(), eps=0.75, min_samples=1)
|
|
out = worker.run([make_log("fl1", "No space left on device")])
|
|
self.assertEqual(out[0].fault_type, "disk_full")
|
|
|
|
|
|
class TestRootCauseWorker(unittest.TestCase):
|
|
def test_run_persists_root_cause(self):
|
|
rc_repo = InMemoryRootCauseRepository()
|
|
event_repo = InMemoryEventRepository(
|
|
[
|
|
Event(
|
|
event_id="e1",
|
|
host_id="h-1",
|
|
metric="disk_used_percent",
|
|
value=97.0,
|
|
fired_at=datetime(2025, 1, 1, 10, 1, 0, tzinfo=timezone.utc),
|
|
)
|
|
]
|
|
)
|
|
worker = RootCauseWorker(rc_repo, event_repo, window_minutes=5)
|
|
results = worker.run([make_log("fl1", "No space left on device")])
|
|
self.assertEqual(results[0].cause_type, "disk_full")
|
|
self.assertEqual(rc_repo.get("fl1").cause_type, "disk_full")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|