当 运行 在 gunicorn 中时,Flask 应用程序记录器不工作
Flask app logger not working when running within gunicorn
我正在尝试将来自一个非常简单的 Flask 应用程序的应用程序日志消息保存在日志文件中。虽然当我 运行 将应用程序与嵌入式 Flask 服务器连接时这可以完美地工作,但是当 运行 在 gUnicorn 中连接时它根本不起作用,基本上,没有应用程序输出被重定向,日志文件(在我的 Flask 应用程序中指定的那个)或在 运行ning gunicorn 时发送到 STDOUT。
也就是说,这是我的 Flask 应用程序:
@app.route('/')
def index():
app.logger.debug('Into /!!!!')
print 'Will this print?'
return 'Flask is running!'
if __name__ == '__main__':
#Setup the logger
file_handler = FileHandler('test.log')
handler = logging.StreamHandler()
file_handler.setLevel(logging.DEBUG)
handler.setLevel(logging.DEBUG)
file_handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'))
handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'))
app.logger.addHandler(handler)
app.logger.addHandler(file_handler)
app.run(debug=True)
现在,如果我以以下方式启动应用程序:
python app.py
我得到了预期的输出:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
--------------------------------------------------------------------------------
DEBUG in app [app.py:23]:
Into /!!!!
--------------------------------------------------------------------------------
2015-03-11 09:36:18,375 DEBUG: Into /!!!! [in app.py:23]
Will this print?
127.0.0.1 - - [11/Mar/2015 09:36:18] "GET / HTTP/1.1" 200 -
拖尾test.log,我看到了:
2015-03-11 09:36:18,375 DEBUG: Into /!!!! [in app.py:23]
到目前为止一切看起来都很棒,然后当我尝试 运行 使用 nginx + gunicorn 的应用程序时,首先我尝试 运行 gunicorn 是这样的:
gunicorn app:app -b localhost:8000 --debug --log-level debug
如果我转到 http://localhost:
,应用程序正在运行
curl http://localhost
Flask is running!
但是查看日志文件,是空的,什么都没有写。我加了777权限只是为了检查是不是权限问题没有用。然后查看 gunicorn stdout,除了 print 语句外什么都没有写:
2015-03-11 09:42:06 [25641] [DEBUG] GET /
Will this print?
Looking around,我尝试将所有输出重定向到 gunicorn 日志,然后像这样启动 gunicorn:
gunicorn app:app -b localhost:8000 --debug --log-file /tmp/test.log --log-level debug --error-logfile /tmp/error.log
但现在我什至没有在 gunicorn 文件中得到打印语句,这是 test.log 和 error.log 的输出(它们是相同的):
2015-03-11 09:46:17 [26257] [DEBUG] tmp_upload_dir: None
2015-03-11 09:46:17 [26257] [DEBUG] keyfile: None
2015-03-11 09:46:17 [26257] [DEBUG] backlog: 2048
2015-03-11 09:46:17 [26257] [DEBUG] logger_class: simple
2015-03-11 09:46:17 [26257] [INFO] Starting gunicorn 17.5
2015-03-11 09:46:17 [26257] [DEBUG] Arbiter booted
2015-03-11 09:46:17 [26257] [INFO] Listening at: http://127.0.0.1:8000 (26257)
2015-03-11 09:46:17 [26257] [INFO] Using worker: sync
2015-03-11 09:46:17 [26262] [INFO] Booting worker with pid: 26262
2015-03-11 09:48:15 [26262] [DEBUG] GET /
有一个非常相似的问题here,其中一个答案似乎表明在 gunicorn 中 运行nning 时没有可用的应用程序记录器???至少,这听起来很奇怪...那我应该如何登录?
另一个 proposed solution 似乎建议不要使用 Flask 记录器,但与 gunicorn 无关(我认为)...
我错过了什么?我应该放弃 gunicorn 转而使用 Apache-mod wsgi 吗? Nginx-uWSGI?快速CGI?有什么想法吗?
谢谢!
亚历杭德罗
编辑:
我已经用 uWGSI 代替 gunicorn 尝试了这个完全相同的设置和相同的行为,没有获得任何应用程序日志记录。
现在基于 this response and this other one,我想到了这个(在 gUnicorn 和 uWSGI 上,两者都有效)
from flask import Flask
import logging
from logging import Formatter, FileHandler
app = Flask(__name__)
LOGGER = logging.getLogger('whatever')
file_handler = FileHandler('test.log')
handler = logging.StreamHandler()
file_handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'
))
handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'
))
LOGGER.addHandler(file_handler)
LOGGER.addHandler(handler)
LOGGER.setLevel(logging.INFO)
@app.route('/')
def hello():
LOGGER.info('info log')
LOGGER.debug('debug log')
return 'Hello!'
if __name__ == '__main__':
app.run()
gunicorn 的输出:
2015-03-11 12:25:01 [11540] [INFO] Starting gunicorn 17.5
2015-03-11 12:25:01 [11540] [INFO] Listening at: http://127.0.0.1:8000 (11540)
2015-03-11 12:25:01 [11540] [INFO] Using worker: sync
2015-03-11 12:25:01 [11545] [INFO] Booting worker with pid: 11545
2015-03-11 12:26:20,765 INFO: info log [in /home/mosquito/www/flask-project/flask-project/app.py:24]
并查看我的 test.log 文件:
2015-03-11 12:26:20,765 INFO: info log [in /home/mosquito/www/flask-project/flask-project/app.py:24]
所以是的,它有点管用,但最初的问题仍然存在...为什么当 运行在 wsgi 容器 - gunicorn、uWSGI 中时 Flask 记录器似乎不起作用?
Flask 使用 Werkzeug for WSGI. The "Flask logs" you see are actually from Werkzeug's builtin development 服务器而不是 Flask 本身。
当您用 Gunicorn 或 uWSGI 之类的东西替换那个开发服务器时,您看不到它的日志。
调试器也是如此。即使只用Werkzeug's Debugger.
也能看到熟悉的"Flask debug page"
现在你知道了。 :)
您在这里自己回答了您的问题。虽然我会添加我的答案,希望它能帮助其他有类似问题的人。
由于你的问题有两部分,第一部分已经解决了,我对每一部分的回答做标记:
第 1 部分:如果不是通过 python 直接 运行 应用程序,而是 运行 它在 gunicorn 下,则不会发生日志记录
这是因为,当直接 运行ning 时,name == 'main' 为 True,并且您的代码同时初始化了一个 FileHandler和一个 StreamHandler,并且日志记录有效。
但是当 运行 通过 gunicorn 时,name == 'main' 会失败,因为 name 然后将包含您的模块的名称。这意味着不会初始化 effective 处理程序。因此没有日志记录。
第 2 部分:为什么 Flask 记录器在 gunicorn/uWSGI 下默认不工作
最新的 flask 版本从头开始初始化 app.logger,并根据 app.debug==True 是否默认附加一些处理程序,如 DebugHandler、StreamHandler。记录器仍然不够,只会记录到 STDERR。
在过去的几个版本中,gunicorn 发生了多处变化。
版本 19.4.1 不会将 STDOUT 和 STDERR 捕获到 gunicorn error.log。
但它确实提供了名称为 'gunicorn'、'gunicorn.access' 和 'gunicorn.error' 的记录器。最后一个有一个 FileHandler 写入配置的 error.log。
如果您希望 Flask 应用程序的日志转到 error.log,请使用以下方法之一:
方法一:
#only use gunicorn.error logger for all logging
LOGGER = logging.getLogger('gunicorn.error')
LOGGER.info('my info')
LOGGER.debug('debug message')
# this would write the log messages to error.log
方法二:
# Only use the FileHandler from gunicorn.error logger
gunicorn_error_handlers = logging.getLogger('gunicorn.error').handlers
app.logger.handlers.extend(gunicorn_error_handlers )
app.logger.addHandler(myhandler1)
app.logger.addHandler(myhandler2)
app.logger.info('my info')
app.logger.debug('debug message')
将推荐方法 2,因为除了 gunicorn.error 之外,您还可以保留任何您想要的处理程序。此外,您可以根据条件选择不添加 gunicorn.error 个处理程序。
谢谢
对于 gunicorn 19.6,--capture-output --enable-stdio-inheritance
似乎可以工作。
@Auguiwan的回答确实说明了问题的来源,但没有说到如何解决。@indrajeet的回答很全面,提供了一种解决方案。但是,他们并没有解决我的相关问题。
我的回答主要是想帮助像我一样通过搜索相似关键词"flask gunicorn log"来到这里的人。
我发现这个 link 在相关搜索结果中非常有用
https://medium.com/@yoanis_gil/logging-with-docker-part-1-1-965cb5e17165
部分Gunicorn配置
exec gunicorn ${WSGI_MODULE}:${WSGI_APP} \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=info \
--log-file=/dev/stdout
真的帮了我大忙。核心配置是--log-level
和--log-file
部分。
如果您像我一样使用 supervisored
和 gunicorn.conf
,只需更改相关的 gunicorn.conf
文件即可。
有人可以搜索:将 Flask
与 Gunicorn
结合使用时如何使用 Python
错误堆栈查看错误。
只需将标志 --error-logfile
设置为要查看错误堆栈的文件路径。特别是(在 Docker
中使用时)您可以在 GUNICORN_CMD_ARGS
环境变量中将其设置为下一个值(示例):
--bind=0.0.0.0:8000 --access-logfile=/logs/rest.app/access.log --error-logfile=/logs/rest.app/error.log --capture-output --enable-stdio-inheritance
我正在尝试将来自一个非常简单的 Flask 应用程序的应用程序日志消息保存在日志文件中。虽然当我 运行 将应用程序与嵌入式 Flask 服务器连接时这可以完美地工作,但是当 运行 在 gUnicorn 中连接时它根本不起作用,基本上,没有应用程序输出被重定向,日志文件(在我的 Flask 应用程序中指定的那个)或在 运行ning gunicorn 时发送到 STDOUT。
也就是说,这是我的 Flask 应用程序:
@app.route('/')
def index():
app.logger.debug('Into /!!!!')
print 'Will this print?'
return 'Flask is running!'
if __name__ == '__main__':
#Setup the logger
file_handler = FileHandler('test.log')
handler = logging.StreamHandler()
file_handler.setLevel(logging.DEBUG)
handler.setLevel(logging.DEBUG)
file_handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'))
handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'))
app.logger.addHandler(handler)
app.logger.addHandler(file_handler)
app.run(debug=True)
现在,如果我以以下方式启动应用程序:
python app.py
我得到了预期的输出:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
--------------------------------------------------------------------------------
DEBUG in app [app.py:23]:
Into /!!!!
--------------------------------------------------------------------------------
2015-03-11 09:36:18,375 DEBUG: Into /!!!! [in app.py:23]
Will this print?
127.0.0.1 - - [11/Mar/2015 09:36:18] "GET / HTTP/1.1" 200 -
拖尾test.log,我看到了:
2015-03-11 09:36:18,375 DEBUG: Into /!!!! [in app.py:23]
到目前为止一切看起来都很棒,然后当我尝试 运行 使用 nginx + gunicorn 的应用程序时,首先我尝试 运行 gunicorn 是这样的:
gunicorn app:app -b localhost:8000 --debug --log-level debug
如果我转到 http://localhost:
,应用程序正在运行curl http://localhost
Flask is running!
但是查看日志文件,是空的,什么都没有写。我加了777权限只是为了检查是不是权限问题没有用。然后查看 gunicorn stdout,除了 print 语句外什么都没有写:
2015-03-11 09:42:06 [25641] [DEBUG] GET /
Will this print?
Looking around,我尝试将所有输出重定向到 gunicorn 日志,然后像这样启动 gunicorn:
gunicorn app:app -b localhost:8000 --debug --log-file /tmp/test.log --log-level debug --error-logfile /tmp/error.log
但现在我什至没有在 gunicorn 文件中得到打印语句,这是 test.log 和 error.log 的输出(它们是相同的):
2015-03-11 09:46:17 [26257] [DEBUG] tmp_upload_dir: None
2015-03-11 09:46:17 [26257] [DEBUG] keyfile: None
2015-03-11 09:46:17 [26257] [DEBUG] backlog: 2048
2015-03-11 09:46:17 [26257] [DEBUG] logger_class: simple
2015-03-11 09:46:17 [26257] [INFO] Starting gunicorn 17.5
2015-03-11 09:46:17 [26257] [DEBUG] Arbiter booted
2015-03-11 09:46:17 [26257] [INFO] Listening at: http://127.0.0.1:8000 (26257)
2015-03-11 09:46:17 [26257] [INFO] Using worker: sync
2015-03-11 09:46:17 [26262] [INFO] Booting worker with pid: 26262
2015-03-11 09:48:15 [26262] [DEBUG] GET /
有一个非常相似的问题here,其中一个答案似乎表明在 gunicorn 中 运行nning 时没有可用的应用程序记录器???至少,这听起来很奇怪...那我应该如何登录?
另一个 proposed solution 似乎建议不要使用 Flask 记录器,但与 gunicorn 无关(我认为)...
我错过了什么?我应该放弃 gunicorn 转而使用 Apache-mod wsgi 吗? Nginx-uWSGI?快速CGI?有什么想法吗?
谢谢! 亚历杭德罗
编辑:
我已经用 uWGSI 代替 gunicorn 尝试了这个完全相同的设置和相同的行为,没有获得任何应用程序日志记录。
现在基于 this response and this other one,我想到了这个(在 gUnicorn 和 uWSGI 上,两者都有效)
from flask import Flask
import logging
from logging import Formatter, FileHandler
app = Flask(__name__)
LOGGER = logging.getLogger('whatever')
file_handler = FileHandler('test.log')
handler = logging.StreamHandler()
file_handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'
))
handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'
))
LOGGER.addHandler(file_handler)
LOGGER.addHandler(handler)
LOGGER.setLevel(logging.INFO)
@app.route('/')
def hello():
LOGGER.info('info log')
LOGGER.debug('debug log')
return 'Hello!'
if __name__ == '__main__':
app.run()
gunicorn 的输出:
2015-03-11 12:25:01 [11540] [INFO] Starting gunicorn 17.5
2015-03-11 12:25:01 [11540] [INFO] Listening at: http://127.0.0.1:8000 (11540)
2015-03-11 12:25:01 [11540] [INFO] Using worker: sync
2015-03-11 12:25:01 [11545] [INFO] Booting worker with pid: 11545
2015-03-11 12:26:20,765 INFO: info log [in /home/mosquito/www/flask-project/flask-project/app.py:24]
并查看我的 test.log 文件:
2015-03-11 12:26:20,765 INFO: info log [in /home/mosquito/www/flask-project/flask-project/app.py:24]
所以是的,它有点管用,但最初的问题仍然存在...为什么当 运行在 wsgi 容器 - gunicorn、uWSGI 中时 Flask 记录器似乎不起作用?
Flask 使用 Werkzeug for WSGI. The "Flask logs" you see are actually from Werkzeug's builtin development 服务器而不是 Flask 本身。
当您用 Gunicorn 或 uWSGI 之类的东西替换那个开发服务器时,您看不到它的日志。
调试器也是如此。即使只用Werkzeug's Debugger.
也能看到熟悉的"Flask debug page"现在你知道了。 :)
您在这里自己回答了您的问题。虽然我会添加我的答案,希望它能帮助其他有类似问题的人。
由于你的问题有两部分,第一部分已经解决了,我对每一部分的回答做标记:
第 1 部分:如果不是通过 python 直接 运行 应用程序,而是 运行 它在 gunicorn 下,则不会发生日志记录 这是因为,当直接 运行ning 时,name == 'main' 为 True,并且您的代码同时初始化了一个 FileHandler和一个 StreamHandler,并且日志记录有效。 但是当 运行 通过 gunicorn 时,name == 'main' 会失败,因为 name 然后将包含您的模块的名称。这意味着不会初始化 effective 处理程序。因此没有日志记录。
第 2 部分:为什么 Flask 记录器在 gunicorn/uWSGI 下默认不工作 最新的 flask 版本从头开始初始化 app.logger,并根据 app.debug==True 是否默认附加一些处理程序,如 DebugHandler、StreamHandler。记录器仍然不够,只会记录到 STDERR。 在过去的几个版本中,gunicorn 发生了多处变化。 版本 19.4.1 不会将 STDOUT 和 STDERR 捕获到 gunicorn error.log。 但它确实提供了名称为 'gunicorn'、'gunicorn.access' 和 'gunicorn.error' 的记录器。最后一个有一个 FileHandler 写入配置的 error.log。 如果您希望 Flask 应用程序的日志转到 error.log,请使用以下方法之一: 方法一:
#only use gunicorn.error logger for all logging
LOGGER = logging.getLogger('gunicorn.error')
LOGGER.info('my info')
LOGGER.debug('debug message')
# this would write the log messages to error.log
方法二:
# Only use the FileHandler from gunicorn.error logger
gunicorn_error_handlers = logging.getLogger('gunicorn.error').handlers
app.logger.handlers.extend(gunicorn_error_handlers )
app.logger.addHandler(myhandler1)
app.logger.addHandler(myhandler2)
app.logger.info('my info')
app.logger.debug('debug message')
将推荐方法 2,因为除了 gunicorn.error 之外,您还可以保留任何您想要的处理程序。此外,您可以根据条件选择不添加 gunicorn.error 个处理程序。
谢谢
对于 gunicorn 19.6,--capture-output --enable-stdio-inheritance
似乎可以工作。
@Auguiwan的回答确实说明了问题的来源,但没有说到如何解决。@indrajeet的回答很全面,提供了一种解决方案。但是,他们并没有解决我的相关问题。
我的回答主要是想帮助像我一样通过搜索相似关键词"flask gunicorn log"来到这里的人。 我发现这个 link 在相关搜索结果中非常有用 https://medium.com/@yoanis_gil/logging-with-docker-part-1-1-965cb5e17165
部分Gunicorn配置
exec gunicorn ${WSGI_MODULE}:${WSGI_APP} \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=info \
--log-file=/dev/stdout
真的帮了我大忙。核心配置是--log-level
和--log-file
部分。
如果您像我一样使用 supervisored
和 gunicorn.conf
,只需更改相关的 gunicorn.conf
文件即可。
有人可以搜索:将 Flask
与 Gunicorn
结合使用时如何使用 Python
错误堆栈查看错误。
只需将标志 --error-logfile
设置为要查看错误堆栈的文件路径。特别是(在 Docker
中使用时)您可以在 GUNICORN_CMD_ARGS
环境变量中将其设置为下一个值(示例):
--bind=0.0.0.0:8000 --access-logfile=/logs/rest.app/access.log --error-logfile=/logs/rest.app/error.log --capture-output --enable-stdio-inheritance