为什么Flask应用程序在Gunicorn托管时不会创建任何日志?

时间:2014-10-26 22:31:30

标签: python logging flask gunicorn

我正在尝试将日志记录添加到使用Flask的Web应用程序。

使用内置服务器(即python3 server.py)托管时,日志记录有效。使用Gunicorn托管时,不会创建日志文件。

重现问题的最简单的代码是:

#!/usr/bin/env python

import logging
from flask import Flask
flaskApp = Flask(__name__)


@flaskApp.route('/')
def index():
    flaskApp.logger.info('Log message')
    print('Direct output')
    return 'Hello World\n'


if __name__ == "__main__":
    logHandler = logging.FileHandler('/var/log/demo/app.log')
    logHandler.setLevel(logging.INFO)
    flaskApp.logger.addHandler(logHandler)
    flaskApp.logger.setLevel(logging.INFO)
    flaskApp.run()

使用以下方法调用应用程序:

gunicorn server:flaskApp -b :80 -w 4
    --access-gfile /var/log/demo/access.log
    --error-logfile /var/log/demo/error.log

在向网站主页发出请求时,会发生以下情况:

  1. 我收到了预期的HTTP 200" Hello World \ n"作为回应。

  2. /var/log/demo/access.log中有一条请求。

  3. /var/log/demo/error.log保持不变(只有引导事件)。

  4. 有"直接输出"终点线。

  5. 没有' /var/log/demo/app.log'。如果我在启动应用程序之前创建文件,则不会修改该文件。

  6. 请注意:

    • 每个人都可以访问(读,写,执行)目录/var/log/demo,因此这不是权限问题。

    • 如果我将StreamHandler添加为第二个处理程序,则仍然没有" Log消息"消息既不在终端,也不在Gunicorn日志文件中。

    • 使用pip3 install gunicorn安装Gunicorn,因此不应与Python版本不匹配。

    发生了什么?

3 个答案:

答案 0 :(得分:29)

当您使用python3 server.py时,您正在运行server3.py脚本。

当您使用gunicorn server:flaskApp ...时,您正在运行gunicorn启动脚本,然后导入模块server并在该模块中查找变量flaskApp。< / p>

自导入server.py后,__name__ var将包含"server",而不是"__main__",因此您的日志处理程序设置代码未运行。

您只需将日志处理程序设置代码移到if __name__ == "__main__":节之外即可。但请确保您保留flaskApp.run(),因为 希望在gunicorn导入server时运行

有关what does if __name__ == “__main__”: do?

的更多信息

答案 1 :(得分:18)

这种方法对我有用:导入Python日志记录模块并添加gunicorn的错误处理程序。然后您的记录器将登录gunicorn错误日志文件:

import logging

app = Flask(__name__)

gunicorn_error_logger = logging.getLogger('gunicorn.error')
app.logger.handlers.extend(gunicorn_error_logger.handlers)
app.logger.setLevel(logging.DEBUG)
app.logger.debug('this will show in the log')

我的Gunicorn启动脚本配置为将日志条目输出到如下文件:

gunicorn main:app \
    --workers 4 \
    --bind 0.0.0.0:9000 \
    --log-file /app/logs/gunicorn.log \
    --log-level DEBUG \
    --reload

答案 2 :(得分:3)

这背后有两个原因:Gunicorn拥有自己的记录器,并通过该机制控制日志级别。解决此问题的方法是添加app.logger.setLevel(logging.DEBUG)。
但是这种方法有什么问题呢?首先,将其硬编码到应用程序本身中。是的,我们可以将其重构为一个环境变量,但是我们有两个不同的日志级别:一个用于Flask应用程序,一个完全独立的用于Gunicorn,它是通过--log-level参数设置的(“调试”,“信息”,“警告”,“错误”和“严重”)。

解决此问题的一个好方法是以下代码段:

import logging
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/')
def default_route():
    """Default route"""
    app.logger.debug('this is a DEBUG message')
    app.logger.info('this is an INFO message')
    app.logger.warning('this is a WARNING message')
    app.logger.error('this is an ERROR message')
    app.logger.critical('this is a CRITICAL message')
    return jsonify('hello world')

if __name__ == '__main__':
    app.run(host=0.0.0.0, port=8000, debug=True)

else:
    gunicorn_logger = logging.getLogger('gunicorn.error')
    app.logger.handlers = gunicorn_logger.handlers
    app.logger.setLevel(gunicorn_logger.level)

引用:Code and Explanation is taken from here