Pythonでロギングする際の俺的ベストプラクティス
パターンは以下の通り
- ファイル出力(全て同一ログファイルに出力する)
- ファイル出力(ログレベルに応じてログファイルを分ける)
- 標準出力
基本的に、ログファイル出力と標準出力を併用するケースって少ないと思います。
標準出力のパターンは、コンテナ環境でfluentdドライバなどで外部転送したいケースがあるかなと思います。
参考にさせて頂きました → pythonのlog出力 by
@yopya
ファイル出力(全て同一ログファイルに出力する)
from logging import getLogger, Formatter, handlers, DEBUG
class FileLogger:
def __init__(self, file='log/app.log'):
self.logger = getLogger(__name__)
self.logger.setLevel(DEBUG)
formatter = Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s')
handler = handlers.RotatingFileHandler(
filename=file,
maxBytes=1048576,
backupCount=3
)
handler.setFormatter(formatter)
handler.setLevel(DEBUG)
self.logger.addHandler(handler)
def debug(self, msg):
self.logger.debug(msg)
def info(self, msg):
self.logger.info(msg)
def warn(self, msg):
self.logger.warning(msg)
def error(self, msg):
self.logger.error(msg)
def critical(self, msg):
self.logger.critical(msg)
ファイル出力(ログレベルに応じてログファイルを分ける)
ERROR以上のレベルの場合にerr.log
に出力
from logging import getLogger, Formatter, handlers, DEBUG, ERROR
class FileLogger:
def __init__(self, debug_file='log/app.log', error_file='log/err.log'):
self.logger = getLogger(__name__)
self.logger.setLevel(DEBUG)
formatter = Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s')
# DEBUGレベルハンドラ定義
debug_handler = handlers.RotatingFileHandler(
filename=debug_file,
maxBytes=1048576,
backupCount=3
)
debug_handler.setFormatter(formatter)
debug_handler.setLevel(DEBUG)
self.logger.addHandler(debug_handler)
# ERRORレベルハンドラ
error_handler = handlers.RotatingFileHandler(
filename=error_file,
maxBytes=1048576,
backupCount=3
)
error_handler.setFormatter(formatter)
error_handler.setLevel(ERROR)
self.logger.addHandler(error_handler)
def debug(self, msg):
self.logger.debug(msg)
def info(self, msg):
self.logger.info(msg)
def warn(self, msg):
self.logger.warning(msg)
def error(self, msg):
self.logger.error(msg)
def critical(self, msg):
self.logger.critical(msg)
標準出力
from logging import getLogger, Formatter, StreamHandler, DEBUG
class StreamLogger:
def __init__(self):
self.logger = getLogger(__name__)
self.logger.setLevel(DEBUG)
formatter = Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s')
handler = StreamHandler()
handler.setFormatter(formatter)
handler.setLevel(DEBUG)
self.logger.addHandler(handler)
def debug(self, msg):
self.logger.debug(msg)
def info(self, msg):
self.logger.info(msg)
def warn(self, msg):
self.logger.warning(msg)
def error(self, msg):
self.logger.error(msg)
def critical(self, msg):
self.logger.critical(msg)
使い方
logger = StreamLogger()
message = 'hello world!'
logger.info(message)
# => '2019-10-03 12:47:46,667 INFO __main__: hello world!'
FileLogger
の場合は同様のメッセージが/log/app.log
に出力されていく
まとめ
「標準出力」に加えて「標準エラー出力」も必要だということに記事書いてて気づいたので後で対応する。