ログ処理(Logging) Logging

Flaskは標準的なPythonのloggerを使用します。Flaskアプリケーションに関するメッセージは、app.nameと同じ名前を取り入れたapp.loggerを使ってログされます。このloggerは自分独自のメッセージをログするためにも使用されます(訳注: Flask自体のログだけでなく、Flaskアプリ開発者がアプリのログを出力するためにも使用するという意味合いだと思います)。 Flask uses standard Python :mod:`logging`. Messages about your Flask application are logged with :meth:`app.logger <flask.Flask.logger>`, which takes the same name as :attr:`app.name <flask.Flask.name>`. This logger can also be used to log your own messages.

@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)

基本設定(Basic Configuration) Basic Configuration

自分のプロジェクト用にログ処理を設定したいときは、プログラム開始時に出来るだけ早く実施するべきです。もしログ処理を設定する前にapp.loggerが使われたときは、標準の処理器(handler)が追加されます。可能であれば、アプリケーションのオブジェクトを作成する前にログ処理を設定してください。 When you want to configure logging for your project, you should do it as soon as possible when the program starts. If :meth:`app.logger <flask.Flask.logger>` is accessed before logging is configured, it will add a default handler. If possible, configure logging before creating the application object.

以下の例では、全てのログを対象にしていること以外はFlaskの標準設定と似たログ処理設定を作成するために、dictConfig()を使用しています: This example uses :func:`~logging.config.dictConfig` to create a logging configuration similar to Flask's default, except for all logs::

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__)

Default Configuration

もし自分度ログ処理設定をしない場合、Flaskはapp.loggerStreamHandlerを自動的に追加するでしょう。リクエストの処理中は、WSGIサーバによってenvironment['wsgi.errors']で指定されたストリーム(普通はsys.stderrです)へ書き込みます。リクエストの外側では、sys.stderrへログします。 If you do not configure logging yourself, Flask will add a :class:`~logging.StreamHandler` to :meth:`app.logger <flask.Flask.logger>` automatically. During requests, it will write to the stream specified by the WSGI server in ``environ['wsgi.errors']`` (which is usually :data:`sys.stderr`). Outside a request, it will log to :data:`sys.stderr`.

標準の処理器(Handler)の除去 Removing the Default Handler

もしapp.loggerへアクセスした後でログ処理設定をし、標準のhandlerを取り除く必要がある場合、それをimportしてremoveできます(訳注: 以下のコード例で「import」「remove~」とあるような処理ができます): If you configured logging after accessing :meth:`app.logger <flask.Flask.logger>`, and need to remove the default handler, you can import and remove it::

from flask.logging import default_handler

app.logger.removeHandler(default_handler)

管理者へのエラーのメール送信 Email Errors to Admins

本番環境用に遠隔サーバでアプリケーションを走らせているとき、おそらくあなたはそれほど頻繁にログメッセージを調べようとはしないでしょう。WSGIサーバはおそらくログメッセージをファイルへ送り、もしもユーザが何か上手くいってないと伝えたときだけ、ログをチェックするでしょう。 When running the application on a remote server for production, you probably won't be looking at the log messages very often. The WSGI server will probably send log messages to a file, and you'll only check that file if a user tells you something went wrong.

バグの発見と修正に関して先手を取れるよう、エラーもしくはより重大なことがログされたときにはメールを送信するためのlogging.handlers.SMTPHandlerを設定できます。: To be proactive about discovering and fixing bugs, you can configure a :class:`logging.handlers.SMTPHandler` to send an email when errors and higher are logged. ::

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サーバが準備されていることが必要です。このhandlerの設定に関するさらなる情報についてはPythonのドキュメントを見てください。 This requires that you have an SMTP server set up on the same server. See the Python docs for more information about configuring the handler.

リクエストの情報の注入 Injecting Request Information

例えばIPアドレス等、リクエストに関する情報をもっと見ることは、いくらかのエラーのデバッグする手助けになることがあります。メッセージ中で使用可能になる独自のフィールドを注入するために、logging.Formatterのサブクラスを作成できます。Flaskの標準handler、先ほど定義したメールのhandler、およびあらゆるその他のhandlerに対してformatterを変更できます。: Seeing more information about the request, such as the IP address, may help debugging some errors. You can subclass :class:`logging.Formatter` to inject your own fields that can be used in messages. You can change the formatter for Flask's default handler, the mail handler defined above, or any other handler. ::

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)

他のライブラリ Other Libraries

他のライブラリでloggingを広く使用していて、それらのログからも関連するメッセージを見たくなることがあるかもしれません。これを行う最も単純なやり方は、app.loggerにだけhandlerを追加する代わりに、root(大本)のloggerにhandlerを追加することです。: Other libraries may use logging extensively, and you want to see relevant messages from those logs too. The simplest way to do this is to add handlers to the root logger instead of only the app logger. ::

from flask.logging import default_handler

root = logging.getLogger()
root.addHandler(default_handler)
root.addHandler(mail_handler)

自分のプロジェクト次第で、rootのloggerだけを設定する代わりに、扱っているloggerをそれぞれ別々に設定する方がより便利かもしれません。 Depending on your project, it may be more useful to configure each logger you care about separately, instead of configuring only the root logger. ::

for logger in (
    app.logger,
    logging.getLogger('sqlalchemy'),
    logging.getLogger('other_package'),
):
    logger.addHandler(default_handler)
    logger.addHandler(mail_handler)

Werkzeug

Werkzeugは基本的なリクエスト/レスポンスの情報を'werkzeug'のloggerへログします。もしrootのloggerにhandlerが設定されていない場合、werkzeugはStreamHandlerをwerkzeugのloggerへ追加します。 Werkzeug logs basic request/response information to the ``'werkzeug'`` logger. If the root logger has no handlers configured, Werkzeug adds a :class:`~logging.StreamHandler` to its logger.

Flask拡張 Flask Extensions

状況次第で、Flask拡張はapp.loggerもしくは独自の名前のloggerへログすることを選択するかもしれません。詳細については、それぞれのFlask拡張のドキュメントを調べてください。 Depending on the situation, an extension may choose to log to :meth:`app.logger <flask.Flask.logger>` or its own named logger. Consult each extension's documentation for details.