Фреймворк Flask для ведения журнала логов использует стандартный модуль logging
Python. Сообщения приложения Flask регистрируются с помощью app.logger
, имя которого совпадает с именем app.name
. Этот регистратор также может использоваться для регистрации собственных сообщений.
@app.route('/login', methods=['POST']) def login(): user = get_user(request.form['username']) if user.check_password(request.form['password']): login_user(user) # логирование успешного входа пользователя app.logger.info('%s успешно вошел в систему', user.username) return redirect(url_for('index')) else: # логирование неудачной авторизации app.logger.info('%s не удалось войти в систему', user.username) abort(401)
Если ведение журнала логов в приложении на Flask не настраивалось, то по умолчанию уровень журнала настроен как предупреждение 'warning'
. Следовательно, ниже уровня 'warning'
ничего не будет видно.
Если нужно настроить ведение журнала для своего проекта, то это необходимо делать перед созданием объекта приложения или сразу после его создания. Если доступ к app.logger
осуществляется до настройки ведения журнала, то обработчик по умолчанию добавляется автоматически.
В примере ниже, используется dictConfig()
для создания конфигурации ведения журнала, аналогичной настройке 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', 'stream': 'ext://flask.logging.wsgi_errors_stream', 'formatter': 'default' }}, 'root': { 'level': 'INFO', 'handlers': ['wsgi'] } }) app = Flask(__name__)
Если запустить приложение Flask не настраивая ведение журнала, то Flask автоматически добавит в app.logger
обработчик StreamHandler
. Во время запросов приложение будет записывать логи в поток, указанный сервером WSGI в environment['wsgi.errors']
(обычно это sys.stderr). Вне запроса, сообщения от app.logger
будут регистрироваться в sys.stderr.
Если ведение журнала логов приложения настраивается после доступа к app.logger
и нужно удалить обработчик по умолчанию (который добавился автоматически), то перед удалением, его необходимо импортировать, а затем удалить:
from flask.logging import default_handler app.logger.removeHandler(default_handler)
При работе приложения Flask на удаленном сервере в "боевом" режиме, все сообщения журнала будут записываться в файл и скорее всего не будет возможности постоянного мониторинга этого файла на ошибки.
Чтобы своевременно получать сообщения об ошибках в приложении, можно настроить logging.handlers.SMTPHandler
для отправки электронного письма при регистрации ошибок.
import logging from logging.handlers import SMTPHandler mail_handler = SMTPHandler( mailhost='127.0.0.1', fromaddr='server-error@example.com', toaddrs=['admin@example.com'], subject='Application Error' ) mail_handler.setLevel(logging.ERROR) mail_handler.setFormatter(logging.Formatter( '[%(asctime)s] %(levelname)s in %(module)s: %(message)s' )) if not app.debug: app.logger.addHandler(mail_handler)
Просмотр дополнительной информации о запросе, такой как IP-адрес, может помочь отладить некоторые ошибки. Для добавления собственных полей в сообщения регистратора, можно создать подкласс logging.Formatter
. Таким же способом можно изменить форматирование для обработчика Flask по умолчанию, обработчика сообщений отправляемых на почту, или любого другого обработчика.
from flask import has_request_context, request from flask.logging import default_handler class RequestFormatter(logging.Formatter): def format(self, record): if has_request_context(): record.url = request.url record.remote_addr = request.remote_addr else: record.url = None record.remote_addr = None return super().format(record) formatter = RequestFormatter( '[%(asctime)s] %(remote_addr)s requested %(url)s\n' '%(levelname)s in %(module)s: %(message)s' ) default_handler.setFormatter(formatter) mail_handler.setFormatter(formatter)
Расширения Flask так же могут широко использовать логирование, и что бы увидеть эти сообщения, необходимо добавить соответствующие обработчики к корневому регистратору, а не только к регистратору приложения app.logger
.
from flask.logging import default_handler root = logging.getLogger() root.addHandler(default_handler) root.addHandler(mail_handler)
В зависимости от проекта, бывает полезно настраивать каждый регистратор отдельно, а не только корневой регистратор.
for logger in ( app.logger, logging.getLogger('sqlalchemy'), logging.getLogger('other_package'), ): logger.addHandler(default_handler) logger.addHandler(mail_handler)