# Django 5.0.9.dev20240806133106 ドキュメント

# ロギングの設定と利用

参考

- Django のロギング リファレンス
- Django のロギングの概要

Django はそのままで動作する デフォルトのロギング設定 を持っており、すぐに拡張可能です。

## 基本的なロギング呼び出しを作成する

ログメッセージをコード内から送信するには、コードにロギングの呼び出しを書く必要があります。

`settings.py` でログ呼び出しを使用しようとしないでください。

Django のロギングは `setup()` 関数の一部として設定されるため、 `settings.py` でロギングを呼び出しても期待通りに動作しないかもしれません。ロギングを調べるには、以下の例で推奨されているようにビュー関数を使用してください。

まず、Python の logging ライブラリをインポートし、`logging.getLogger()` でロガーのインスタンスを取得します。`getLogger()` メソッドに、ロガーとロガーが出力するレコードを識別するための名前を指定します。そのための良い方法は `__name__` を使用することです (これについては以下の ロガーの名前空間を使う を参照してください)。これは、次のように、現在の Python モジュールの名前をドット区切りのパスで返します。

    import logging

    logger = logging.getLogger(__name__)

この宣言はモジュール・レベルで行うのがよいとされています。

そして、ビューなどの関数内で、logger にレコードを送信します。

    def some_view(request):
        ...
        if some_risky_state:
            logger.warning("Platform is running at risk")

このコードが実行されると、そのメッセージを含む `LogRecord` が logger に送られます。Django のデフォルトの logging 設定を使っている場合、メッセージはコンソールに表示されます。

上の例で使われている `WARNING` レベルは、いくつかある ログの重大度レベル: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` の一つです。したがって、別の例は次のようになります。

    logger.critical("Payment system is not responding")

重要

`WARNING` より低いレベルのレコードはデフォルトではコンソールに表示されません。この動作を変更するには追加の設定が必要です。

## ロギングの設定をカスタマイズする

Djangoのロギング設定は初期状態で動作しますが、追加の設定を行うことで、ログを様々な宛先（ログファイル、外部サービス、メールなど）に送信するのを正確にコントロールできます。

以下のものを設定できます。

- どのレコードがどのハンドラに送られるかを決定するためのロガーマッピング
- 受け取ったレコードをどう処理するかを決めるハンドラー
- レコードの転送をさらにコントロールし、レコードをその場で変更することもできるフィルタ
- `LogRecord` オブジェクトを、人間や他のシステムで利用できるように文字列や他の形式に変換するためのフォーマッタ

ロギングの設定には様々な方法があります。Django では、 `LOGGING` 設定が最もよく使われます。この設定は dictConfig フォーマット を使い、 デフォルトのロギング設定 を拡張します。

カスタム設定が Django のデフォルトとどのようにマージされるかについては ロギングを設定する を参照してください。

その他のロギングの設定方法の詳細については `Python logging documentation` を参照してください。簡単にするために、このドキュメントでは `LOGGING` 設定による設定のみを考えます。

### ロギングの基本的な設定

ロギングを設定する場合、以下のようにします。

#### `LOGGING` 辞書を作成する

`settings.py` に以下を追加します:

    LOGGING = {
        "version": 1,  # the dictConfig format version
        "disable_existing_loggers": False,  # retain the default loggers
    }

ほとんどの場合、 `disable_existing_loggers` を `False` に設定することで、デフォルトのロギング設定を保持し、拡張できます。

#### ハンドラを設定する

この例では、Python の `FileHandler` を使って、レベル `DEBUG` 以上のログを (プロジェクトルート内の) `general.log` ファイルに保存する `file` という名前のハンドラを設定します:

    LOGGING = {
        # ...
        "handlers": {
            "file": {
                "class": "logging.FileHandler",
                "filename": "general.log",
            },
        },
    }

異なるハンドラクラスは異なる設定オプションを取ります。利用可能なハンドラクラスの詳細については、 Django が提供する `AdminEmailHandler` や Python が提供する様々な `handler class` を参照してください。

ログレベルはハンドラで設定することもできます（デフォルトでは、ハンドラはすべてのレベルのログメッセージを受け取ります）。上の例を使うと、次のように書けます:

    {
        "class": "logging.FileHandler",
        "filename": "general.log",
        "level": "DEBUG",
    }

これで、レベル `DEBUG` 以上のレコードだけを受け付けるようにハンドラを設定できます。

#### ロガーマッピングを設定する

このハンドラにレコードを送信するには、ロガーマッピングをそのハンドラを使うように設定します。例えば:

    LOGGING = {
        # ...
        "loggers": {
            "": {
                "level": "DEBUG",
                "handlers": ["file"],
            },
        },
    }

マッピングの名前はどのログレコードを処理するかを決定します。この設定 (`""`) は 無名 です。つまり、 すべての ロガーからのレコードを処理します（レコードを処理するロガーを決定するためにマッピング名を使用する方法については、以下の ロガーの名前空間を使う を参照してください）。

これは `DEBUG` レベル以上のメッセージを `file` というハンドラーに転送します。

ロガーは複数のハンドラーにメッセージを転送できるので、ロガーとハンドラーの関係は多対多であることに注意してください。

このコードを実行したら、:

    logger.debug("Attempting to connect to API")

プロジェクトルートの `general.log` ファイルにそのメッセージが保存されるでしょう。

#### フォーマッタを設定する

デフォルトでは、最終的なログ出力には各 `log record` のメッセージ部分が含まれます。追加データを含めたい場合はフォーマッタを使います。まずフォーマッタに名前を付けて定義します。この例では `verbose` と `simple` という名前のフォーマッタを定義しています:

    LOGGING = {
        # ...
        "formatters": {
            "verbose": {
                "format": "{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}",
                "style": "{",
            },
            "simple": {
                "format": "{levelname} {message}",
                "style": "{",
            },
        },
    }

`style` キーワードを使用すると、 `str.format()` 用の `{` または `string.Template` フォーマット用の `$` を指定できます。デフォルトは `$` です。

含めることができる `LogRecord` 属性については LogRecord attributes を参照してください。

ハンドラにフォーマッタを適用するには、ハンドラの辞書に `formatter` エントリを追加します:

    "handlers": {
        "file": {
            "class": "logging.FileHandler",
            "filename": "general.log",
            "formatter": "verbose",
        },
    }

#### ロガーの名前空間を使う

無名のロギング設定 `""` は任意の Python アプリケーションからログを取り込みます。名前付きロギング設定は、一致する名前のロガーからだけログを取得します。

logger インスタンスの名前空間は `getLogger()` を使って定義します。例えば、 `my_app` の `views.py` で次のように定義します:

    logger = logging.getLogger(__name__)

これは `my_app.views` 名前空間にロガーを作成します。 `__name__` を使うと、プロジェクト内のアプリケーションにおけるログメッセージの出所に基づいて、自動的にそれらを整理できます。また、それによって名前の衝突が起こらなくなります。

`my_app.views` という名前のロガーマッピングは、このロガーからレコードを取得します:

    LOGGING = {
        # ...
        "loggers": {
            "my_app.views": {...},
        },
    }

`my_app` という名前のロガーマッピングはより広く、 `my_app` 名前空間内のロガー（`my_app.views`、`my_app.utils` などを含む）からレコードを取得します:

    LOGGING = {
        # ...
        "loggers": {
            "my_app": {...},
        },
    }

ロガーの名前空間を明示的に定義することもできます:

    logger = logging.getLogger("project.payment")

そして、それに応じてロガーマッピングを設定することもできます。

##### ロガーの階層と伝搬（propagation）を使う

ロガーの命名は 階層的 です。 `my_app` は `my_app.views` の親であり、 `my_app.views` は `my_app.views.private` の親です。特に指定がない限り、ロガーのマッピングは処理したレコードを親に伝播（propagate）します―― `my_app.views.private` 名前空間のロガーからのレコードは、 `my_app` と `my_app.views` の両方のマッピングで処理されます。

この動作を管理するには、定義したマッピングに `"propagate"` キーを設定します:

    LOGGING = {
        # ...
        "loggers": {
            "my_app": {
                # ...
            },
            "my_app.views": {
                # ...
            },
            "my_app.views.private": {
                # ...
                "propagate": False,
            },
        },
    }

`propagate` のデフォルトは `True` です。この例では、`my_app.views.private` のログは親プロセスでは処理されませんが、 `my_app.views` のログは親プロセスで処理されます。

### レスポンシブなロギングを設定する

ロギングは、必要な情報ができるだけ多く含まれているときに最も有用であり、目的のために必要な情報だけが含まれているとなお嬉しいです。そして、必要な情報量は、あなたが何をしているかによって異なります。デバッグ中には、本番環境では過剰で役に立たないようなレベルの情報が必要になります。

必要な時に必要な詳細レベルを提供するように、ロギングを設定できます。これを実現するために手動で設定を変更するよりも良い方法は、環境に応じて自動的に設定を適用することです。

例えば、開発環境とステージング環境で環境変数 `DJANGO_LOG_LEVEL` を適切に設定し、ロガーマッピングで次のように使用できます:

    "level": os.getenv("DJANGO_LOG_LEVEL", "WARNING")

- 環境がより低いログレベルを指定しない限り、このコンフィギュレーションは重大度 `WARNING` 以上のレコードだけをハンドラに転送します。

設定の他のオプション（ハンドラの `level` や `formatter` オプションなど）も同様に管理できます。