Pythonのloggingモジュールで、TimedRotatingFileHandlerを使って指定時間でログローテーションする方法を解説します。
Contents
時間指定でログローテーション
Pythonに限らずですがプログラムの開発をした際にはログ出力し、障害時の際には状況を把握できるようにすることが非常に重要です。
業務アプリケーションといった常時動作しているシステムの場合、ログファイルが常に出力されるのでログファイルが肥大化し、ディスクの容量を圧迫してしまいシステム全体の動作に影響を与える可能性があります。
その場合には、ログローテーションすることで回避します。例えば「ログデータの総量が一定の容量を超えたら別のファイルにログを出力する」「一定時間が過ぎたら別のファイルにログを出力する」といったように切り替えます。
pythonではロギングのモジュールとしてloggingが用意されています。loggingにはハンドラというものがありますが、TimedRotatingFileHandlerを使用することで指定した時間でのログローテーションを実現することができます。
本記事では、TimeRotatingFileHandlerの使用方法について紹介します。
ファイルサイズでログローテーションする方法としては「loggingのRotatingFileHandlerを使って指定ファイルサイズでログローテーションする方法」でまとめていますので興味があれば参考にしてください。
loggingのTimedRotatingFileHandlerでログローテーションする方法
Pythonでログ出力に使用されるloggingでTimedRotatingFileHandelrによってログローテーションする方法を説明します。
TimedRotatingFileHandlerの使い方
loggingで指定時間によるログローテーションをする場合は、以下のようにTimedRotatingFileHandlerを設定して使用します。
import logging.handlers import time def main(): # ロギングの基本設定 formatter = "%(asctime)s:%(levelname)s:%(name)s:%(message)s" logging.basicConfig(level=logging.INFO, format=formatter, encoding="utf_8") # ロガーの作成 logger = logging.getLogger(__name__) # ログレベルをDEBUGへ変更 logger.setLevel(logging.DEBUG) # ログローテーションのハンドラーを設定 # when: intervalの単位 # ('S':秒、'M':分、'H':時間、'D':日、'W0'-'W6':曜日(0=月曜)) # interval: ログローテーション間隔 # backupCount: バックアップとして保持するログファイル数 h = logging.handlers.TimedRotatingFileHandler( "test.log", when="S", interval=20, backupCount=5 ) # フォーマットを設定 h.setFormatter(logging.Formatter(formatter)) # ロガーにハンドラーを設定 logger.addHandler(h) for _ in range(1000): time.sleep(0.1) logger.debug("log rotation test") if __name__ == "__main__": main()
【実行結果例】対象フォルダをdirコマンドで確認した例
【詳細説明】
以降でプログラムの各部分について解説をします。
まず、TimedRotatingFileHandlerを使用する場合には「logging.handlers」をimportする必要があります。
import logging.handlers
以下の部分は、ログ基本設定の部分でメインプログラムなどで設定する基本的な設定内容です。
# ロギングの基本設定 formatter = "%(asctime)s:%(levelname)s:%(name)s:%(message)s" logging.basicConfig(level=logging.INFO, format=formatter, encoding="utf_8")
ロガーを作成し、ログローテーションのためのTimedRotatingFileHandlerを設定しているのは以下の部分になっています。
# ロガーの作成 logger = logging.getLogger(__name__) # ログレベルをDEBUGへ変更 logger.setLevel(logging.DEBUG) # ログローテーションのハンドラーを設定 # when: intervalの単位 # ('S':秒、'M':分、'H':時間、'D':日、'W0'-'W6':曜日(0=月曜)) # interval: ログローテーション間隔 # backupCount: バックアップとして保持するログファイル数 h = logging.handlers.TimedRotatingFileHandler( "test.log", when="S", interval=20, backupCount=5 ) # フォーマットを設定 h.setFormatter(logging.Formatter(formatter)) # ロガーにハンドラーを設定 logger.addHandler(h)
ログローテーションのハンドラーを作成する際には、「ファイル名」「when」、「interval」、「backupCount」といった引数を指定します。
whenはログをローテーションする間隔(interval)の単位を指定します。whenで指定できるものには以下のようなものがあります。日単位で1日分のログでローテーションしたい場合には’midnight’を使用するのがよいかと思います。
whenに指定する値 | 内容 |
---|---|
‘S’ | 秒 |
‘M’ | 分 |
‘H’ | 時間 |
‘D’ | 日 |
‘W0’-‘W6’ | 曜日(‘W0’が月曜を表す) |
‘midnight’ | ・atTime引数が指定されなかった場合は深夜にローテーションされる ・atTime引数に指定された時刻にローテーションされる。ただし、時刻はdatetime.timeインスタンスで指定する。 |
intervalは、whenで指定した単位でどれだけの間隔をとってローテーションするかを指定します。
上記の例では、’S’で20と指定しているので20秒ごとにログをローテーションします。実際にはこんなに短い時間でのローテーションはしないと思いますが、実行結果の確認をしやすいように短い時間にしています。
backupCountについては、いくつの古いログファイルを保持するかを指定します。
まとめると上記の例では、test.logというファイルにログを出力し、20秒ごとに上限5つのバックアップファイルでローテーションするという設定です。
また、フォーマット指定しておかないと入力した文字列のみ出力されてしまうので、setFormatterでハンドラにフォーマットを指定しています。最後にaddHandlerでロガーにハンドラーを設定しています。
上記まででログローテーションをする準備は完了です。以下の部分はログ出力の確認をしています。sleepで一定時間止まって出力するようにしていますので、繰り返し回数やsleep時間などは任意に変えてみてください。
for _ in range(1000): time.sleep(0.1) logger.debug("log rotation test")
複数回実行いただくと分かりますが、test.logに常に最新のログが出力されます。
ログが指定時間に達するとtest.log.2022-04-21_06-29-42のように出力時間が分かるようなファイル名でローテーションがされます。上記の例では、backupCountを5としているので5ファイルまでしか作成されません。
以上が、TimedRotatingFileHandlerを使って時間指定によるログローテーションをする方法でした。
TimedRotatingFileHandlerの公式ドキュメントページはこちらを参考にしてください。
上記で紹介しているソースコードについてはgithubにて公開しています。参考にしていただければと思います。