きっかけ
とあるプログラムを延々と動かしてたんです。1週間ほど。
ログを出していたのですが、動かしっぱなしなので一つのログファイルにログを溜め込み・・・。(ちょっと怖い)
いや、これメモリーを圧迫したりとかしないの?(コンピューターは(も)よく知らない)
とういうことで、「動かしっぱなしのプログラムのログファイルを日毎に取得したい」って思いました。
精神的にも安心できそうだしね。
環境
2020 M1 MacBookAir
Python==3.10.8
ドキュメントを読んでみた
ム・ズ・カ・シ・イ
それっぽいのも見当たらない
GPTに聞いてみた
さすが!!!
とあるクラスを紹介してくれました。そして使ってみたらバッチリ。
だから紹介します!キリッ!
そのクラスとは
TimedRotatingFileHandler!!!
たいむどろーていてぃんぐふぁいるはんどら
時間設定されたくるくる回るファイルを取り扱うやつ
そんな感じ(意訳が過ぎるだろ)
ということで、ドキュメントを索引から探す・・・見つからん
見つけられないのでクラス名でサイト内検索したらあった!喜
横の+
をクリックして開いたらlogging.handlers
があった。ここか!
実装例
import logging
from logging.handlers import TimedRotatingFileHandler
import time
log_file_path = './log/my_watchdog.log'
formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(message)s')
logger = logging.getLogger(__name__)
handler = TimedRotatingFileHandler(
filename=log_file_path, # ログファイルのパス
when='M', # ファイルを作る時間単位。この場合は分。
interval=1, # 1分ごとにログファイルを新たに作成
backupCount=7, # 過去7つのログファイルを保存
encoding='utf-8', # エンコーディングをUTF-8に設定
delay=False, # ちょっと謎
# utc=False # ローカルタイムでローテーション(時間設定にした場合)
)
handler.setLevel(logging.DEBUG)
handler.setFormatter(formatter)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler) # ここで色々な設定を入れたハンドラーをloggerに設定
logger.info('**************** start ***************')
while True:
# 処理
logger.info('処理中')
time.sleep(20) # サンプルとして20秒毎にログを記録
動作結果
うん、目的達成できそう。
スタートの時だけ1行付け加えているのでわかりやすいですね。
**************** start ***************
指定したファイル名の後ろに2024-08-28_22-40
と日付と時間が付与されてます。
この時、書き込まれているファイルの名前はは指定した通りで、my_watchdog.log
です。
と、ここまで書いていたら最初のファイルが消えてました。
上に記した最初のファイルmy_watchdog.log.2024-08_22−40
が無いです。
そして末尾が−42
までのファイルが消えてます。
今回は上の通り、毎分新しいログファイルを作り、過去7ファイルを保持するということが達成できました。
常時起動のプログラムで膨大な行数になりそうなログファイルになりそうな時はうまく時間設定、ファイル数設定をしてメモリーやらストレージをうまく使えそうです。
TimedRotatingFileHandler解説
filename:
ログファイルのパスを指定します。
例: './log/my_watchdog.log'
そういや、連続稼働しているプログラムの名前がバレそうだ。www
when:
ログファイルをどんな周期で作成するか、指定するための時間単位を指定します。
主要なオプション:
'S': 秒ごと
'M': 分ごと
'H': 時ごと
'D': 日ごと
'midnight': 日付が変わるとき
'W': 曜日ごと(デフォルトは月曜日)
今回は検証なので、M
:分を使いました。(秒とか目で追うだけで精一杯になっちまう。)
interval:
ログファイルを生成し直す間隔を指定します。whenで指定した単位に対する数値です。
今回は1
を設定したので、when
の設定で単位を分としたので1分毎にログファイルを生成します。
backupCount:
古いログファイルをいくつ保存するかを指定します。
今回は7を指定したので、7つのファイルを保持することになります。
これで、when='D'とすると日毎の1週間分のファイルが保持できます。
encoding:
ログファイルのエンコーディングを指定します。
まぁ、utf-8
でええんちゃう?w
delay:
delay が true なら、ファイルを開くのは emit() の最初の呼び出しまで延期されます。
と書いてあるけど、正直よくわからない。ということで、GPTに聞くとこう返してくれた。
Trueに設定すると、実際にログファイルが書き込みされるまでファイルを開かないようにします。
ま、特に設定はいらんかな(知らんけど)
utc:
Trueに設定すると、ローテーションの時間をUTC(協定世界時)で計算します。
ま、時間設定する時には必須ですね。
日付変更に設定したいのに、9時間ズレたとかやらかしそう。www
基本はFalse
でいいでしょう。
atTime
ここにdatetime.time
で時刻を渡してあげるとこの時間で更新されるらしい(未確認)
マニュアルにはdatetime.time
インスタンスじゃないといけないって明示されてました。
ここにハンドラだけ書いておく。(自分用)
from logging.handlers import TimedRotatingFileHandler
from datetime.datetime import time
handler = TimeRotatingFileHandler(
filename='./log/my_watchdog.log',
atTime=time(8, 30),
utc=False,
)
おわりに
GPTさんの手を借りながらなんとか目的を果たすことができました。
監視系のソフトや、1週間ほど動きっぱなしの現場系ソフトを作ったことがあります。
ちょっと気になっていた、一つのログファイルが大きくなりすぎる問題がこれで解決できそうです。
あ、今んとこ問題は出てないけどね。(知らんけど)
じゃ、また!