Django log integration & MySQL/Redis exception capture

"  Does a qualified developer use print as the main output debugging tool in daily development? Can the exceptions of Python's web development framework Django capture all exceptions of MySQL and Redis? "

This article is aimed at the Django development framework, and other development frameworks can refer to ideas.

 Django logging integration

        First of all, print is seen in the console of IDE such as Pycharm. At the same time, print also consumes performance. Normal running projects will be placed on the server. First, does the server have a console? Second, can so many prints withstand its performance consumption? Running sluggishly is not what we want.

So         the necessity of the log comes (generally, the log is output to one or some files, and the operation and maintenance personnel will need such files), and the control of the overall operation of the project requires the log . In addition, in addition In environments such as Debug, you can output logs to the console. At the same time, the log can provide better, more comprehensive and more structured information.

    

Python's log consists of four parts:

    ① loggers is similar to defining a logger (the code will use its name)

    ② handlers log processing method

    ③ filters log filtering processing

    ④ formatters log information display format

Note that the log levels are divided into five levels on Django's official website:

    DEBUG/INFO/WARNING/ERROR/CRITICAL

    (where INFO is the lowest level)

Logging integrators are configured in the settings.py file in a Django project, or in the dev.py file in a (pre-)development environment.

Configuration similar to the following ↓

#日志
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,  # 是否禁用已经存在的日志器
    'formatters': {  # 日志信息显示的格式
        'verbose': {
 # %s为字符串 %d为整数,levelname代表级别,asctime为时间,module打印模块名称,lineno打印日志级别的数值,message为信息
          'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'   
        },
    },
    'filters': {  # 对日志进行过滤
        'require_debug_true': {  # django在debug模式下才输出日志
          '()': 'django.utils.log.RequireDebugTrue',  # Debug为True
        },
    },
    'handlers': {  # 日志处理方法
        'console': {  # 向终端中输出日志
            'level': 'INFO',   # 输出级别
             # 指定上面写的过滤器(过滤添加为Debug为true才能向控制台输出) 
            'filters': ['require_debug_true'], 
            'class': 'logging.StreamHandler',
            'formatter': 'verbose'  # 输出格式,也是上面写的格式verbose
        },
        'file': {  # 向文件中输出日志
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            # 日志文件的位置(需要创建目录logs),那么就需要BASE_DIR的dirname即上一级目录
            'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/xxx.log"),  
            'maxBytes': 100 * 1024 * 1024,  # 100兆,若超过,则再创建一个,在文件名后加1 2...
            'backupCount': 5,               # 若文件超过五个,将会删除
            'formatter': 'verbose',         # 输出格式,也是上面写的格式verbose
        },
    },
    'loggers': {  # 日志器
        'xxx': {  # 定义了一个名为xxx的日志器(后续获取logger对象的时候会使用到)
            'handlers': ['console', 'file'],  # 可以同时向终端与文件中输出日志
            'propagate': True,  # 是否继续传递日志信息
            'level': 'INFO',  # 日志器接收的最低日志级别
        },
    },
}

Django official website has log details(levelname/model/...)

Django documentation | Django documentation | Django

[ Note : Log files do not need to be uploaded to the code warehouse, and in team development, there will be direct conflicts of mutual coverage]

        For example, the name of the created log folder is logs. .gitignore will ignore all the log files under logs and logs. If you want to upload empty logs, you only need to create the file .gitkeep under the logs folder.

# 日志文件logs/*.log

Django's exception capture for MySQL and Redis

        In fact, Django is not sensitive to special exceptions of MySQL and Redis, which means that no log processing is done, which is obviously very important.

        Maybe you start a Redis that is not cached (it is used in the project), and Redis is not started, but Django can still run normally without reporting errors. The next thing we need to do is to avoid them from happening.

    In actual development, a utils package is generally created, and an exceptions package is created in it to put the py processing file. (This article uses the current mainstream DRF framework)

The idea is: it is equivalent to capturing the uncaught MySQL and Redis exceptions     under the original DRF exception capture mechanism . (Equivalent to adding an extra coat to the exception handling function of DRF, covering drf_exception_handler with our exception_xxx) [xxx can be named]

logger = logging.getLogger('xxx')   # 获取我们前面定义的日志器
# exc: 异常实例对象  context: 抛出异常的上下文
def exception_xxx(exc, context):
    # 调用drf框架原生的异常处理方法(相当于给DRF异常处理函数套一层)
    response = drf_exception_handler(exc, context)    
    # 没有得到响应
    if response is None:
        # 判断是否是MySQL数据库错误或Redis缓存错误
        if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
            # 数据库异常
            logger.error('[%s] %s' % (context['view'], exc))
            # HTTP507状态码代表的意思是服务器无法存储请求
            response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
    return response

    Add REST_FRAMEWORK to the configuration file:

# DRF配置项REST_FRAMEWORK = {
   
       ...    # 异常处理    'EXCEPTION_HANDLER': 'xxx.utils.exceptions.exception_xxx',}

 

[There are more development tips, welcome to pay attention to the official account: All the way to the east]

おすすめ

転載: blog.csdn.net/lxd_max/article/details/127855563