• en
  • Language: ru
  • Documentation version: 1.1.x

Ведение журнала

Flask использует стандартный Python logging. Сообщения о вашем приложении 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 logged in successfully', user.username)
        return redirect(url_for('index'))
    else:
        app.logger.info('%s failed to log in', user.username)
        abort(401)

Базовая конфигурация

Если вы хотите настроить ведение журнала для своего проекта, это следует сделать как можно раньше при запуске программы. Если к 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 автоматически добавит StreamHandler в app.logger. Во время запросов он будет писать в поток, указанный сервером WSGI в environ['wsgi.errors'] (обычно это sys.stderr). Вне запроса он будет вести журнал в sys.stderr.

Удаление обработчика по умолчанию

Если вы настроили логирование после доступа к app.logger, и вам нужно удалить обработчик по умолчанию, вы можете импортировать и удалить его:

from flask.logging import default_handler

app.logger.removeHandler(default_handler)

Ошибки по электронной почте администраторам

При запуске приложения на удаленном сервере для производства вы, вероятно, не будете просматривать сообщения журнала очень часто. Сервер WSGI, вероятно, будет отправлять сообщения журнала в файл, и вы будете проверять этот файл, только если пользователь скажет вам, что что-то пошло не так.

Чтобы быть активным в обнаружении и исправлении ошибок, вы можете настроить 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)

Для этого необходимо, чтобы SMTP-сервер был настроен на том же сервере. Дополнительную информацию о настройке обработчика см. в документации Python.

Информация о запросе на инъекции

Просмотр дополнительной информации о запросе, например, 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)

Другие библиотеки

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

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)

Werkzeug

Werkzeug записывает основную информацию о запросах/ответах в логгер 'werkzeug'. Если корневой регистратор не имеет настроенных обработчиков, Werkzeug добавляет StreamHandler в его регистратор.

Расширения Flask

В зависимости от ситуации, расширение может выбрать ведение журнала в app.logger или в свой собственный именованный регистратор. Для получения подробной информации обратитесь к документации каждого расширения.