diff --git a/loglens/analyzers/patterns.py b/loglens/analyzers/patterns.py index 8e44601..7f177fd 100644 --- a/loglens/analyzers/patterns.py +++ b/loglens/analyzers/patterns.py @@ -1,13 +1,14 @@ -"""Pattern library for error detection.""" +'''Pattern library for error detection.''' import re from dataclasses import dataclass, field -from typing import Dict, List, Optional, Tuple +from typing import Optional @dataclass class ErrorPattern: - """Represents an error detection pattern.""" + '''Represents an error detection pattern.''' + name: str pattern: str severity: str = "error" @@ -23,7 +24,7 @@ class ErrorPattern: self._regex = re.compile(re.escape(self.pattern), re.IGNORECASE) def match(self, text: str) -> Optional[re.Match]: - """Match pattern against text.""" + '''Match pattern against text.''' if not self.enabled: return None return self._regex.search(text) @@ -31,21 +32,22 @@ class ErrorPattern: @dataclass class PatternGroup: - """Group of related patterns.""" + '''Group of related patterns.''' + name: str - patterns: List[ErrorPattern] = field(default_factory=list) + patterns: list[ErrorPattern] = field(default_factory=list) class PatternLibrary: - """Library of error detection patterns.""" + '''Library of error detection patterns.''' def __init__(self): - self._patterns: List[ErrorPattern] = [] - self._groups: Dict[str, PatternGroup] = {} + self._patterns: list[ErrorPattern] = [] + self._groups: dict[str, PatternGroup] = {} self._load_default_patterns() def _load_default_patterns(self) -> None: - """Load default error patterns.""" + '''Load default error patterns.''' self._patterns = [ ErrorPattern( name="Python Exception", @@ -53,7 +55,7 @@ class PatternLibrary: severity="error", description="Python exception detected", suggestion="Check the exception type and stack trace to identify the root cause", - group="exceptions" + group="exceptions", ), ErrorPattern( name="Java Stack Trace", @@ -61,7 +63,7 @@ class PatternLibrary: severity="error", description="Java exception/stack trace detected", suggestion="Review the Java stack trace for the exception cause", - group="exceptions" + group="exceptions", ), ErrorPattern( name="Connection Refused", @@ -69,7 +71,7 @@ class PatternLibrary: severity="error", description="Connection was refused", suggestion="Check if the service is running and the port is correct", - group="network" + group="network", ), ErrorPattern( name="Connection Timeout", @@ -77,7 +79,7 @@ class PatternLibrary: severity="error", description="Connection timed out", suggestion="Check network connectivity and server responsiveness", - group="network" + group="network", ), ErrorPattern( name="Database Error", @@ -85,7 +87,7 @@ class PatternLibrary: severity="error", description="Database error detected", suggestion="Check database connectivity and query syntax", - group="database" + group="database", ), ErrorPattern( name="SQL Error", @@ -93,7 +95,7 @@ class PatternLibrary: severity="error", description="SQL error detected", suggestion="Review the SQL query for syntax errors", - group="database" + group="database", ), ErrorPattern( name="HTTP 5xx Error", @@ -101,7 +103,7 @@ class PatternLibrary: severity="error", description="Server-side HTTP error", suggestion="Check server logs for the root cause", - group="http" + group="http", ), ErrorPattern( name="HTTP 4xx Error", @@ -109,7 +111,7 @@ class PatternLibrary: severity="warning", description="Client-side HTTP error", suggestion="Check request URL and parameters", - group="http" + group="http", ), ErrorPattern( name="Null Pointer", @@ -117,7 +119,7 @@ class PatternLibrary: severity="error", description="Null pointer/null reference error", suggestion="Add null checks before accessing objects", - group="exceptions" + group="exceptions", ), ErrorPattern( name="Index Error", @@ -125,7 +127,7 @@ class PatternLibrary: severity="error", description="Index out of bounds error", suggestion="Check array/list bounds before access", - group="exceptions" + group="exceptions", ), ErrorPattern( name="Key Error", @@ -133,7 +135,7 @@ class PatternLibrary: severity="error", description="Key not found in dictionary/map", suggestion="Add key existence checks or use .get() method", - group="exceptions" + group="exceptions", ), ErrorPattern( name="Permission Denied", @@ -141,7 +143,7 @@ class PatternLibrary: severity="error", description="Permission denied error", suggestion="Check file/directory permissions", - group="system" + group="system", ), ErrorPattern( name="Disk Full", @@ -149,7 +151,7 @@ class PatternLibrary: severity="critical", description="Disk space exhausted", suggestion="Free up disk space or increase storage", - group="system" + group="system", ), ErrorPattern( name="Memory Error", @@ -157,7 +159,7 @@ class PatternLibrary: severity="critical", description="Out of memory error", suggestion="Increase memory or optimize memory usage", - group="system" + group="system", ), ErrorPattern( name="Segmentation Fault", @@ -165,7 +167,7 @@ class PatternLibrary: severity="critical", description="Segmentation fault", suggestion="Check for null pointer dereferences or buffer overflows", - group="system" + group="system", ), ErrorPattern( name="Panic", @@ -173,7 +175,7 @@ class PatternLibrary: severity="critical", description="Application panic", suggestion="Review panic message and stack trace", - group="system" + group="system", ), ErrorPattern( name="Deprecated", @@ -181,7 +183,7 @@ class PatternLibrary: severity="info", description="Deprecated feature usage", suggestion="Update to the recommended replacement", - group="code_quality" + group="code_quality", ), ErrorPattern( name="Warning", @@ -189,7 +191,7 @@ class PatternLibrary: severity="warning", description="General warning", suggestion="Review warning message for potential issues", - group="general" + group="general", ), ErrorPattern( name="Debug", @@ -197,7 +199,7 @@ class PatternLibrary: severity="debug", description="Debug message", suggestion="Ignore unless debugging", - group="general" + group="general", ), ErrorPattern( name="Authentication Failed", @@ -205,7 +207,7 @@ class PatternLibrary: severity="error", description="Authentication failure", suggestion="Verify username/password or API key", - group="security" + group="security", ), ErrorPattern( name="SSL/TLS Error", @@ -213,47 +215,40 @@ class PatternLibrary: severity="error", description="SSL/TLS error", suggestion="Check certificate validity and configuration", - group="security" + group="security", ), ] self._groups = { "exceptions": PatternGroup( - name="Exceptions", - patterns=[p for p in self._patterns if p.group == "exceptions"] + name="Exceptions", patterns=[p for p in self._patterns if p.group == "exceptions"] ), "network": PatternGroup( - name="Network", - patterns=[p for p in self._patterns if p.group == "network"] + name="Network", patterns=[p for p in self._patterns if p.group == "network"] ), "database": PatternGroup( - name="Database", - patterns=[p for p in self._patterns if p.group == "database"] + name="Database", patterns=[p for p in self._patterns if p.group == "database"] ), "http": PatternGroup( - name="HTTP", - patterns=[p for p in self._patterns if p.group == "http"] + name="HTTP", patterns=[p for p in self._patterns if p.group == "http"] ), "system": PatternGroup( - name="System", - patterns=[p for p in self._patterns if p.group == "system"] + name="System", patterns=[p for p in self._patterns if p.group == "system"] ), "security": PatternGroup( - name="Security", - patterns=[p for p in self._patterns if p.group == "security"] + name="Security", patterns=[p for p in self._patterns if p.group == "security"] ), "code_quality": PatternGroup( name="Code Quality", - patterns=[p for p in self._patterns if p.group == "code_quality"] + patterns=[p for p in self._patterns if p.group == "code_quality"], ), "general": PatternGroup( - name="General", - patterns=[p for p in self._patterns if p.group == "general"] + name="General", patterns=[p for p in self._patterns if p.group == "general"] ), } - def detect(self, text: str) -> List[Tuple[ErrorPattern, re.Match]]: - """Detect all patterns matching the text.""" + def detect(self, text: str) -> list[tuple[ErrorPattern, re.Match]]: + '''Detect all patterns matching the text.''' matches = [] for pattern in self._patterns: if pattern.enabled: @@ -262,8 +257,8 @@ class PatternLibrary: matches.append((pattern, match)) return matches - def find_match(self, text: str) -> Optional[Tuple[ErrorPattern, re.Match]]: - """Find the first matching pattern.""" + def find_match(self, text: str) -> Optional[tuple[ErrorPattern, re.Match]]: + '''Find the first matching pattern.''' for pattern in self._patterns: if pattern.enabled: match = pattern.match(text) @@ -271,20 +266,20 @@ class PatternLibrary: return (pattern, match) return None - def get_patterns_by_severity(self, severity: str) -> List[ErrorPattern]: - """Get patterns by severity level.""" + def get_patterns_by_severity(self, severity: str) -> list[ErrorPattern]: + '''Get patterns by severity level.''' return [p for p in self._patterns if p.severity == severity] - def get_patterns_by_group(self, group: str) -> List[ErrorPattern]: - """Get patterns by group.""" + def get_patterns_by_group(self, group: str) -> list[ErrorPattern]: + '''Get patterns by group.''' return [p for p in self._patterns if p.group == group] def add_pattern(self, pattern: ErrorPattern) -> None: - """Add a custom pattern.""" + '''Add a custom pattern.''' self._patterns.append(pattern) def remove_pattern(self, name: str) -> bool: - """Remove a pattern by name.""" + '''Remove a pattern by name.''' for i, p in enumerate(self._patterns): if p.name == name: self._patterns.pop(i) @@ -292,7 +287,7 @@ class PatternLibrary: return False def disable_pattern(self, name: str) -> bool: - """Disable a pattern by name.""" + '''Disable a pattern by name.''' for p in self._patterns: if p.name == name: p.enabled = False @@ -300,17 +295,17 @@ class PatternLibrary: return False def enable_pattern(self, name: str) -> bool: - """Enable a pattern by name.""" + '''Enable a pattern by name.''' for p in self._patterns: if p.name == name: p.enabled = True return True return False - def list_patterns(self) -> List[ErrorPattern]: - """List all patterns.""" + def list_patterns(self) -> list[ErrorPattern]: + '''List all patterns.''' return self._patterns.copy() - def list_groups(self) -> Dict[str, List[ErrorPattern]]: - """List patterns by group.""" + def list_groups(self) -> dict[str, list[ErrorPattern]]: + '''List patterns by group.''' return {name: group.patterns.copy() for name, group in self._groups.items()}