| 24 | class JsonFormatter(logging.Formatter): |
| 25 | # NOTE: 输出 JSON 行日志,字段固定,便于后续统一采集与检索 |
| 26 | def format(self, record: logging.LogRecord) -> str: |
| 27 | data = { |
| 28 | "ts": datetime.fromtimestamp(record.created, tz=timezone.utc).isoformat().replace("+00:00", "Z"), |
| 29 | "level": record.levelname, |
| 30 | "logger": record.name, |
| 31 | "event": getattr(record, "event", "log"), |
| 32 | "action": getattr(record, "action", ""), |
| 33 | "status": getattr(record, "status", ""), |
| 34 | "op_id": getattr(record, "op_id", "") or current_op_id(), |
| 35 | "module": record.module, |
| 36 | "function": record.funcName, |
| 37 | "message": record.getMessage(), |
| 38 | "cmd": getattr(record, "cmd", ""), |
| 39 | "duration_ms": getattr(record, "duration_ms", None), |
| 40 | "error_type": getattr(record, "error_type", ""), |
| 41 | "error_message": getattr(record, "error_message", ""), |
| 42 | "traceback": getattr(record, "traceback", ""), |
| 43 | } |
| 44 | if record.exc_info and not data["traceback"]: |
| 45 | data["traceback"] = self.formatException(record.exc_info) |
| 46 | return json.dumps(data, ensure_ascii=False) |
| 47 | |
| 48 | |
| 49 | class ConsoleFormatter(logging.Formatter): |