DjangoのログをLTSVで出力する


備忘録。

Djangoのログフォーマットを切り替えるにはlogging.Formatterを継承したカスタムクラスを作れば良い。format()メソッドを追加してstrオブジェクトを返すようにする。

log_formatter.py
import logging
import socket
from django.utils.datastructures import SortedDict

from ltsv import ltsv


class LTSVFormatter(logging.Formatter):
    def format(self, record):
        # dictオブジェクト並び順が保証されない?のでDjango SortedDictを使っている
        data = SortedDict()
        data['host'] = socket.gethostname()
        data['time'] = record.created
        data['pid'] = record.process
        data['level'] = record.levelname

        # ログメッセージが辞書の場合には出力データにそのままマッピングする
        if isinstance(record.msg, str):
            data['msg'] = record.msg
        elif isinstance(record.msg, dict):
            data.update(record.msg)

        return ltsv.writer(data).decode('utf-8')

settings.LOGGINGのformattersに次のように追加する。カスタムフォーマッタを使うには()というキーにコーラブルオブジェクトを渡す。公式のドキュメントに書いてなくて、コード読んで初めて知った…。

settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'ltsv': {
            '()': 'apps.base.logging.LTSVFormatter',
        },
    }
}

出力結果。

host:mbp15-retina.local time:1422418685.587985  pid:58432   level:INFO  msg:Hello world!

余談。

pypiにあるltsvモジュールはwriter()が上手く動かなかった。フォークされているコードは正常に動作した。プルリク投げられてるのでマージしてほしいなあ…。


参考