Python中在Web框架里如何正确配置和使用logging模块?

比如
有一个接口,我会记录用户的请求数据 dataA,比如 querystring 再加其他一些数据,
但是我又不想把 dataA 直接用 print
输出到 sys.stdout 里面去,因为这样 dataA 并不好找,所以我就用了 FileRotateHandler,并设置文件最大为 50M,
然而这样会产生一个问题就是,当我用 supervisor 启动多个 web 进程的时候,我发现有许多日志文件大为在 5M 
的时候就被切割出来了。如果要解决这种问题是不是只有使用队列这一种方式呢


Python中在Web框架里如何正确配置和使用logging模块?

7 回复

一般框架都会自带 log 模块吧


在Web框架里配置logging,核心是尽早初始化、统一配置。以Flask为例,最稳妥的做法是在应用工厂函数里配置,确保在任何请求之前logger就绪。

# app/__init__.py
import logging
from logging.config import dictConfig
from flask import Flask

def create_app():
    app = Flask(__name__)
    
    # 必须在应用实例化后立即配置logging
    dictConfig({
        'version': 1,
        'formatters': {
            'default': {
                'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
            }
        },
        'handlers': {
            'wsgi': {
                'class': 'logging.StreamHandler',
                'stream': 'ext://flask.logging.wsgi_errors_stream',
                'formatter': 'default'
            },
            'file': {
                'class': 'logging.handlers.RotatingFileHandler',
                'filename': 'app.log',
                'maxBytes': 1024 * 1024,
                'backupCount': 3,
                'formatter': 'default'
            }
        },
        'root': {
            'level': 'INFO',
            'handlers': ['wsgi', 'file']
        }
    })
    
    # 移除Flask默认handler,避免重复日志
    app.logger.handlers.clear()
    # 让app.logger使用我们配置的root logger
    app.logger = logging.getLogger()
    
    return app

关键点:

  1. dictConfigfileConfig一次性配置所有logger,避免多个模块各自配置
  2. 配置完成后才导入业务模块,这样模块内的logging.getLogger(__name__)会自动继承配置
  3. 生产环境考虑添加邮件handler或集中式日志服务handler

对于Django,在settings.py里配置LOGGING字典;FastAPI则在启动时配置,原理相同。

总结:在应用入口一次性配置,让所有模块共享配置。

log 模块无法处理由于多个 supervisor 进程 导致的多进程问题吧,除非让 supervisor 来处理

不懂 python。你可以 log 到 rsyslog,然后用 logrotate 分割 log 文件

我一般采用下面两种方法:

1. 日志直接输出到 stdout,如直接 print 或者 logging.StreamHandler,然后配置 supervisor 的 stdout_logfile 来将标准输出记录到文件

2. FileRotateHandler 不是进程安全的,多个进程使用会在切文件的时候产生竞争,造成文件切的大小不准确,可以实现一个多进程安全的 RotatingFileHandler

https://gist.github.com/SerhoLiu/a3d7be43df882af80ef98bc375fc6046.js

就是不能输出到 stdout 里面呀,因为这个日志要单独保存。。方便日后查看

FileRotateHandler 不是进程安全的。
用 WatchedFileHandler 来写日志,多个进程可以写同一个日志文件。
有切日志的需求,用 logrotate 来切。

回到顶部