Фреймворк 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)