| 19 | |
| 20 | |
| 21 | class EventLog: |
| 22 | def __init__(self, path=None): |
| 23 | self.path = path |
| 24 | self._lock = threading.Lock() |
| 25 | self._buffer = [] # 内存镜像(便于查询/测试) |
| 26 | |
| 27 | def append(self, event_type, request_id=None, **fields): |
| 28 | record = {"ts": time.time(), "type": event_type, "request_id": request_id} |
| 29 | record.update(fields) |
| 30 | line = json.dumps(record, ensure_ascii=False) |
| 31 | with self._lock: |
| 32 | self._buffer.append(record) |
| 33 | if self.path: |
| 34 | with open(self.path, "a", encoding="utf-8") as f: |
| 35 | f.write(line + "\n") |
| 36 | return record |
| 37 | |
| 38 | def events(self, request_id=None, event_type=None): |
| 39 | with self._lock: |
| 40 | items = list(self._buffer) |
| 41 | if request_id is not None: |
| 42 | items = [e for e in items if e.get("request_id") == request_id] |
| 43 | if event_type is not None: |
| 44 | items = [e for e in items if e.get("type") == event_type] |
| 45 | return items |
| 46 | |
| 47 | def trim(self, max_events): |
| 48 | """仅保留最近 max_events 条事件(内存与文件同步),控制存储增长。""" |
| 49 | with self._lock: |
| 50 | self._buffer = self._buffer[-max_events:] |
| 51 | if self.path: |
| 52 | with open(self.path, "w", encoding="utf-8") as f: |
| 53 | for rec in self._buffer: |
| 54 | f.write(json.dumps(rec, ensure_ascii=False) + "\n") |
| 55 | return len(self._buffer) |
| 56 | |
| 57 | @staticmethod |
| 58 | def read_file(path): |
| 59 | out = [] |
| 60 | try: |
| 61 | with open(path, "r", encoding="utf-8") as f: |
| 62 | for line in f: |
| 63 | line = line.strip() |
| 64 | if line: |
| 65 | out.append(json.loads(line)) |
| 66 | except OSError: |
| 67 | pass |
| 68 | return out |
no outgoing calls