option('days'); $type = $this->option('type'); $serviceId = $this->option('service'); $dryRun = $this->option('dry-run'); $force = $this->option('force'); if ($days < 1) { $this->error('保留天数必须大于0'); return Command::FAILURE; } if (!in_array($type, ['logs', 'monitors', 'all'])) { $this->error('清理类型必须是 logs、monitors 或 all'); return Command::FAILURE; } $this->info("开始清理 {$days} 天前的记录..."); try { $cutoffDate = now()->subDays($days); $results = []; if ($type === 'logs' || $type === 'all') { $results['logs'] = $this->cleanupLogs($cutoffDate, $serviceId, $dryRun); } if ($type === 'monitors' || $type === 'all') { $results['monitors'] = $this->cleanupMonitors($cutoffDate, $serviceId, $dryRun); } $this->displayResults($results, $dryRun); if ($dryRun) { $this->info('这是预览模式,没有实际删除记录'); return Command::SUCCESS; } if (!$force && !$this->confirmDeletion($results)) { $this->info('操作已取消'); return Command::SUCCESS; } // 实际执行删除 $actualResults = []; if ($type === 'logs' || $type === 'all') { $actualResults['logs'] = $this->cleanupLogs($cutoffDate, $serviceId, false); } if ($type === 'monitors' || $type === 'all') { $actualResults['monitors'] = $this->cleanupMonitors($cutoffDate, $serviceId, false); } $this->displayResults($actualResults, false); $this->info('清理完成'); return Command::SUCCESS; } catch (\Exception $e) { $this->error("清理失败: {$e->getMessage()}"); return Command::FAILURE; } } /** * 清理调用日志 * * @param \Carbon\Carbon $cutoffDate * @param int|null $serviceId * @param bool $dryRun * @return array */ protected function cleanupLogs($cutoffDate, $serviceId, bool $dryRun): array { $query = ThirdPartyLog::where('created_at', '<', $cutoffDate); if ($serviceId) { $query->where('service_id', $serviceId); } $count = $query->count(); if (!$dryRun && $count > 0) { $deleted = $query->delete(); return [ 'type' => '调用日志', 'count' => $deleted, 'size' => $this->estimateLogSize($deleted), ]; } return [ 'type' => '调用日志', 'count' => $count, 'size' => $this->estimateLogSize($count), ]; } /** * 清理监控记录 * * @param \Carbon\Carbon $cutoffDate * @param int|null $serviceId * @param bool $dryRun * @return array */ protected function cleanupMonitors($cutoffDate, $serviceId, bool $dryRun): array { $query = ThirdPartyMonitor::where('checked_at', '<', $cutoffDate); if ($serviceId) { $query->where('service_id', $serviceId); } $count = $query->count(); if (!$dryRun && $count > 0) { $deleted = $query->delete(); return [ 'type' => '监控记录', 'count' => $deleted, 'size' => $this->estimateMonitorSize($deleted), ]; } return [ 'type' => '监控记录', 'count' => $count, 'size' => $this->estimateMonitorSize($count), ]; } /** * 估算日志大小 * * @param int $count * @return string */ protected function estimateLogSize(int $count): string { // 估算每条日志记录约2KB $sizeInBytes = $count * 2048; return $this->formatBytes($sizeInBytes); } /** * 估算监控记录大小 * * @param int $count * @return string */ protected function estimateMonitorSize(int $count): string { // 估算每条监控记录约512字节 $sizeInBytes = $count * 512; return $this->formatBytes($sizeInBytes); } /** * 格式化字节大小 * * @param int $bytes * @return string */ protected function formatBytes(int $bytes): string { $units = ['B', 'KB', 'MB', 'GB']; $unitIndex = 0; while ($bytes >= 1024 && $unitIndex < count($units) - 1) { $bytes /= 1024; $unitIndex++; } return round($bytes, 2) . ' ' . $units[$unitIndex]; } /** * 显示清理结果 * * @param array $results * @param bool $dryRun * @return void */ protected function displayResults(array $results, bool $dryRun): void { if (empty($results)) { return; } $action = $dryRun ? '将要删除' : '已删除'; $this->info("\n清理结果:"); $this->line(str_repeat('-', 60)); $totalCount = 0; $totalSize = 0; foreach ($results as $result) { $this->line("{$action} {$result['type']}: {$result['count']} 条记录 ({$result['size']})"); $totalCount += $result['count']; // 简单累加字节数(这里简化处理) $sizeInBytes = $this->parseSizeToBytes($result['size']); $totalSize += $sizeInBytes; } $this->line(str_repeat('-', 60)); $this->line("总计: {$totalCount} 条记录 ({$this->formatBytes($totalSize)})"); if ($totalCount === 0) { $this->info('没有找到需要清理的记录'); } } /** * 解析大小字符串为字节数 * * @param string $size * @return int */ protected function parseSizeToBytes(string $size): int { $units = ['B' => 1, 'KB' => 1024, 'MB' => 1024*1024, 'GB' => 1024*1024*1024]; foreach ($units as $unit => $multiplier) { if (str_contains($size, $unit)) { $value = (float)str_replace(' ' . $unit, '', $size); return (int)($value * $multiplier); } } return 0; } /** * 确认删除操作 * * @param array $results * @return bool */ protected function confirmDeletion(array $results): bool { $totalCount = array_sum(array_column($results, 'count')); if ($totalCount === 0) { return false; } return $this->confirm("确认要删除 {$totalCount} 条记录吗?此操作不可恢复!"); } /** * 显示清理统计信息 * * @return void */ protected function displayCleanupStats(): void { $logCount = ThirdPartyLog::count(); $monitorCount = ThirdPartyMonitor::count(); $oldLogCount = ThirdPartyLog::where('created_at', '<', now()->subDays(30))->count(); $oldMonitorCount = ThirdPartyMonitor::where('checked_at', '<', now()->subDays(30))->count(); $this->info("\n当前统计:"); $this->line("调用日志总数: {$logCount} (30天前: {$oldLogCount})"); $this->line("监控记录总数: {$monitorCount} (30天前: {$oldMonitorCount})"); if ($oldLogCount > 0 || $oldMonitorCount > 0) { $this->warn("建议定期清理旧记录以节省存储空间"); } } }