67 lines
1.8 KiB
Python
67 lines
1.8 KiB
Python
import logging
|
||
|
||
from rest_framework.views import exception_handler as drf_exception_handler
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def _error_messages(details):
|
||
messages = []
|
||
|
||
def collect(value):
|
||
if isinstance(value, dict):
|
||
for item in value.values():
|
||
collect(item)
|
||
elif isinstance(value, (list, tuple)):
|
||
for item in value:
|
||
collect(item)
|
||
elif value is not None:
|
||
message = str(value).strip()
|
||
if message and message not in messages:
|
||
messages.append(message)
|
||
|
||
collect(details)
|
||
return messages
|
||
|
||
|
||
def _error_message(details):
|
||
messages = _error_messages(details)
|
||
if not messages:
|
||
return "请求未能完成"
|
||
return ";".join(messages)[:300]
|
||
|
||
|
||
def exception_handler(exc, context):
|
||
response = drf_exception_handler(exc, context)
|
||
request = context.get("request")
|
||
if response is None:
|
||
logger.exception(
|
||
"api_unhandled_error method=%s path=%s",
|
||
getattr(request, "method", "-"),
|
||
getattr(request, "path", "-"),
|
||
)
|
||
return response
|
||
|
||
details = response.data
|
||
code = getattr(exc, "default_code", "request_error")
|
||
message = _error_message(details)
|
||
fields = ",".join(details.keys()) if isinstance(details, dict) else "-"
|
||
logger.info(
|
||
"api_request_error method=%s path=%s status=%s code=%s fields=%s message=%s",
|
||
getattr(request, "method", "-"),
|
||
getattr(request, "path", "-"),
|
||
response.status_code,
|
||
code,
|
||
fields,
|
||
message,
|
||
)
|
||
response.data = {
|
||
"error": {
|
||
"code": code,
|
||
"message": message,
|
||
"details": details,
|
||
"request_id": getattr(request, "request_id", None),
|
||
}
|
||
}
|
||
return response
|