python-3.x 使用Gunicorn记录Flask应用程序

qltillow  于 2023-10-21  发布在  Python
关注(0)|答案(1)|浏览(149)

我正在学习Python和Flask,现在我需要一些社区帮助。
我已经为我目前工作的同事构建了一个非常简单的Flask应用程序。它运行在Ubuntu机器上的Docker中,在nginx后面,数据库是Postresql。应用程序由gunicorn使用此命令提供服务。

exec gunicorn -b :5000 --access-logfile - --error-logfile - base_habilis:app

一般来说,我遵循Miguel Grinberg教程,根据Flask和依赖库文档和其他一些来源进行了一些添加和修复。它工作运行和工作得很好。
现在我遇到了一些日志问题。Flask有内置的日志记录器,可以记录几乎所有的活动。
在那之后,我尝试配置我自己的日志格式并添加一些自定义日志消息(例如在错误处理程序中),所以我的问题从这里开始。
我遵循官方Flask文档并添加了此配置(从doc复制粘贴):

from logging.config import dictConfig

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'
    }},
    'root': {
        'level': 'INFO',
        'handlers': ['wsgi']
    }
})

def create_app():
    app = Flask(__name__)
    # and all other inits

404错误处理器

def save_logs(error):
    current_app.logger.info('Failed endpoint - ' + request.url)
    current_app.logger.error(error.code, exc_info=True)

@bp.app_errorhandler(NotFound)
def not_found_error(error: NotFound):
    save_logs(error)
    response = {
        'code': error.response['ResponseMetadata']['HTTPStatusCode'],
        'message': error.response['Error']['Message'],
        'tb': traceback.format_exc()
    }
    return render_template('errors/base_error.html', response=response)

如果我运行这个 flask 应用程序与内置的开发服务器flask run-一切工作正常:我看到完整的日志输出在我的新格式.

[2023-10-09 11:40:23,680] INFO in _internal: 127.0.0.1 - - [09/Oct/2023 11:40:23] "GET /das HTTP/1.1" 404 -
[2023-10-09 11:40:23,701] INFO in _internal: 127.0.0.1 - - [09/Oct/2023 11:40:23] "GET /static/styles.css HTTP/1.1" 304 -
[2023-10-09 11:40:23,722] INFO in _internal: 127.0.0.1 - - [09/Oct/2023 11:40:23] "GET /static/sad_face.png HTTP/1.1" 200 -
[2023-10-09 11:40:44,726] INFO in _internal: 127.0.0.1 - - [09/Oct/2023 11:40:44] "GET /index HTTP/1.1" 200 -
[2023-10-09 11:40:44,751] INFO in _internal: 127.0.0.1 - - [09/Oct/2023 11:40:44] "GET /static/styles.css HTTP/1.1" 304 -
[2023-10-09 11:40:44,756] INFO in _internal: 127.0.0.1 - - [09/Oct/2023 11:40:44] "GET /static/favicon.ico HTTP/1.1" 304 -
[2023-10-09 11:40:54,009] INFO in handlers: Failed endpoint - some_endpoint
[2023-10-09 11:40:54,010] ERROR in handlers: 404
Traceback (most recent call last):
#etc

但是如果我用Gunicorn运行它,它运行得很好,但是我只能看到我的自定义错误处理程序的日志(以及打印)

[2023-10-09 12:26:28 +0300] [8286] [INFO] Starting gunicorn 21.2.0
[2023-10-09 12:26:28 +0300] [8286] [INFO] Listening at: http://127.0.0.1:5000 (8286)
[2023-10-09 12:26:28 +0300] [8286] [INFO] Using worker: sync
[2023-10-09 12:26:28 +0300] [8287] [INFO] Booting worker with pid: 8287
[2023-10-09 12:26:39,413] INFO in handlers: Failed endpoint - some_endpoint
[2023-10-09 12:26:39,414] ERROR in handlers: 404
Traceback (most recent call last):
# blabla

有趣的是,即使我删除了这个自定义日志配置-我在错误处理程序中的日志消息仍然保持这种自定义格式。

(venv) antonstrokov@https://base-habilis ia_ras_anthropology % gunicorn -b 127.0.0.1:5000 --access-logfile - --error-logfile - base_habilis:app
[2023-10-09 12:27:58 +0300] [8338] [INFO] Starting gunicorn 21.2.0
[2023-10-09 12:27:58 +0300] [8338] [INFO] Listening at: http://127.0.0.1:5000 (8338)
[2023-10-09 12:27:58 +0300] [8338] [INFO] Using worker: sync
[2023-10-09 12:27:58 +0300] [8339] [INFO] Booting worker with pid: 8339
127.0.0.1 - - [09/Oct/2023:12:28:03 +0300] "GET /index HTTP/1.1" 200 3952 "some_endpoint" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15"

# other requests logs in default gunicorn format

# my custom error logs with already removed (!) formatting

[2023-10-09 12:28:13,216] INFO in handlers: Failed endpoint - some_endpoint
[2023-10-09 12:28:13,216] ERROR in handlers: 404

在我看来,这个自定义配置存储在缓存中的某个地方,gunicorn不会捕获请求/响应日志?在这一点上,我的知识,我无法调试这个问题,由我自己。
所以,我的问题是-我如何也可以记录默认的flask请求/响应输出与gunicorn和自定义日志格式?
我知道,nginx也记录了每个请求/响应,我可以从中获取这些信息,但我试图理解
1.它是如何工作
1.我想有一个格式的日志可能在未来的解析

到目前为止,我尝试了:

我在dict处理程序中为stream尝试了许多选项,如sys.stdoutsys.stderr等。- 没什么帮助
我试图删除所有的pycache文件夹和文件,然后我甚至删除和重新安装venv文件夹(至少试图理解-为什么它保持我的自定义日志格式的一些日志条目?)-问题仍然存在
我从flask文档中了解到,有一个'werkzeug' logger,它记录了这个基本的req/resp活动。我试图在conf中用相同的处理程序显式地定义它:

'werkzeug': {
        'level': 'DEBUG',
        'handlers': ['wsgi']
    }

但也没用
我还尝试了一些解决方案,从这个thread-像添加--capture-output标志或重新定义gunicorn.error记录器-也没有成功

ss2ws0br

ss2ws0br1#

您看不到gunicorn access日志的原因:
您正在覆盖gunicorn worker中的日志记录配置
让我们做一个小测试:

import logging.config

DEFAULT_LOGGING = {
    'version': 1,
    'loggers': {'': {'level': 'DEBUG'}}
}

logging.config.dictConfig(DEFAULT_LOGGING)
logging.debug('DEBUG LEVEL')

# let's change log level and call dictConfig one more time
DEFAULT_LOGGING['loggers']['']['level'] = 'INFO'
logging.config.dictConfig(DEFAULT_LOGGING)

logging.debug('DEBUG LEVEL')

您将看到唯一的一条消息-DEBUG:root:DEBUG LEVELgunicorn也是一样:

# base_habilis.py
from logging.config import dictConfig
from flask import Flask

app = Flask(__name__)

dictConfig({'version': 1, 'root': {'level': 'INFO', 'handlers': []}})

@app.route('/test')
def test():
    return 'ok'

运行服务器gunicorn -p app.pid -w 1 --access-logfile - --capture-output --log-level debug 'base_habilis:app'并从新终端调用API:

curl http://localhost:8000/test
curl http://localhost:8000/

您不会看到访问日志:

[2023-10-16 17:29:18 +0200] [251581] [INFO] Starting gunicorn 21.2.0
[2023-10-16 17:29:18 +0200] [251581] [DEBUG] Arbiter booted
[2023-10-16 17:29:18 +0200] [251581] [INFO] Listening at: http://127.0.0.1:8000 (251581)
[2023-10-16 17:29:18 +0200] [251581] [INFO] Using worker: sync
[2023-10-16 17:29:18 +0200] [251582] [INFO] Booting worker with pid: 251582
[2023-10-16 17:29:18 +0200] [251581] [DEBUG] 1 workers

现在让我们跳过dictConfig(...),重新启动服务器并再次调用API:

[2023-10-16 17:31:28 +0200] [252523] [INFO] Starting gunicorn 21.2.0
[2023-10-16 17:31:28 +0200] [252523] [DEBUG] Arbiter booted
[2023-10-16 17:31:28 +0200] [252523] [INFO] Listening at: http://127.0.0.1:8000 (252523)
[2023-10-16 17:31:28 +0200] [252523] [INFO] Using worker: sync
[2023-10-16 17:31:28 +0200] [252524] [INFO] Booting worker with pid: 252524
[2023-10-16 17:31:28 +0200] [252523] [DEBUG] 1 workers
[2023-10-16 17:31:32 +0200] [252524] [DEBUG] GET /test
127.0.0.1 - - [16/Oct/2023:17:31:32 +0200] "GET /test HTTP/1.1" 200 2 "-" "curl/7.81.0"
[2023-10-16 17:31:35 +0200] [252524] [DEBUG] GET /
127.0.0.1 - - [16/Oct/2023:17:31:35 +0200] "GET / HTTP/1.1" 404 207 "-" "curl/7.81.0"

因此,您只需重置gunicorn logger configuration(请参阅:Logger.setup()方法或dictConfig用法)。
如何解决这个问题
1.您可以在不使用dictConfig的情况下配置应用程序记录器
1.您可以将disable_existing_loggers设置为 FalsedictConfig({'disable_existing_loggers': False, ...})

相关问题