-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathplain2code_logger.py
More file actions
97 lines (75 loc) · 3.01 KB
/
plain2code_logger.py
File metadata and controls
97 lines (75 loc) · 3.01 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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import logging
import os
import time
from typing import Optional
from event_bus import EventBus
from plain2code_events import LogMessageEmitted
LOGGER_NAME = "codeplain"
class IndentedFormatter(logging.Formatter):
def format(self, record):
original_message = record.getMessage()
modified_message = original_message.replace("\n", "\n ")
record.msg = modified_message
return super().format(record)
class TuiLoggingHandler(logging.Handler):
def __init__(self, event_bus: EventBus):
super().__init__()
self.event_bus = event_bus
self.start_time = time.time()
def emit(self, record):
try:
offset_seconds = record.created - self.start_time
minutes = int(offset_seconds // 60)
seconds = int(offset_seconds % 60)
milliseconds = int((offset_seconds % 1) * 100)
timestamp = f"{minutes:02d}:{seconds:02d}:{milliseconds:02d}"
event = LogMessageEmitted(
logger_name=record.name,
level=record.levelname,
message=record.getMessage(),
timestamp=timestamp,
)
self.event_bus.publish(event)
except RuntimeError:
# We're going to get this crash after the TUI app is closed (forcefully).
# NOTE: This should be more thought out.
pass
except Exception:
self.handleError(record)
class CrashLogHandler(logging.Handler):
def __init__(self):
super().__init__()
self.records = []
def emit(self, record):
self.records.append(record)
def dump_to_file(self, filepath, formatter=None):
if not self.records:
return False
try:
with open(filepath, "w") as f:
for record in self.records:
if formatter:
msg = formatter.format(record)
else:
msg = self.format(record)
f.write(msg + "\n")
return True
except Exception:
return False
def get_log_file_path(plain_file_path: Optional[str], log_file_name: str) -> Optional[str]:
"""Get the full path to the log file, relative to the plain file directory."""
if not plain_file_path:
return None
plain_dir = os.path.dirname(os.path.abspath(plain_file_path))
return os.path.join(plain_dir, log_file_name)
def dump_crash_logs(args, formatter=None):
"""Dump buffered logs to file if CrashLogHandler is present."""
if args.log_to_file:
return
if formatter is None:
formatter = IndentedFormatter("%(levelname)s:%(name)s:%(message)s")
root_logger = logging.getLogger(LOGGER_NAME)
crash_handler = next((h for h in root_logger.handlers if isinstance(h, CrashLogHandler)), None)
if crash_handler and args.filename:
log_file_path = get_log_file_path(args.filename, args.log_file_name)
crash_handler.dump_to_file(log_file_path, formatter)