Почему приложение Flask не создает никаких журналов при размещении в Gunicorn?
Я пытаюсь добавить журнал в веб-приложение, которое использует флажок.
При размещении с использованием встроенного сервера (т.е. python3 server.py
) выполняется ведение журнала. При размещении с использованием Gunicorn файл журнала не создается.
Самый простой код, который воспроизводит проблему, следующий:
#!/usr/bin/env python
import logging
from flask import Flask
flaskApp = Flask(__name__)
@flaskApp.route('/')
def index():
flaskApp.logger.info('Log message')
print('Direct output')
return 'Hello World\n'
if __name__ == "__main__":
logHandler = logging.FileHandler('/var/log/demo/app.log')
logHandler.setLevel(logging.INFO)
flaskApp.logger.addHandler(logHandler)
flaskApp.logger.setLevel(logging.INFO)
flaskApp.run()
Приложение вызывается с использованием:
gunicorn server:flaskApp -b :80 -w 4
--access-gfile /var/log/demo/access.log
--error-logfile /var/log/demo/error.log
При выполнении запроса на домашнюю страницу сайта происходит следующее:
-
Я получаю ожидаемый HTTP 200 "Hello World\n" в ответ.
-
В /var/log/demo/access.log
есть трассировка запроса.
-
/var/log/demo/error.log
остается неизменным (есть только события загрузки).
-
В терминале есть строка "Прямой выход".
-
Нет '/var/log/demo/app.log'. Если я создаю файл перед запуском приложения, файл не будет изменен.
Обратите внимание, что:
-
Доступ к каталогу /var/log/demo
можно получить (чтение, запись, выполнение) всеми, так что это не проблема с разрешениями.
-
Если я добавлю StreamHandler
в качестве второго обработчика, по-прежнему нет следа сообщения "Сообщение журнала" ни в терминале, ни в файлах журнала Gunicorn.
-
Gunicorn устанавливается с помощью pip3 install gunicorn
, поэтому не должно быть никакого несоответствия с версиями Python.
Что происходит?
Ответы
Ответ 1
Когда вы используете python3 server.py
, вы запустите server3.py script.
Когда вы используете gunicorn server:flaskApp ...
, вы запускаете запуск gunicorn script, который затем импортирует модуль server
и ищет переменную flaskApp
в этом модуле.
Поскольку server.py
импортируется, __name__
var будет содержать "server"
, а не "__main__"
, и поэтому код установки обработчика журнала не запускается.
Вы можете просто переместить код настройки обработчика журнала за пределы if __name__ == "__main__":
. Но убедитесь, что вы держите flaskApp.run()
там, так как вы не хотите, чтобы это было запущено, когда увольняющий противник импортировал server
.
Подробнее о что делает if __name__ == "__main__":
?
Ответ 2
Этот подход работает для меня: импортируйте модуль протоколирования Python и добавьте к нему обработчики ошибок gunicorn. Затем ваш регистратор войдет в файл журнала ошибок gunicorn:
import logging
app = Flask(__name__)
gunicorn_error_logger = logging.getLogger('gunicorn.error')
app.logger.handlers.extend(gunicorn_error_logger.handlers)
app.logger.setLevel(logging.DEBUG)
app.logger.debug('this will show in the log')
My Gunicorn startup script настроен для вывода записей журнала в файл следующим образом:
gunicorn main:app \
--workers 4 \
--bind 0.0.0.0:9000 \
--log-file /app/logs/gunicorn.log \
--log-level DEBUG \
--reload