CollectUserLogsContinuousCommand.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. namespace App\Module\Game\Commands;
  3. use App\Module\Game\Logics\UserLogCollectorManager;
  4. use UCore\Command\Command;
  5. /**
  6. * 用户日志持续收集命令
  7. *
  8. * 持续运行的日志收集命令,循环100次后退出,间隔1秒
  9. * 复用CollectUserLogsCommand的核心逻辑
  10. */
  11. class CollectUserLogsContinuousCommand extends Command
  12. {
  13. /**
  14. * 命令名称和参数
  15. *
  16. * @var string
  17. */
  18. protected $signature = 'game:collect-user-logs-continuous {--detail : 显示详细的处理过程} {--limit=1000 : 单次处理最大记录数} {--cycles=100 : 循环次数} {--interval=1 : 间隔秒数}';
  19. /**
  20. * 命令描述
  21. *
  22. * @var string
  23. */
  24. protected $description = '持续收集用户日志,循环指定次数后退出
  25. 选项说明:
  26. --detail 显示详细的处理过程
  27. --limit 单次处理最大记录数(默认1000)
  28. --cycles 循环次数(默认100)
  29. --interval 间隔秒数(默认1秒)
  30. 注意:此命令会持续运行指定的循环次数,每次循环间隔指定时间,适用于需要持续监控日志收集的场景';
  31. /**
  32. * 执行命令
  33. */
  34. public function handleRun()
  35. {
  36. $detail = $this->option('detail');
  37. $limit = (int)$this->option('limit');
  38. $cycles = (int)$this->option('cycles');
  39. $interval = (int)$this->option('interval');
  40. // 参数验证
  41. if ($cycles <= 0) {
  42. $this->error("❌ 循环次数必须大于0");
  43. return 1;
  44. }
  45. if ($interval < 0) {
  46. $this->error("❌ 间隔时间不能小于0");
  47. return 1;
  48. }
  49. $this->info("🚀 开始持续收集用户日志...");
  50. $this->line("📊 配置信息:");
  51. $this->line(" 🔄 循环次数: <info>{$cycles}</info>");
  52. $this->line(" ⏱️ 间隔时间: <info>{$interval}秒</info>");
  53. $this->line(" 📝 单次限制: <info>{$limit}条</info>");
  54. $this->line("");
  55. $manager = new UserLogCollectorManager();
  56. $totalProcessed = 0;
  57. $totalExecutionTime = 0;
  58. $successfulCycles = 0;
  59. $failedCycles = 0;
  60. $startTime = microtime(true);
  61. for ($i = 1; $i <= $cycles; $i++) {
  62. $cycleStartTime = microtime(true);
  63. try {
  64. if ($detail) {
  65. $this->line("🔄 第 {$i}/{$cycles} 次循环开始...");
  66. }
  67. // 复用原有的收集逻辑
  68. $result = $this->executeTimelineCollection($manager, $limit, $detail);
  69. $cycleEndTime = microtime(true);
  70. $cycleExecutionTime = round(($cycleEndTime - $cycleStartTime) * 1000, 2);
  71. $totalProcessed += $result['processed_count'];
  72. $totalExecutionTime += $cycleExecutionTime;
  73. $successfulCycles++;
  74. if ($detail) {
  75. $this->line("✅ 第 {$i} 次循环完成: 处理 {$result['processed_count']} 条记录,耗时 {$cycleExecutionTime}ms");
  76. } else {
  77. // 简化输出,只显示有处理记录的循环
  78. if ($result['processed_count'] > 0) {
  79. $this->line("✅ 第 {$i} 次: 处理 {$result['processed_count']} 条记录");
  80. }
  81. }
  82. } catch (\Exception $e) {
  83. $failedCycles++;
  84. $this->error("❌ 第 {$i} 次循环失败: {$e->getMessage()}");
  85. if ($detail) {
  86. $this->line("🚨 错误详情: " . $e->getTraceAsString());
  87. }
  88. }
  89. // 如果不是最后一次循环,则等待间隔时间
  90. if ($i < $cycles && $interval > 0) {
  91. if ($detail) {
  92. $this->line("⏳ 等待 {$interval} 秒...");
  93. }
  94. sleep($interval);
  95. }
  96. }
  97. $endTime = microtime(true);
  98. $totalRealTime = round(($endTime - $startTime) * 1000, 2);
  99. // 显示最终统计
  100. $this->displayFinalStatistics($cycles, $successfulCycles, $failedCycles, $totalProcessed, $totalExecutionTime, $totalRealTime);
  101. return $failedCycles > 0 ? 1 : 0;
  102. }
  103. /**
  104. * 执行时间线收集(复用原有逻辑)
  105. *
  106. * @param UserLogCollectorManager $manager
  107. * @param int $limit
  108. * @param bool $detail
  109. * @return array
  110. */
  111. private function executeTimelineCollection(UserLogCollectorManager $manager, int $limit, bool $detail): array
  112. {
  113. $startTime = microtime(true);
  114. // 直接执行所有收集器,传递限制参数
  115. $results = $manager->collectAll($limit);
  116. if ($results['total_processed'] == 0) {
  117. return [
  118. 'processed_count' => 0,
  119. 'execution_time' => round((microtime(true) - $startTime) * 1000, 2),
  120. 'status' => 'success',
  121. 'message' => '没有新记录需要处理',
  122. 'timestamp' => now()->toDateTimeString()
  123. ];
  124. }
  125. if ($detail) {
  126. foreach ($results['collectors'] as $collectorName => $result) {
  127. if ($result['processed_count'] > 0) {
  128. $this->line(" {$collectorName}: 处理了 {$result['processed_count']} 条记录");
  129. }
  130. }
  131. }
  132. $endTime = microtime(true);
  133. return [
  134. 'processed_count' => $results['total_processed'],
  135. 'execution_time' => round(($endTime - $startTime) * 1000, 2),
  136. 'status' => 'success',
  137. 'timestamp' => now()->toDateTimeString(),
  138. 'details' => $results['collectors']
  139. ];
  140. }
  141. /**
  142. * 显示最终统计信息
  143. *
  144. * @param int $totalCycles
  145. * @param int $successfulCycles
  146. * @param int $failedCycles
  147. * @param int $totalProcessed
  148. * @param float $totalExecutionTime
  149. * @param float $totalRealTime
  150. * @return void
  151. */
  152. private function displayFinalStatistics(int $totalCycles, int $successfulCycles, int $failedCycles, int $totalProcessed, float $totalExecutionTime, float $totalRealTime): void
  153. {
  154. $this->line("");
  155. $this->info("🎉 持续收集完成!");
  156. $this->line("");
  157. $this->line("📊 <comment>执行统计</comment>:");
  158. $this->line(" 🔄 总循环次数: <info>{$totalCycles}</info>");
  159. $this->line(" ✅ 成功次数: <info>{$successfulCycles}</info>");
  160. if ($failedCycles > 0) {
  161. $this->line(" ❌ 失败次数: <error>{$failedCycles}</error>");
  162. }
  163. $this->line(" 📝 总处理记录: <info>{$totalProcessed}</info>");
  164. $this->line(" ⏱️ 总执行时间: <info>{$totalExecutionTime}ms</info>");
  165. $this->line(" 🕐 总运行时间: <info>{$totalRealTime}ms</info>");
  166. if ($totalProcessed > 0) {
  167. $avgTimePerRecord = round($totalExecutionTime / $totalProcessed, 2);
  168. $this->line(" 📈 平均处理时间: <info>{$avgTimePerRecord}ms/条</info>");
  169. }
  170. if ($successfulCycles > 0) {
  171. $avgRecordsPerCycle = round($totalProcessed / $successfulCycles, 2);
  172. $this->line(" 📊 平均每次处理: <info>{$avgRecordsPerCycle}条</info>");
  173. }
  174. $successRate = round(($successfulCycles / $totalCycles) * 100, 2);
  175. $this->line(" 🎯 成功率: <info>{$successRate}%</info>");
  176. $this->line("");
  177. }
  178. }