pythonでjson形式でログを出す


TL;DR

python-json-logger便利

madzak/python-json-logger: Json Formatter for the standard python logger

  • わりかし簡単にjson形式でログが出せるようになる
  • 出力も柔軟に設定出来る
    • カスタムのフォーマッタを定義したり
    • info呼ぶところでアドホックにキーを足したり(logger.info(extra={'a': 10})的な)

パッケージインストール

$ pip install python-json-logger

logger定義

プロジェクト用のJsonFormattergetLoggerを定義しておく例

import logging
import datetime
from pytz import timezone
from pythonjsonlogger import jsonlogger


# https://github.com/madzak/python-json-logger#customizing-fields
class JsonFormatter(jsonlogger.JsonFormatter):

    def parse(self):
        """
        他に出したいフィールドがあったらこのリストに足す
        https://docs.python.jp/3/library/logging.html
        """
        return [
            'process',
            'timestamp',
            'level',
            'name',
            'message',
            'stack_info',
        ]

    def add_fields(self, log_record, record, message_dict):
        super().add_fields(log_record, record, message_dict)
        if not log_record.get('timestamp'):
            # https://qiita.com/yoppe/items/4260cf4ddde69287a632
            now = datetime.datetime.now(timezone('Asia/Tokyo')).strftime('%Y-%m-%dT%H:%M:%S%z')
            log_record['timestamp'] = now
        if log_record.get('level'):
            log_record['level'] = log_record['level'].upper()
        else:
            log_record['level'] = record.levelname


def getLogger(module_name):
    """プロジェクトごとにハンドラの設定などをしたい場合はここでやる"""
    logger = logging.getLogger(module_name)
    handler = logging.StreamHandler()
    formatter = JsonFormatter()
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    logger.setLevel(logging.DEBUG)
    return logger

使う側

  • 使う側のスクリプトにてgetLogger(__name__)で初期化
  • extraにdictを渡すとそれも出力してくれる
from project_logging import getLogger
logger = getLogger(__name__)
logger.info('Inserting rows into MySQL', extra={'rows': rows})
{
  "process": 43274,
  "timestamp": "2017-10-15T12:28:13+0900",
  "level": "INFO",
  "name": "etl.mysql",
  "message": "Inserting rows into MySQL",
  "stack_info": null,
  "rows": 10
}

参考