as-partionpeek / utils /disk_monitor.py
TopgunM's picture
Upload 26 files
6c8c831 verified
Raw
History Blame Contribute Delete
9.62 kB
"""
ディスク使用量監視ユーティリティ
"""
import os
import time
import logging
from datetime import datetime
from pathlib import Path
from typing import Dict, Any, Optional
from utils.cache_manager import CacheManager
class DiskMonitor:
"""ディスク使用量を監視するクラス"""
def __init__(self, warning_threshold: float = 85.0, critical_threshold: float = 90.0):
"""
ディスク監視を初期化
Args:
warning_threshold: 警告閾値(%)
critical_threshold: 危険閾値(%)
"""
self.warning_threshold = warning_threshold
self.critical_threshold = critical_threshold
self.cache_manager = CacheManager()
self.logger = logging.getLogger(__name__)
# 最後の警告時刻を記録(重複警告を防ぐため)
self.last_warning_time = None
self.last_critical_time = None
def get_status(self) -> Dict[str, Any]:
"""
現在のディスク使用状況を取得
Returns:
ディスク使用状況の辞書
"""
try:
disk_usage = self.cache_manager.get_disk_usage()
if "error" in disk_usage:
return {"error": disk_usage["error"]}
usage_percent = disk_usage["working_directory"]["usage_percent"]
# 警告レベルを判定
if usage_percent >= self.critical_threshold:
level = "CRITICAL"
action_needed = "immediate_cleanup"
elif usage_percent >= self.warning_threshold:
level = "WARNING"
action_needed = "cleanup_recommended"
else:
level = "OK"
action_needed = "none"
return {
"level": level,
"usage_percent": usage_percent,
"action_needed": action_needed,
"disk_usage": disk_usage,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
self.logger.error(f"ディスク状況の取得に失敗: {e}")
return {"error": str(e)}
def check_and_alert(self) -> Optional[Dict[str, Any]]:
"""
ディスク使用量をチェックし、必要に応じて警告を発行
Returns:
警告が発行された場合の情報
"""
try:
status = self.get_status()
if "error" in status:
return None
current_time = time.time()
usage_percent = status["usage_percent"]
# 危険レベルの処理
if usage_percent >= self.critical_threshold:
# 前回の警告から1時間以上経過している場合のみ警告
if (self.last_critical_time is None or
current_time - self.last_critical_time > 3600):
self.last_critical_time = current_time
# 緊急クリーンアップを実行
cleanup_result = self.cache_manager.emergency_cleanup()
alert_message = {
"level": "CRITICAL",
"message": f"ディスク使用率が危険レベルに達しました: {usage_percent:.1f}%",
"action_taken": "emergency_cleanup",
"cleanup_result": cleanup_result,
"timestamp": datetime.now().isoformat()
}
self.logger.critical(alert_message["message"])
print(f"[CRITICAL] {alert_message['message']}")
return alert_message
# 警告レベルの処理
elif usage_percent >= self.warning_threshold:
# 前回の警告から30分以上経過している場合のみ警告
if (self.last_warning_time is None or
current_time - self.last_warning_time > 1800):
self.last_warning_time = current_time
# 通常のクリーンアップを実行
cleanup_result = self.cache_manager.cleanup_cache()
alert_message = {
"level": "WARNING",
"message": f"ディスク使用率が警告レベルに達しました: {usage_percent:.1f}%",
"action_taken": "cleanup",
"cleanup_result": cleanup_result,
"timestamp": datetime.now().isoformat()
}
self.logger.warning(alert_message["message"])
print(f"[WARNING] {alert_message['message']}")
return alert_message
return None
except Exception as e:
self.logger.error(f"ディスク監視でエラーが発生: {e}")
return None
def continuous_monitor(self, interval: int = 300):
"""
継続的にディスク使用量を監視
Args:
interval: 監視間隔(秒)
"""
print(f"[INFO] ディスク監視を開始しました(間隔: {interval}秒)")
try:
while True:
alert = self.check_and_alert()
if alert:
print(f"[ALERT] {alert['message']}")
time.sleep(interval)
except KeyboardInterrupt:
print("[INFO] ディスク監視を停止しました")
except Exception as e:
self.logger.error(f"ディスク監視中にエラーが発生: {e}")
print(f"[ERROR] ディスク監視中にエラーが発生: {e}")
def generate_report(self) -> str:
"""
現在の状況レポートを生成
Returns:
レポート文字列
"""
try:
status = self.get_status()
if "error" in status:
return f"レポート生成エラー: {status['error']}"
disk_usage = status["disk_usage"]
working_dir = disk_usage["working_directory"]
cache_info = disk_usage["cache"]
report = f"""
=== ディスク使用量レポート ===
生成日時: {status['timestamp']}
警告レベル: {status['level']}
【作業用ディレクトリ】
パス: {working_dir['path']}
使用率: {working_dir['usage_percent']:.1f}%
使用量: {working_dir['used_gb']:.2f}GB / {working_dir['total_gb']:.2f}GB
空き容量: {working_dir['free_gb']:.2f}GB
【Huggingfaceキャッシュ】
キャッシュサイズ: {cache_info.get('total_size_gb', 0):.2f}GB
リポジトリ数: {cache_info.get('num_repos', 0)}
キャッシュパス: {cache_info.get('cache_path', 'N/A')}
【推奨アクション】
"""
if status["action_needed"] == "immediate_cleanup":
report += "⚠️ 緊急: 即座にキャッシュクリーンアップが必要です"
elif status["action_needed"] == "cleanup_recommended":
report += "⚠️ 推奨: キャッシュクリーンアップを検討してください"
else:
report += "✅ 現在のところ、アクションは不要です"
return report
except Exception as e:
return f"レポート生成中にエラーが発生: {e}"
def main():
"""メイン関数(スタンドアロン実行用)"""
import argparse
parser = argparse.ArgumentParser(description="ディスク使用量監視ツール")
parser.add_argument("--monitor", action="store_true", help="継続監視を開始")
parser.add_argument("--report", action="store_true", help="現在の状況レポートを表示")
parser.add_argument("--interval", type=int, default=300, help="監視間隔(秒)")
parser.add_argument("--warning", type=float, default=85.0, help="警告閾値(%)")
parser.add_argument("--critical", type=float, default=90.0, help="危険閾値(%)")
args = parser.parse_args()
monitor = DiskMonitor(
warning_threshold=args.warning,
critical_threshold=args.critical
)
if args.monitor:
monitor.continuous_monitor(interval=args.interval)
elif args.report:
print(monitor.generate_report())
else:
# デフォルト: 1回だけチェック
status = monitor.get_status()
if "error" in status:
print(f"エラー: {status['error']}")
else:
print(f"ディスク使用率: {status['usage_percent']:.1f}% ({status['level']})")
alert = monitor.check_and_alert()
if alert:
print(f"警告: {alert['message']}")
if __name__ == "__main__":
main()