LoginSignup
12
13

More than 5 years have passed since last update.

Python標準のloggingでログをJSON形式で出力する

Posted at

loggingの使い方

まずは基本編。ライブラリ側でログを記述し、
クライアント側でそのログをどのように扱うかを決める。

Library side

まず各ファイルの最初に以下の4行を追加しておく

from logging import getLogger, DEBUG, NullHandler
logger = getLogger(__name__)
logger.addHandler(NullHandler())
logger.setLevel(DEBUG)

これでlogger.debug, .info等で出力する

logger.info("Enter special block")

NullHandlerが登録してあるのでclientがキャプチャしなかったらこのログは捨てられる。

Client side

ライブラリ側のloggerは__name__で名前が登録されている。例えばmod.submod1, mod.submod2みたいな名前で登録されている。.で階層化されているのでmodで参照すると両方のサブモジュールのログを受け取れる。また名前を与えない場合、すべてのログを収集する。

  • 全部のログを標準エラー出力(sys.stderr)に出す
import logging
logger = logging.getLogger()
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.DEBUG)
  • modモジュールのINFO以上のログをファイル(mod.log)に出力する
import logging
logger = logging.getLogger("mod")
logger.addHandler(logging.FileHandler("mod.log", mode="w"))
logger.setLevel(logging.INFO)

もちろんこれらのコードをクライアントが実行しやすい関数をライブラリ側で用意することはできる。

JSONで出力する

その後の解析を考えると構造化したログが欲しかったりする。
実はlogger.infoとかに辞書オブジェクトあげることができる:

logger.info({
  "key": value,
  "homhom": 0,
})

特に設定しない場合、これを普通にprintした結果が出力されるので見た目にはJSONと変わらないが、
正式なJSONではないのでパースできなくて辛い。
そこで登場するのがpythonjsonloggerである。
これはクライアント側で出力するときにJSONとしてフォーマットし直す。

上のファイルに出力する場合は以下のようにする:

import logging
from pythonjsonlogger import jsonlogger
h = logging.FileHandler("mod.log", mode="w")
h.setFormatter(jsonlogger.JsonFormatter())
logging.getLogger("mod").addHandler(h)

これで行ごとにJSONとして有効なログが出力されます。なのでログを

with open("mod.log") as f:
    df = pd.DataFrame([json.loads(l) for l in f])

のように簡単にpandasに流し込める。

12
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
13