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

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)

Если вы не настроите ведение журнала, уровень журнала по умолчанию в Python обычно равен „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 автоматически добавит 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 или собственный именованный регистратор. Для получения подробной информации обратитесь к документации каждого расширения.

Вернуться на верх