-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.py
More file actions
80 lines (64 loc) · 2.46 KB
/
Copy pathparser.py
File metadata and controls
80 lines (64 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import re
from typing import List, Optional, Dict
from dataclasses import dataclass
from enum import Enum
class ErrorType(Enum):
FAILED = "FAILED"
DEPENDENCY_FAILED = "Dependency failed"
RESTART_LOOP = "Restart loop detected"
UNKNOWN = "Unknown"
@dataclass
class LogEntry:
timestamp: str
service: str
error_type: ErrorType
message: str
def to_dict(self) -> Dict:
return {
"timestamp": self.timestamp,
"service": self.service,
"error_type": self.error_type.value,
"message": self.message
}
def to_text(self) -> str:
return f"[{self.timestamp}] {self.service} {self.error_type.value}"
class LogParser:
TIMESTAMP_PATTERN = re.compile(r'(\d{2}:\d{2}:\d{2})')
ISO_TIMESTAMP_PATTERN = re.compile(r'\d{4}-\d{2}-\d{2}T(\d{2}:\d{2}:\d{2})')
SERVICE_PATTERN = re.compile(r'([a-zA-Z0-9_-]+\.service)')
FAILED_PATTERN = re.compile(r'(failed|FAILED)', re.IGNORECASE)
DEPENDENCY_PATTERN = re.compile(r'(dependency failed|Failed to start|dependency)', re.IGNORECASE)
RESTART_LOOP_PATTERN = re.compile(r'(start request repeated too quickly|restart loop)', re.IGNORECASE)
def parse(self, lines: List[str]) -> List[LogEntry]:
entries = []
for line in lines:
entry = self._parse_line(line)
if entry:
entries.append(entry)
return entries
def _parse_line(self, line: str) -> Optional[LogEntry]:
timestamp_match = self.ISO_TIMESTAMP_PATTERN.search(line)
if not timestamp_match:
timestamp_match = self.TIMESTAMP_PATTERN.search(line)
service_match = self.SERVICE_PATTERN.search(line)
if not timestamp_match or not service_match:
return None
timestamp = timestamp_match.group(1)
service = service_match.group(1)
message = line
error_type = self._detect_error_type(line)
return LogEntry(
timestamp=timestamp,
service=service,
error_type=error_type,
message=message.strip()
)
def _detect_error_type(self, line: str) -> ErrorType:
if self.RESTART_LOOP_PATTERN.search(line):
return ErrorType.RESTART_LOOP
elif self.DEPENDENCY_PATTERN.search(line):
return ErrorType.DEPENDENCY_FAILED
elif self.FAILED_PATTERN.search(line):
return ErrorType.FAILED
else:
return ErrorType.FAILED