我有一个基于烧瓶的应用程序。在本地运行时,是从命令行运行的,但是在部署时,我是由具有多个工作人员的gunicorn启动的。
我想使用logging
模块登录到文件。我为此找到的文档是https://docs.python.org/3/library/logging.html和https://docs.python.org/3/howto/logging-cookbook.html。
当我的应用程序可能与gunicorn一起启动时,我对使用日志记录的正确方法感到困惑。该文档解决了线程问题,但假设我可以控制主进程。困惑点:
logger = logging.getLogger('myapp')
将在不同的gunicorn工作线程中返回相同的记录器对象吗?
如果我要将日志记录FileHandler
附加到记录器以记录到文件,如何避免在不同的工作程序中多次执行此操作?
我的理解-可能是错误的-是,如果我只调用logger.setLevel(logging.DEBUG)
,它将通过root logger发送消息,该root logger的默认日志记录级别可能更高,并且可能会忽略调试消息,因此我还需要调用logging.basicConfig(logging.DEBUG)
才能使调试消息通过。但是文档说不要从线程调用logging.basicConfig()
。使用gunicorn时如何正确设置根日志记录级别?还是我不需要?
答案 0 :(得分:1)
这是我典型的Flask / Gunicorn设置。注意Gunicorn是通过主管运行的。
wsgi_web.py。注意ProxyFix
,以便从Nginx获取客户端的真实IP地址。
from werkzeug.contrib.fixers import ProxyFix
from app import create_app
import logging
gunicorn_logger = logging.getLogger('gunicorn.error')
application = create_app(logger_override=gunicorn_logger)
application.wsgi_app = ProxyFix(application.wsgi_app, num_proxies=1)
烧瓶应用程序工厂create_app
def create_app(logger_override=None):
app = Flask(__name__)
if logger_override:
app.logger.handlers = logger_override.handlers
app.logger.setLevel(logger_override.level)
# more
return app
主管conf中的Gunicorn命令(第4行),请注意,在这种情况下,--log-level
参数已设置为info
。请注意X-REAL-IP
已通过访问权限--access-logformat
[program:web]
directory = /home/paul/www/example
environment = APP_SETTINGS="app.config.ProductionConfig"
command = /home/paul/.virtualenvs/example/bin/gunicorn wsgi_web:application -b localhost:8000 --workers 3 --worker-class gevent --keep-alive 10 --log-level info --access-logfile /home/paul/www/logs/admin.gunicorn.access.log --error-logfile /home/paul/www/logs/admin.gunicorn.error.log --access-logformat '%%({X-REAL-IP}i)s %%(l)s %%(u)s %%(t)s "%%(r)s" %%(s)s %%(b)s "%%(f)s" "%%(a)s"'
user = paul
autostart=true
autorestart=true
答案 1 :(得分:1)
每个工作程序都是一个独立的进程,具有自己的内存,因此您无法真正在不同工作程序之间共享同一记录器。
您的代码在这些工作程序中运行,因为主流程只关心管理工作程序。
主进程是一个侦听各种进程的简单循环 发出信号并做出相应反应。它管理正在运行的工人列表 通过收听诸如TTIN,TTOU和CHLD之类的信号。 TTIN和TTOU告诉 主人增加或减少在职工人的数量。
在Gunicorn本身中,有两种主要的运行模式
因此与线程处理不同,这是多处理。
但是,自Gunicorn 19起,线程选项可用于处理以下内容中的请求: 多线程。使用线程假定使用了gthread worker。
牢记这一点,记录代码将被编写一次,并且每次创建新工作程序时将被多次调用。您可以使用Singelton模式来确保在同一工作程序中使用同一记录器实例。
对于配置记录器本身,您只需要遵循设置根记录器级别和不同记录器级别的正常过程即可。
basicConfig()不会影响根处理程序(如果已设置):
如果根记录器已经为其配置了处理程序,则此功能不起作用。
要在根目录上显式设置级别
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(name)
然后可以在处理程序或记录器级别上设置级别。
handler = logging.handlers.TimedRotatingFileHandler(log_path, when='midnight', backupCount=30)
handler.setLevel(min_level)
您可以检查此类似答案以记录相关的详细信息 Set logging levels
更多资源: