diff --git a/loglens/analyzers/severity.py b/loglens/analyzers/severity.py index 4dda3a7..fdfd609 100644 --- a/loglens/analyzers/severity.py +++ b/loglens/analyzers/severity.py @@ -1,12 +1,13 @@ -"""Severity classification for log entries.""" +'''Severity classification for log entries.''' from dataclasses import dataclass from enum import Enum -from typing import Any, Dict, List, Optional +from typing import Any, Optional class SeverityLevel(Enum): - """Severity levels for log entries.""" + '''Severity levels for log entries.''' + CRITICAL = "critical" ERROR = "error" WARNING = "warning" @@ -16,7 +17,7 @@ class SeverityLevel(Enum): @classmethod def from_string(cls, level: str) -> "SeverityLevel": - """Convert string to SeverityLevel.""" + '''Convert string to SeverityLevel.''' level_lower = level.lower() for member in cls: if member.value == level_lower: @@ -24,19 +25,19 @@ class SeverityLevel(Enum): return cls.UNKNOWN def score(self) -> int: - """Get numeric score for severity.""" + '''Get numeric score for severity.''' scores = { SeverityLevel.CRITICAL: 5, SeverityLevel.ERROR: 4, SeverityLevel.WARNING: 3, SeverityLevel.INFO: 2, SeverityLevel.DEBUG: 1, - SeverityLevel.UNKNOWN: 0 + SeverityLevel.UNKNOWN: 0, } return scores.get(self, 0) def __lt__(self, other: "SeverityLevel") -> bool: - """Compare severity levels.""" + '''Compare severity levels.''' return self.score() < other.score() def __le__(self, other: "SeverityLevel") -> bool: @@ -51,16 +52,17 @@ class SeverityLevel(Enum): @dataclass class SeverityRule: - """Rule for severity classification.""" + '''Rule for severity classification.''' + name: str - patterns: List[str] + patterns: list[str] severity: SeverityLevel weight: int = 1 description: str = "" class SeverityClassifier: - """Classifies log entries by severity.""" + '''Classifies log entries by severity.''' DEFAULT_RULES = [ SeverityRule( @@ -68,57 +70,59 @@ class SeverityClassifier: patterns=["fatal", "segfault", "panic", "core dumped", "critical system failure"], severity=SeverityLevel.CRITICAL, weight=10, - description="Critical system failures" + description="Critical system failures", ), SeverityRule( name="error_keywords", patterns=["error", "exception", "failed", "failure", "timeout", "cannot", "unable"], severity=SeverityLevel.ERROR, weight=5, - description="General errors" + description="General errors", ), SeverityRule( name="warning_keywords", patterns=["warning", "warn", "deprecated", "deprecation"], severity=SeverityLevel.WARNING, weight=3, - description="Warnings and deprecations" + description="Warnings and deprecations", ), SeverityRule( name="info_keywords", patterns=["info", "notice", "started", "stopped", "loaded"], severity=SeverityLevel.INFO, weight=1, - description="Informational messages" + description="Informational messages", ), SeverityRule( name="debug_keywords", patterns=["debug", "trace", "verbose"], severity=SeverityLevel.DEBUG, weight=0, - description="Debug and trace messages" + description="Debug and trace messages", ), ] - def __init__(self, custom_rules: Optional[List[Dict[str, Any]]] = None): - self.rules: List[SeverityRule] = self.DEFAULT_RULES.copy() + def __init__(self, custom_rules: Optional[list[dict[str, Any]]] = None): + self.rules: list[SeverityRule] = self.DEFAULT_RULES.copy() if custom_rules: self._load_custom_rules(custom_rules) - def _load_custom_rules(self, rules: List[Dict[str, Any]]) -> None: - """Load custom severity rules.""" + def _load_custom_rules(self, rules: list[dict[str, Any]]) -> None: + '''Load custom severity rules.''' for rule_data in rules: rule = SeverityRule( name=rule_data.get("name", "custom"), patterns=rule_data.get("patterns", []), severity=SeverityLevel.from_string(rule_data.get("severity", "info")), weight=rule_data.get("weight", 1), - description=rule_data.get("description", "") + description=rule_data.get("description", ""), ) self.rules.append(rule) - def classify(self, level: Optional[str], message: str = "", pattern_match: Optional[str] = None) -> SeverityLevel: - """Classify severity based on level, message, and pattern.""" + def classify( + self, level: Optional[str], message: str = "", pattern_match: Optional[str] = None + ) -> SeverityLevel: + '''Classify severity based on level, message, and pattern.''' score = 0 matched_severity = SeverityLevel.UNKNOWN @@ -159,8 +163,10 @@ class SeverityClassifier: return SeverityLevel.INFO - def classify_with_details(self, level: Optional[str], message: str = "", pattern_match: Optional[str] = None) -> Dict[str, Any]: - """Classify severity with detailed information.""" + def classify_with_details( + self, level: Optional[str], message: str = "", pattern_match: Optional[str] = None + ) -> dict[str, Any]: + '''Classify severity with detailed information.''' severity = self.classify(level, message, pattern_match) text = f"{message} {pattern_match or ''}".lower() @@ -169,33 +175,41 @@ class SeverityClassifier: for rule in self.rules: for pattern in rule.patterns: if pattern.lower() in text: - matched_rules.append({ - "rule": rule.name, - "pattern": pattern, - "severity": rule.severity.value, - "weight": rule.weight - }) + matched_rules.append( + { + "rule": rule.name, + "pattern": pattern, + "severity": rule.severity.value, + "weight": rule.weight, + } + ) return { "severity": severity, "matched_rules": matched_rules, - "confidence": min(1.0, len(matched_rules) * 0.3) if matched_rules else 0.5 + "confidence": min(1.0, len(matched_rules) * 0.3) if matched_rules else 0.5, } - def get_severity_order(self) -> List[SeverityLevel]: - """Get severity levels in order from highest to lowest.""" + def get_severity_order(self) -> list[SeverityLevel]: + '''Get severity levels in order from highest to lowest.''' return sorted( - [SeverityLevel.CRITICAL, SeverityLevel.ERROR, SeverityLevel.WARNING, - SeverityLevel.INFO, SeverityLevel.DEBUG, SeverityLevel.UNKNOWN], - reverse=True + [ + SeverityLevel.CRITICAL, + SeverityLevel.ERROR, + SeverityLevel.WARNING, + SeverityLevel.INFO, + SeverityLevel.DEBUG, + SeverityLevel.UNKNOWN, + ], + reverse=True, ) def add_rule(self, rule: SeverityRule) -> None: - """Add a custom rule.""" + '''Add a custom rule.''' self.rules.append(rule) def remove_rule(self, name: str) -> bool: - """Remove a rule by name.""" + '''Remove a rule by name.''' for i, rule in enumerate(self.rules): if rule.name == name: self.rules.pop(i)