fault-log-analyzer/tests/test_workers.py

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()