loggerクラスに専用メソッドを持たせ特定のメッセージを出力させたい
目的
ログに出すべき文字列が状況によって決まっているため、loggerクラスのメソッドにして呼び出すだけにしたい。
バッドパターン
CustomLoggerクラスをゼロから実装し、その内部でloggerを呼び出す。
デメリット
logger同等のメソッドをリレーするメソッドをたくさん実装する必要がある
実装したぶんだけテストコードが必要になる
リフレクション等を使ってコードを短くすると理解が難しくなる
code:log.py
import logging
class CustomLogger:
def __init__(self, logger_name):
self.logger = logging.getLogger(logger_name)
def process_started(self):
"""処理開始時のログ出力用"""
self._write_log("info", event="process_started")
def process_finished(self):
"""処理正常終了時のログ出力用"""
self._write_log("info", event="process_finished", result_code="success")
def process_failed(self):
"""処理要再実行時のログ出力用"""
self._write_log("warning", event="process_failed", result_code="failed")
def process_error(self):
"""処理例外発生終了時のログ出力用"""
self._write_log("error", event="process_failed", result_code="error")
def info(self, message=None, *args, **kwargs):
"""infoログ出力"""
self._write_log("info", message, *args, **kwargs)
# debug, warning, error, exception も同様に実装
def _write_log(self, log_level, message=None, *args, **kwargs):
"""ログ出力共通処理"""
getattr(self.logger, log_level)(
message=message, *args, **kwargs)
ベストプラクティス
独自クラスで専用メソッドを実装するのはなく、LoggerAdapterを使う
メリット
リレー処理はLoggerAdapterで実装されている
UnitTestは LoggerAadapter 由来の処理がテスト不要となり、小さくできる
ロガーのプラクティスに従うため、コードの読み手にすぐに使い方が伝わる
code:new_log.py
import logging
class CustomLogAdapter(logging.LoggerAdapter):
def process_started(self):
"""処理開始時のログ出力用"""
self.info(event="process_started")
def process_finished(self):
"""処理正常終了時のログ出力用"""
self.info(event="process_finished", result_code="success")
def process_failed(self):
"""処理要再実行時のログ出力用"""
self.warning(event="process_failed", result_code="failed")
def process_error(self):
"""処理例外発生終了時のログ出力用"""
self.error(event="process_failed", result_code="error")
# debug, info, warning, error, exception は再定義不要
使い方
code:main.py
logger = logging.getLogger(__name__)
def main():
process_logger = CustomLogAdapter(logger, {}) # adapterを付ける
# 広く使いたければmain関数外で用意してもOK
process_logger.process_started()
....
except Exception as e:
process_logger.exception('メッセージ') # adapter経由でもexceptionとか呼べる
process_logger.batch_error()
参考
タグ