備忘録。
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()が上手く動かなかった。フォークされているコードは正常に動作した。プルリク投げられてるのでマージしてほしいなあ…。