1. ホーム
  2. python

[解決済み] Pythonのログフォーマット文字列にカスタムフィールドを追加するには?

2022-08-20 03:51:08

質問

現在のフォーマット文字列は

formatter = logging.Formatter('%(asctime)s : %(message)s')

という新しいフィールドを追加したいのですが app_name という新しいフィールドを追加したいのですが、これはこのフォーマッタを含む各スクリプトで異なる値を持つことになります。

import logging
formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s')
syslog.setFormatter(formatter)
logger.addHandler(syslog)

しかし、その受け渡し方法として app_name の値をロガーに渡し、フォーマット文字列に挿入する方法がわかりません。私は明らかにそれを毎回渡すことによって、ログメッセージに表示させることができますが、これは面倒です。

試してみました。

logging.info('Log message', app_name='myapp')
logging.info('Log message', {'app_name', 'myapp'})
logging.info('Log message', 'myapp')

が、どれも動作しない。

どのように解決するのですか?

Python3

Python3.2以降では、以下のように LogRecordFactory

import logging

logging.basicConfig(format="%(custom_attribute)s - %(message)s")

old_factory = logging.getLogRecordFactory()

def record_factory(*args, **kwargs):
    record = old_factory(*args, **kwargs)
    record.custom_attribute = "my-attr"
    return record

logging.setLogRecordFactory(record_factory)

>>> logging.info("hello")
my-attr - hello

もちろん record_factory は任意の callable にカスタマイズ可能で、その値は custom_attribute の値は、ファクトリーの callable への参照を保持していれば、更新される可能性があります。

なぜアダプタ/フィルタを使用するよりも良いのですか?

  • ロガーをアプリケーションに渡す必要がありません。
  • 独自のロガーを使用するサードパーティライブラリでも実際に動作します (これは、単に logger = logging.getLogger(..) を呼び出すだけで、) 同じログフォーマットを持つようになります。(これは、同じロガーオブジェクトを使用する必要があるフィルタ/アダプタの場合ではありません)
  • 複数のファクトリーをスタック/チェーンすることができます。