- 格式化 66 个 Python 文件以符合 Black 代码风格 - 修复 GitHub Actions Code Quality 工作流失败问题 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
111 lines
3.1 KiB
Python
111 lines
3.1 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import logging
|
|
import re
|
|
import uuid
|
|
from typing import Any, Dict, Optional
|
|
|
|
from flask import current_app, g
|
|
|
|
_FALLBACK_LOGGER = logging.getLogger("outlook_web.errors")
|
|
if not _FALLBACK_LOGGER.handlers:
|
|
_FALLBACK_LOGGER.addHandler(logging.NullHandler())
|
|
_FALLBACK_LOGGER.propagate = False
|
|
|
|
|
|
def generate_trace_id() -> str:
|
|
return uuid.uuid4().hex
|
|
|
|
|
|
def sanitize_error_details(details: Optional[str]) -> str:
|
|
if not details:
|
|
return ""
|
|
sanitized = details
|
|
patterns = [
|
|
(r"(?i)(bearer\s+)[A-Za-z0-9\-._~\+/]+=*", r"\1***"),
|
|
(
|
|
r"(?i)(refresh_token|access_token|token|password|passwd|secret)\s*[:=]\s*\"?[A-Za-z0-9\-._~\+/]+=*\"?",
|
|
r"\1=***",
|
|
),
|
|
(r"(?i)(\"refresh_token\"\s*:\s*\")[^\"]+(\"?)", r"\1***\2"),
|
|
(r"(?i)(\"access_token\"\s*:\s*\")[^\"]+(\"?)", r"\1***\2"),
|
|
(r"(?i)(\"password\"\s*:\s*\")[^\"]+(\"?)", r"\1***\2"),
|
|
(r"(?i)(client_secret|refresh_token|access_token)=[^&\s]+", r"\1=***"),
|
|
]
|
|
for pattern, repl in patterns:
|
|
sanitized = re.sub(pattern, repl, sanitized)
|
|
return sanitized
|
|
|
|
|
|
def build_error_payload(
|
|
code: str,
|
|
message: str,
|
|
err_type: str = "Error",
|
|
status: int = 500,
|
|
details: Any = None,
|
|
trace_id: Optional[str] = None,
|
|
) -> Dict[str, Any]:
|
|
if not isinstance(message, str):
|
|
message = str(message)
|
|
sanitized_message = sanitize_error_details(message) if message else ""
|
|
|
|
if details is not None and not isinstance(details, str):
|
|
try:
|
|
details = json.dumps(details, ensure_ascii=False)
|
|
except Exception:
|
|
details = str(details)
|
|
sanitized_details = sanitize_error_details(details) if details else ""
|
|
|
|
request_trace_id = None
|
|
try:
|
|
request_trace_id = getattr(g, "trace_id", None)
|
|
except Exception:
|
|
request_trace_id = None
|
|
|
|
trace_id_value = trace_id or request_trace_id or generate_trace_id()
|
|
payload = {
|
|
"code": code,
|
|
"message": sanitized_message or "请求失败",
|
|
"type": err_type,
|
|
"status": status,
|
|
"details": sanitized_details,
|
|
"trace_id": trace_id_value,
|
|
}
|
|
|
|
# 根据状态码选择日志级别:
|
|
# - 5xx: ERROR(服务端错误)
|
|
# - 4xx: WARNING(客户端错误,如验证失败、权限不足等,属于正常业务流程)
|
|
# - 其他: INFO
|
|
log_level = (
|
|
logging.ERROR
|
|
if status >= 500
|
|
else (logging.WARNING if status >= 400 else logging.INFO)
|
|
)
|
|
|
|
try:
|
|
current_app.logger.log(
|
|
log_level,
|
|
"trace_id=%s code=%s status=%s type=%s details=%s",
|
|
trace_id_value,
|
|
code,
|
|
status,
|
|
err_type,
|
|
sanitized_details,
|
|
)
|
|
except Exception:
|
|
try:
|
|
_FALLBACK_LOGGER.log(
|
|
log_level,
|
|
"trace_id=%s code=%s status=%s type=%s details=%s",
|
|
trace_id_value,
|
|
code,
|
|
status,
|
|
err_type,
|
|
sanitized_details,
|
|
)
|
|
except Exception:
|
|
pass
|
|
|
|
return payload
|