実現したいこと
logをファイルで日付ごとに分けて保存したい。
ファイル名は「app_20230101.log」のようにし、日付が更新されると、「app_20230102.log」を新しく作成して書き込んでいくような感じ。
該当のソースコード
python
1import os 2from pathlib import Path 3from datetime import datetime 4import logging 5from logging import Formatter, handlers, getLogger, Handler 6import inspect 7 8from rich.logging import RichHandler 9 10class Logger: 11 """ 12 ログを管理するためのクラスです。 13 14 Attributes 15 ---------- 16 log_level : str 17 ログレベル ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')。デフォルトは 'INFO'。 18 save_log_dir : str 19 ログファイルを保存するディレクトリのパス。デフォルトは 'logs/console'。 20 21 Methods 22 ------- 23 debug(msg: str) -> None 24 DEBUG レベルのログを出力します。 25 info(msg: str) -> None 26 INFO レベルのログを出力します。 27 warn(msg: str) -> None 28 WARNING レベルのログを出力します。 29 error(msg: str, exc_info: bool = True) -> None 30 ERROR レベルのログを出力します。exc_info が True の場合、例外情報も表示します。 31 critical(msg: str) -> None 32 CRITICAL レベルのログを出力します。 33 remove_oldlog(max_num_log: int = 100) -> None 34 古いログファイルを削除します。max_num_log で保持するログファイルの最大数を指定します。 35 """ 36 37 def __init__( 38 self, 39 *, 40 log_level: str = "INFO", 41 save_log_dir: str = "logs/console" 42 ): 43 self.log_level = log_level 44 self.log_dir: Path = Path(save_log_dir) 45 self.log_backupcount: int = 3 46 self.log_file_path: Path = self.get_log_file_path() 47 48 stdout_formatter: Formatter = Formatter(fmt="%(message)s") 49 file_formatter: Formatter = Formatter( 50 fmt="%(asctime)s.%(msecs)03d %(levelname)7s %(message)s [%(name)s:%(lineno)d]", 51 datefmt="%Y/%m/%d %H:%M:%S", 52 ) 53 54 stdout_handler: Handler = RichHandler(rich_tracebacks=True) 55 stdout_handler.setFormatter(fmt=stdout_formatter) 56 file_handler: Handler = handlers.TimedRotatingFileHandler( 57 filename=self.log_file_path, 58 when="midnight", 59 encoding="UTF-8", 60 backupCount=self.log_backupcount, 61 ) 62 file_handler.setFormatter(fmt=file_formatter) 63 64 logging.basicConfig( 65 level=self.log_level, 66 handlers=[stdout_handler, file_handler], 67 ) 68 caller_func_name: str = inspect.stack()[1].filename.split("/")[-1] 69 self.logger = getLogger(name=caller_func_name) 70 71 def get_log_file_path(self) -> Path: 72 log_filename = f"app_{datetime.strftime(datetime.now(), '%Y%m%d')}.log" 73 return self.log_dir / log_filename 74 75 def update_log_file(self) -> None: 76 new_log_file_path = self.get_log_file_path() 77 if new_log_file_path != self.log_file_path: 78 self.log_file_path = new_log_file_path 79 self.logger.info(f"ログファイルが更新されました: {self.log_file_path}") 80 for handler in self.logger.handlers: 81 if isinstance(handler, handlers.TimedRotatingFileHandler): 82 handler.baseFilename = new_log_file_path 83 84 def debug(self, msg: str) -> None: 85 self.update_log_file() 86 self.logger.debug(msg, stacklevel=2) 87 88 def info(self, msg: str) -> None: 89 self.update_log_file() 90 self.logger.info(msg, stacklevel=2) 91 92 def warn(self, msg: str) -> None: 93 self.update_log_file() 94 self.logger.warning(msg, stacklevel=2) 95 96 def error(self, msg: str, *, exc_info: bool = True) -> None: 97 self.update_log_file() 98 self.logger.error(msg, exc_info=exc_info, stacklevel=2) 99 100 def critical(self, msg: str) -> None: 101 self.update_log_file() 102 self.logger.critical(msg, stacklevel=2) 103 104 def remove_oldlog(self, *, max_num_log: int = 100) -> None: 105 logs = list(self.log_dir.glob("*.log")) 106 if len(logs) > max_num_log: 107 log_name_pairs = [ 108 (log, datetime.strptime(log.stem[-8:], "%Y%m%d")) for log in logs 109 ] 110 log_name_pairs = sorted(log_name_pairs, key=lambda s: s[1]) 111 remove_log_path = log_name_pairs[0][0] 112 os.remove(remove_log_path) 113 self.info(f"古いログを削除しました: {remove_log_path}") 114 for i in range(1, self.log_backupcount + 1): 115 remove_rotating_log_path = f"{remove_log_path}.{i}" 116 if os.path.exists(remove_rotating_log_path): 117 os.remove(remove_rotating_log_path) 118 self.info(f"古いログを削除しました: {remove_rotating_log_path}")
試したこと
上記のまま実行すると、ファイルは分かれずに同じファイルのまま書き込まれていきます。
ひとこと
かなりいろいろ試しましたが、なかなか希望通りに動いてくれなくて困っています。よろしくお願いいたします。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/08/27 06:56