[Django] プロジェクト構成のベストプラクティスを探る - ４．ログ設定をシンプルにする

## この記事について

Djangoで本番運用やチーム開発を行うに当たって、プロジェクトの初期構成にどのように手を入れたらよいかを、The Twelve Factorsなどを参考にまとめたメモです。

## Djangoのログファイル設定は面倒なのか？

Djangoのログ出力はPython標準の「[logging](https://docs.python.jp/3/howto/logging.html)」というモジュールを利用しています。

しかしこの`logging`が多機能すぎるためか、設定方法を調べてもやたらと細かい内容のものが多く、結局どうしたら基本的な設定ができるのかわからないケースが多いです。

というわけで、とりあえずこれだけやればＯＫという設定を残しておきます。

## 参考

今回はこちらの本を参考（というかほぼ写し…）にさせていただきました。

現場で使える 基礎 Django（技術書典4バージョン）
https://booth.pm/ja/items/823251

内容が非常に充実していて助かります。

## ログ出力の要件


### 開発環境

出力先：標準出力（コンソール）
出力内容：

  - 自分で書いたログ出力
  - エラー・警告メッセージ
  - 開発ＷＥＢサーバへのリクエスト
  - 実行ＳＱＬ

### 本番環境

 出力先：ファイル

  - 自分で書いたログ出力
  - エラー・警告メッセージ
  
## 設定内容

  [開発と本番の設定ファイルを分離済みである](https://qiita.com/okoppe8/items/e60d35f55188c0ab9ecc)という前提とします。


### 開発環境

```python:config/settings/local.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'local': {
            'format': '%(asctime)s [%(levelname)s] %(pathname)s:%(lineno)d %(message)s'
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'local',
        },
    },
    'loggers': {
        # 自作したログ出力
        '': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': False,
        },
        # Djangoのエラー・警告・開発WEBサーバのアクセスログ
        'django': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': False,
        },
        # 実行SQL
        'django.db.backends': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': False,
        },
    }
}

```

### 本番環境

```python:project/settings/production.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'production': {
            'format': '%(asctime)s [%(levelname)s] %(process)d %(thread)d '
                      '%(pathname)s:%(lineno)d %(message)s'
        },
    },
    'handlers': {
        'file': {
            'class': 'logging.FileHandler',
            'filename': 'logs/django.log',  #環境に合わせて変更
            'formatter': 'production',
            'level': 'INFO',
        },
    },
    'loggers': {
        # 自作したログ出力
        '': {
            'handlers': ['file'],
            'level': 'INFO',
            'propagate': False,
        },
        # Djangoの警告・エラー
        'django': {
            'handlers': ['file'],
            'level': 'INFO',
            'propagate': False,
        },
    },
}

```

### ローテーション設定

ログローテーションの行う場合は`handlers`の設定を変更します。

#### ファイルサイズによるローテーション

```
    'handlers': {
        'file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': 'logs/django.log',
            'formatter': 'production',
            'maxBytes': 1024 * 1024 * 100,  # サイズ（100MB)
            'backupCount': 7, # 世代数
        },
    },
```

#### 期間によるローテーション

```
    'handlers': {
        'file': {
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': 'logs/django.log',
            'formatter': 'production',
            'when': 'D', # 単位は日
            'interval': 1, # 一日おき
            'backupCount': 7, # 世代数
        },
    },
```

※期間指定のフォーマットについては[python公式](https://docs.python.jp/3/library/logging.handlers.html#timedrotatingfilehandler)を参照


#### 注意：Windowsでローテションは使えない

Windows環境ではファイルロック処理の違いでRotatingFileHandlerが正常に動きません。ローテーションは別の方法で行ってください（WEBサーバ停止時にリネーム等）。

参考：[[Python]Windows上でspawnとログローテートの相性が悪い件](https://siguniang.wordpress.com/2012/11/24/python-rotatingfilehandler-spawn-combo-on-windows-sucks/)

## ログ監視方法

エラーや警告の監視は、ログファイル監視エージェントを使って通知するようにします。

- [Amazon CloudWatch Logsによるログの収集とフィルタとアラーム設定](https://dev.classmethod.jp/cloud/cloudwatch-logs/)

loggingから直接通知することもできますが、構成が複雑になるのでやめた方がいいとされています。

参考：[The Twelve Factor XI. ログ](https://12factor.net/ja/logs)