drf自定义全局异常及日志记录
封装全局异常的目的有两个:
- 统一后端出现异常时前端收到的响应信息;
- 记录日志【尤其是异常和错误日志】
封装drf全局异常
drf内置的全局异常,只能捕获一部分的异常,其他的异常将会直接交给django处理。我们封装全局异常的一部分原因就是捕获那些drf没有处理的异常。
drf异常处理使用的是内置的exception_handler
方法,我们可以在此基础上捕获那些没有被处理的异常。
因为没有被drf处理的异常在exception_handler
中直接返回None
,因此可以通过该方法的返回值判断需要我们自己处理的异常。
注意:捕获异常时出现异常,是不会被处理的 😦
# utils/exceptions.py
from rest_framework.views import exception_handler
from .response import APIResponse # 自定义Response
from .logger import log # 自定义的日志记录使用方法
def common_exception_handler(exc, context):
# 记录日志
log.error('view是:%s ,错误是%s' % (context['view'].__class__.__name__, str(exc)))
print(context['view'].__class__.__name__)
# 接收内置exception_handler的异常处理结果
ret = exception_handler(exc, context)
if not ret:
# 处理drf未处理的异常
if isinstance(exc, KeyError):
return APIResponse(code=0, msg='key error')
return APIResponse(code=0, msg='error', result=str(exc))
else:
# drf已经处理的异常
return APIResponse(code=0, msg='error', result=ret.data)
全局异常配置
# settings/dev.py 配置文件
REST_FRAMEWORK = {
# 全局配置setting.py
'EXCEPTION_HANDLER': 'Luffyapi.utils.exceptions.common_exception_handler',
}
日志配置
日志模块的使用参考:loggin模块
# settings/dev.py 配置文件
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
},
},
'filters': {
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
# 实际开发建议使用WARNING
'level': 'DEBUG',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'file': {
# 实际开发建议使用ERROR
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
# 日志位置,日志文件名,日志保存目录必须手动创建,注:这里的文件路径要注意BASE_DIR代表的是小luffyapi
'filename': os.path.join(os.path.dirname(BASE_DIR), "logs", "luffy.log"),
# 日志文件的最大值,这里我们设置300M
'maxBytes': 300 * 1024 * 1024,
# 日志文件的数量,设置最大日志数量为10
'backupCount': 100,
# 日志格式:详细格式
'formatter': 'verbose',
# 文件内容编码
'encoding': 'utf-8'
},
},
# 日志对象
'loggers': {
'django': { # 使用该日志
'handlers': ['console', 'file'],
'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统
},
}
}
封装日志
# utils/logger.py
import logging
log = logging.getLogger('django')
使用日志
在封装的全局异常内使用日志
# from Luffyapi.utils.logger import log
log.error('view是:%s ,错误是%s' % (context['view'].__class__.__name__, str(exc)))