Регистратор приложений для фляг не работает при запуске в рамках пушечного ядра

Я пытаюсь сохранить сообщения журнала приложений из очень простого флеш-приложения в файле журнала. Хотя это работает безупречно, когда я запускаю приложение со встроенным сервером Flask, он вообще не работает при запуске в gUnicorn, в основном, никакой вывод приложения не перенаправляется ни на файл журнала (тот, который указан в моем приложении Flask), либо на 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 -

Tailing test.log, я вижу:

2015-03-11 09:36:18,375 DEBUG: Into /!!!! [in app.py:23]

Все выглядит великолепно до сих пор, затем, когда я пытаюсь запустить приложение с nginx + gunicorn, сначала я попытался запустить такой пулемет, как это:

gunicorn app:app -b localhost:8000 --debug --log-level debug

Приложение работает, если я перейду к http://localhost:

curl http://localhost
Flask is running!

Но просмотр файла журнала пуст, ничего не записывается. Я добавил 777 разрешений, чтобы проверить, не было ли это проблемой разрешения. Затем, глядя на артиллерийский выстрел, ничего не пишет помимо заявления печати:

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

Оглядываясь вокруг, я попытался перенаправить все выходные данные в журналы стрельбы, а затем начать стрельбу:

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 /

Существует очень похожий вопрос здесь, один из ответов, по-видимому, говорит о том, что при запуске внутри пушки не существует никакого регистратора приложений??? Это звучит, по крайней мере, довольно странно... как я должен регистрироваться?

Другое предлагаемое решение, по-видимому, предполагает использование флеш-регистратора, но не связано с пушкой (я думаю)...

Что мне не хватает? Должен ли я отказаться от пушки и пойти на Apache-mod wsgi? Nginx-uWSGI? FastCGI? Любые идеи?

Спасибо! Alejandro

EDIT:

Я пробовал эту же настройку с uWGSI, а не с пушкой и таким же поведением, никаких протоколов регистрации приложений не получилось.

Теперь на основе этого ответа и этого другого, я подошел с этим (на 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()

Результат от пушки:

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?

Ответы

Ответ 1

Flask использует Werkzeug для WSGI. "Журналы фляг", которые вы видите, на самом деле находятся на сервере Werkzeug builtin development, а не на самом флаконе.

Когда вы заменяете этот сервер разработки чем-то вроде Gunicorn или uWSGI, вы не видите его журналы.

То же самое относится к отладчику. Вы можете увидеть знакомую "страницу отладки фляг", даже если вы используете Werkzeug Debugger.

Теперь вы знаете.:)

Ответ 2

Вы сами ответили на свой вопрос. Хотя я добавлю свой ответ в надежде, что это поможет кому-то еще иметь подобную проблему.

Так как ваш вопрос состоит из двух частей, из которых первая часть решена, плохо отметите мой ответ для каждой части:

ЧАСТЬ 1: Нет регистрации, если вместо прямого запуска приложения через python вы запускаете его под пулемётом Это произошло потому, что при прямом запуске имя name == < main) имеет значение True, а ваш код инициализируется как FileHandler, так и StreamHandler, и работает работа. Но при запуске через пушки, имя == ' main "не удастся, так как name будет содержать имя вашего модуля. Это означает, что обработчики эффективных не будут инициализированы. И, следовательно, никаких журналов не видно.

ЧАСТЬ 2: Почему регистратор флагов не работает по умолчанию в режиме gunicorn/uWSGI Последние версии фляг инициализируют app.logger с нуля и прикрепляют несколько обработчиков, таких как DebugHandler, StreamHandler по умолчанию в зависимости от того, является ли app.debug == True. Тем не менее, регистратор недостаточно и будет записываться только в STDERR. За последние несколько версий было много изменений в боеприпасе. Версия 19.4.1 не фиксирует STDOUT и STDERR в ошибке gunlogog.log. Но это делает доступными регистраторы с именами "gunicorn", "gunicorn.access" и "gunicorn.error". В последнем случае FileHandler записывает настроенный error.log. Если вы хотите, чтобы журналы из вашего флеш-приложения отображались в файле error.log, используйте один из следующих способов: Approach1:

#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

Approach2:

# 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 на основе условия.

спасибо

Ответ 3

С помощью стрельбы 19.6, --capture-output --enable-stdio-inheritance, похоже, работает.