From a0d8a32f38fe2509d37dba5ff8733116a82c4db1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 15:03:47 +0000 Subject: [PATCH 1/3] Initial plan From a71cc2f16557e1e621e473253390597955068a30 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 15:05:47 +0000 Subject: [PATCH 2/3] Add compressOldLogs and deleteOldLogs methods to Logger class Co-authored-by: yama <73999+yama@users.noreply.github.com> --- .../2026-02-07-logging-system-refactor.md | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/.agent/plans/2026-02-07-logging-system-refactor.md b/.agent/plans/2026-02-07-logging-system-refactor.md index a61b5a09e..29b997313 100644 --- a/.agent/plans/2026-02-07-logging-system-refactor.md +++ b/.agent/plans/2026-02-07-logging-system-refactor.md @@ -507,6 +507,107 @@ class Logger fclose($handle); return $logs; } + + /** + * 古いログファイルをgzip圧縮(ストレージ節約) + * + * @param int $days 何日以上前のログを圧縮するか(デフォルト: 7日) + * @return array 圧縮結果の統計情報 + */ + public function compressOldLogs($days = 7) + { + $cutoffTime = time() - ($days * 86400); + $result = [ + 'count' => 0, + 'before_size' => 0.0, + 'after_size' => 0.0, + 'saved_size' => 0.0, + 'ratio' => 0.0, + ]; + + $this->compressDirectory($this->logDir, $cutoffTime, $result); + + // 削減率を計算 + if ($result['before_size'] > 0) { + $result['ratio'] = round(($result['saved_size'] / $result['before_size']) * 100, 1); + } + + // サイズをMB単位に変換 + $result['before_size'] = round($result['before_size'] / 1048576, 2); + $result['after_size'] = round($result['after_size'] / 1048576, 2); + $result['saved_size'] = round($result['saved_size'] / 1048576, 2); + + return $result; + } + + /** + * ディレクトリを再帰的に走査して古いログファイルを圧縮 + * + * @param string $dir 対象ディレクトリ + * @param int $cutoffTime 圧縮対象の閾値タイムスタンプ + * @param array &$result 統計情報(参照渡し) + */ + private function compressDirectory($dir, $cutoffTime, &$result) + { + if (!is_dir($dir)) { + return; + } + + $items = scandir($dir); + foreach ($items as $item) { + if ($item === '.' || $item === '..') { + continue; + } + + $path = $dir . $item; + if (is_dir($path)) { + $this->compressDirectory($path . '/', $cutoffTime, $result); + } elseif (is_file($path) && preg_match('/\\.log(\\.\\d+)?$/', $item)) { + // 既に圧縮済みのファイルはスキップ + if (preg_match('/\\.gz$/', $item)) { + continue; + } + + // カットオフ時刻より古いファイルのみ圧縮 + if (filemtime($path) < $cutoffTime) { + $beforeSize = filesize($path); + $gzPath = $path . '.gz'; + + // gzip圧縮 + $fpIn = fopen($path, 'rb'); + $fpOut = gzopen($gzPath, 'wb9'); // 最高圧縮率 + if ($fpIn && $fpOut) { + while (!feof($fpIn)) { + gzwrite($fpOut, fread($fpIn, 8192)); + } + fclose($fpIn); + gzclose($fpOut); + + // 元ファイルを削除 + unlink($path); + + // 統計情報を更新 + $afterSize = filesize($gzPath); + $result['count']++; + $result['before_size'] += $beforeSize; + $result['after_size'] += $afterSize; + $result['saved_size'] += ($beforeSize - $afterSize); + } + } + } + } + } + + /** + * 保持期間を超えた古いログファイルを削除 + * + * @param int $days 保持期間(日数) + */ + public function deleteOldLogs($days) + { + $cutoffTime = time() - ($days * 86400); + $this->cleanDirectory($this->logDir, $cutoffTime); + } } ``` From c7ddaa9aabd1cc0957f608b71e7d9c0c640e76fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 15:06:41 +0000 Subject: [PATCH 3/3] Enhance deleteOldLogs method with dry-run support and statistics Co-authored-by: yama <73999+yama@users.noreply.github.com> --- .../2026-02-07-logging-system-refactor.md | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/.agent/plans/2026-02-07-logging-system-refactor.md b/.agent/plans/2026-02-07-logging-system-refactor.md index 29b997313..266faa55f 100644 --- a/.agent/plans/2026-02-07-logging-system-refactor.md +++ b/.agent/plans/2026-02-07-logging-system-refactor.md @@ -602,11 +602,62 @@ class Logger * 保持期間を超えた古いログファイルを削除 * * @param int $days 保持期間(日数) + * @param bool $dryRun trueの場合は削除せず対象ファイルのみ返す(プレビュー) + * @return array 削除結果の統計情報 */ - public function deleteOldLogs($days) + public function deleteOldLogs($days, $dryRun = false) { $cutoffTime = time() - ($days * 86400); - $this->cleanDirectory($this->logDir, $cutoffTime); + $result = [ + 'count' => 0, + 'size' => 0.0, + 'files' => [], + ]; + + // 削除対象ファイルを収集(統計情報とプレビュー用) + $this->collectOldFiles($this->logDir, $cutoffTime, $result); + + // dry-runモードでない場合のみ実際に削除 + if (!$dryRun) { + $this->cleanDirectory($this->logDir, $cutoffTime); + } + + // サイズをMB単位に変換 + $result['size'] = round($result['size'] / 1048576, 2); + + return $result; + } + + /** + * 古いログファイルを収集(削除プレビュー用) + * + * @param string $dir 対象ディレクトリ + * @param int $cutoffTime 削除対象の閾値タイムスタンプ + * @param array &$result 統計情報(参照渡し) + */ + private function collectOldFiles($dir, $cutoffTime, &$result) + { + if (!is_dir($dir)) { + return; + } + + $items = scandir($dir); + foreach ($items as $item) { + if ($item === '.' || $item === '..') { + continue; + } + + $path = $dir . $item; + if (is_dir($path)) { + $this->collectOldFiles($path . '/', $cutoffTime, $result); + } elseif (is_file($path)) { + if (filemtime($path) < $cutoffTime) { + $result['count']++; + $result['size'] += filesize($path); + $result['files'][] = str_replace($this->logDir, '', $path); + } + } + } } } ```