为什么在前面使用UWSGI时Flask logger无法登录docker?

时间:2018-07-13 06:35:51

标签: python docker logging flask uwsgi

我在Flask内部有一个Docker应用程序,该应用程序在运行时没有前面的docker logs时登录到UWSGI。现在,我将UWSGI与下面的配置结合使用,以在Docker内运行我的应用程序:

[uwsgi]

master = true

processes = 5
threads = 2

socket = 127.0.0.1:3031
chmod-socket = 664
stats=0.0.0.0:30310

chdir = /etc/fantas

uid = root
gid = root

wsgi-file=uwsgi_fantas.py
callable=app

vacuum = true

uwsgi_fantas.py文件包含:

from fantas.fantas_app import FantasApp

app = FantasApp().setup()

setup方法返回app

from flask_restful import Api
from fantas import app

class FantasApp(object):
    def setup(self):
        api = Api(app)
        api.add_resource(Token, '/users')

        return app

最后,启动Flask框架的部分在项目的根目录中的__init__.py内部:

from flask import Flask
import logging

app = Flask(__name__)

s_handler = logging.StreamHandler()
s_handler.setLevel(logging.DEBUG)
app.logger.addHandler(s_handler)

由于UWSGI直接与app内配置的__init__.py对象一起工作,但是问题在于,当DockerUWSGI时,它不会将任何内容记录到app.logger.setLevel(logging.DEBUG)中运行,它只记录Flask个请求。

app.logger配置过程中出了什么问题?

问题已解决,但现在日志已重复!


EDIT-1: 我设置了Docker,看来app.logger.setLevel(logging.DEBUG) 已成功登录proj_fantas.1.huagnqqpzo1n@linuxkit-025000000001 | [2018-07-13 07:02:38,008] DEBUG in token: [Token] authenticating user... proj_fantas.1.huagnqqpzo1n@linuxkit-025000000001 | DEBUG:flask.app:[Token] authenticating user... 。奇怪的是它记录了3次!我删除了所有记录器配置和处理程序,仅使用了它:

app.logger.handlers

但是现在它记录了2次:

[<logging.StreamHandler object at 0x7f0f430ca8d0>]

为什么会这样?


EDIT-2:

ps -ef的输出为Docker。它只是显示了我之前初始化的StreamHandler,仅此而已。


EDIT-3:

UID PID PPID C STIME TTY TIME CMD root 1 0 0 15:26 ? 00:00:00 uwsgi uwsgi_coconuty.ini root 10 1 0 15:26 ? 00:00:00 uwsgi uwsgi_coconuty.ini root 12 1 0 15:26 ? 00:00:00 uwsgi uwsgi_coconuty.ini root 13 1 0 15:26 ? 00:00:00 uwsgi uwsgi_coconuty.ini root 15 1 0 15:26 ? 00:00:00 uwsgi uwsgi_coconuty.ini root 16 1 0 15:26 ? 00:00:00 uwsgi uwsgi_coconuty.ini root 20 0 0 15:27 pts/0 00:00:00 /bin/bash root 112 20 0 15:28 pts/0 00:00:00 ps -ef Docker命令的输出:

HWND

if (pUIAutomation) { IUIAutomationElement *e = nullptr; auto hr = pUIAutomation->ElementFromHandle(hwnd, &e); } 内部没有其他进程在运行。

2 个答案:

答案 0 :(得分:2)

首先,例如,Flask日志从版本0.9初始化到当前稳定的1.0.2的方式发生了一些变化。您可以检查此here。我假设您的Docker映像使用最新版本。

如果是这种情况,即使没有任何自定义日志配置,实际上它正在为您的输出流进行日志记录,但它的过滤率低于警告日志(DEBUG和INFO)。当您依靠Flask为您初始化日志并且没有设置--debug标志(uwsgi情况)时,会发生这种情况。

配置日志记录时可以查看多种策略。一种建议是在定义应用程序之前,先在uwsgi主机上使用library itself提到的dictConfig初始化,然后将其派生。按照您的示例,在__init__.py

from flask import Flask
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',
        'formatter': 'default'
    }},
    'root': {
        'level': 'DEBUG',
        'handlers': ['wsgi']
    }
})

app = Flask(__name__)

您在 EDIT-1 中提到的问题看起来像是Python logging propagation issue。有一个独立的案例,here更易于调试。

即使您只设置了一个流处理程序,如您的日志所示,它也可能附加了一个父级。如果您检查其父级,则可能会与您在 EDIT-2 中提到的处理程序不同相连。 :

print logger.handlers
[<logging.StreamHandler object at 0x7f15669c1550>]
print logger.parent.handlers
[<logging.StreamHandler object at 0x7f15669c1610>]

当启用日志记录传播并且在其他地方发生了一些日志记录初始化时,会发生这种情况。您可以通过查看python's source code中的callHandlers来检查传播方式:

    ...
    hdlr.handle(record)
    if not c.propagate:
        c = None    #break out
    else:
        c = c.parent
    ...

回到案例(Flask),通过查看日志中的踪迹,可以找到一个名为flask.app的记录器,它是由Flask itself创建的。有格式化的版本和未格式化的版本(logging.BASIC_FORMAT)。因此,它可能已在代码中的某个位置或导入的库之一中初始化了。

有多种方法可以解决此问题:

  • 将传播设置为false(简单的解决方法,但解决方法)
  • 搜索“无效”配置并将其删除
  • 按照Flask日志记录教程的建议,在实例化应用程序之前使用dictConfig初始化

答案 1 :(得分:0)

我有一个类似的问题(特殊:我想使用系统日志)。首先,我必须向Dockerfile添加一条规则:

RUN apt-get install -y rsyslog
service rsyslog start

Flask带有内置日志记录,因此我只需要添加一些树枝

from flask import Flask
import logging
import logging.handlers

handler = logging.handlers.SysLogHandler(address = '/dev/log')
handler.setFormatter(logging.Formatter('flask [%(levelname)s] %(message)s'))

app = Flask(__name__)
app.logger.addHandler(handler)

其他设置可以通过syslog-daemon处理