簡體   English   中英

在 gunicorn 中運行時,Flask 應用程序記錄器不工作

[英]Flask app logger not working when running within gunicorn

我正在嘗試將來自一個非常簡單的燒瓶應用程序的應用程序日志消息保存在日志文件中。 雖然這在我使用嵌入式 Flask 服務器運行應用程序時完美無缺,但在 gUnicorn 中運行時它根本不起作用,基本上,沒有應用程序輸出被重定向,日志文件(在我的 Flask 應用程序中指定的那個)或運行 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 標准輸出,除了打印語句之外什么都沒有寫:

2015-03-11 09:42:06 [25641] [DEBUG] GET /
Will this print?

環顧四周,我嘗試將所有輸出重定向到 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 /

有一個非常類似的問題在這里,其中一個答案似乎表明,gunicorn內捉迷藏時沒有應用程序記錄器可??? 至少,這聽起來很奇怪……那我應該如何登錄?

另一個提議的解決方案似乎建議不使用 Flask 記錄器,但與 gunicorn 無關(我認為)...

我缺少什么? 我應該放棄 gunicorn 並選擇 Apache-mod wsgi 嗎? Nginx-uWSGI? 快速CGI? 有任何想法嗎?

謝謝! 亞歷杭德羅

編輯:

我已經用 uWGSI 而不是 gunicorn 和相同的行為嘗試了這個非常相同的設置,沒有獲得任何應用程序日志記錄。

現在基於這個響應另一個響應,我想出了這個(在 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]

所以是的,它有點工作,但最初的問題仍然存在......為什么 Flask 記錄器在 wsgi 容器中運行時似乎不起作用 - gunicorn,uWSGI?

你在這里自己回答了你的問題。 雖然我會添加我的答案,希望它能幫助其他有類似問題的人。

由於您的問題有 2 個部分,其中第一部分已解決,請在我對每個部分的回復中標記:

第 1 部分:如果不是通過 python 直接運行應用程序,而是在 gunicorn 下運行它,則不會發生日志記錄這是因為,直接運行時,名稱== ' main ' 為 True,並且您的代碼初始化了 FileHandler 和 StreamHandler,和日志工作。 但是當通過 gunicorn 運行時, name == ' main ' 將失敗,因為name將包含您的模塊的名稱。 這意味着不會初始化有效的處理程序。 因此沒有看到日志記錄。

第 2 部分:為什么在 gunicorn/uWSGI 下 Flask 記錄器默認不工作最新的 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,請使用以下方法之一:方法 1:

#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 處理程序。

謝謝

Flask 將Werkzeug用於 WSGI。 您看到的“Flask 日志”實際上來自Werkzeug 的內置開發服務器,而不是來自 Flask 本身。

當你用 Gunicorn 或 uWSGI 之類的東西替換那個開發服務器時,你看不到它的日志。

調試器也是如此。 即使您只使用Werkzeug 的 Debugger ,您也可以看到熟悉的“Flask 調試頁面”。

現在你知道了。 :)

使用 gunicorn 19.6, --capture-output --enable-stdio-inheritance似乎有效。

有人可以搜索: how to see errors with Python error stack when using Flask with Gunicorn

只需將標志--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

@Auguiwan 的回答確實解釋了起源問題,但沒有談到如何解決它。@indrajeet 的回答非常全面,提供了一種解決方案。 但是,它們並沒有解決我的相關問題。

我的回答主要是想幫助像我這樣通過搜索類似關鍵詞“flask gunicorn log”來這里的人。 我發現此鏈接在相關搜索結果中非常有用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部分。
如果您像我一樣使用帶有gunicorn.conf supervisored ,只需更改相關的gunicorn.conf文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM