AutoStatisticsUserHourlyTraffic.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Models\Node;
  4. use App\Models\User;
  5. use App\Models\UserDataFlowLog;
  6. use App\Models\UserHourlyDataFlow;
  7. use Illuminate\Console\Command;
  8. use Log;
  9. class AutoStatisticsUserHourlyTraffic extends Command
  10. {
  11. protected $signature = 'autoStatisticsUserHourlyTraffic';
  12. protected $description = '自动统计用户每小时流量';
  13. public function handle(): void
  14. {
  15. $jobStartTime = microtime(true);
  16. echo "🟢 开始执行 autoStatisticsUserHourlyTraffic...\n";
  17. Log::info('🟢 开始执行 autoStatisticsUserHourlyTraffic');
  18. $startTime = strtotime('-1 hour');
  19. $endTime = time();
  20. // 获取 [user_id, node_id] 的流量聚合
  21. $records = UserDataFlowLog::whereBetween('log_time', [$startTime, $endTime])
  22. ->selectRaw('user_id, node_id, SUM(u) as sum_u, SUM(d) as sum_d')
  23. ->groupBy('user_id', 'node_id')
  24. ->get();
  25. $userTotals = [];
  26. $checkedUsers = [];
  27. $checkedNodes = [];
  28. foreach ($records as $record) {
  29. $user_id = $record->user_id;
  30. $node_id = $record->node_id;
  31. // 缓存判断用户是否存在
  32. if (!isset($checkedUsers[$user_id])) {
  33. $checkedUsers[$user_id] = User::where('id', $user_id)->exists();
  34. }
  35. if (!$checkedUsers[$user_id]) {
  36. Log::warning("跳过记录,用户不存在: user_id=$user_id");
  37. continue;
  38. }
  39. // 缓存判断节点是否存在
  40. if (!isset($checkedNodes[$node_id])) {
  41. $checkedNodes[$node_id] = Node::where('id', $node_id)->exists();
  42. }
  43. if (!$checkedNodes[$node_id]) {
  44. Log::warning("跳过记录,节点不存在: node_id=$node_id");
  45. continue;
  46. }
  47. $u = $record->sum_u ?? 0;
  48. $d = $record->sum_d ?? 0;
  49. $total = $u + $d;
  50. //Log::info("📊 保存流量记录 - user: $user_id, node: $node_id, u: $u, d: $d, total: $total");
  51. UserHourlyDataFlow::create([
  52. 'user_id' => $user_id,
  53. 'node_id' => $node_id,
  54. 'u' => $u,
  55. 'd' => $d,
  56. 'total' => $total,
  57. 'traffic' => flowAutoShow($total),
  58. ]);
  59. // 累计每个用户的总流量
  60. if (!isset($userTotals[$user_id])) {
  61. $userTotals[$user_id] = 0;
  62. }
  63. $userTotals[$user_id] += $total;
  64. }
  65. // 判断是否超出阈值
  66. $trafficBanValue = sysConfig('traffic_ban_value');
  67. foreach ($userTotals as $user_id => $total) {
  68. if ($total > $trafficBanValue * GB) {
  69. $user = User::find($user_id);
  70. $email = $user->email ?? '未知邮箱';
  71. Log::warning("⚠️ 用户 [ID: $user_id, 邮箱: $email] 最近1小时流量异常:已使用 ".flowAutoShow($total));
  72. echo "⚠️ 异常用户: $email, 使用 ".flowAutoShow($total)."\n";
  73. }
  74. }
  75. $jobUsedTime = round((microtime(true) - $jobStartTime), 4);
  76. Log::info("✅ autoStatisticsUserHourlyTraffic 执行完成,耗时 {$jobUsedTime} 秒");
  77. echo "✅ 执行完成,耗时 {$jobUsedTime} 秒\n";
  78. }
  79. private function statisticsByNode($user_id, $node_id = null): void
  80. {
  81. $query = UserDataFlowLog::whereUserId($user_id)
  82. ->whereBetween('log_time', [strtotime('-1 hour'), time()]);
  83. if ($node_id) {
  84. $query->whereNodeId($node_id);
  85. }
  86. $sums = $query->selectRaw('SUM(u) as sum_u, SUM(d) as sum_d')->first();
  87. $u = $sums->sum_u ?? 0;
  88. $d = $sums->sum_d ?? 0;
  89. $total = $u + $d;
  90. if ($total > 0) {
  91. Log::info("📊 保存流量记录 - user: $user_id, node: " . ($node_id ?? '总计') . ", u: $u, d: $d, total: $total");
  92. UserHourlyDataFlow::create([
  93. 'user_id' => $user_id,
  94. 'node_id' => $node_id,
  95. 'u' => $u,
  96. 'd' => $d,
  97. 'total' => $total,
  98. 'traffic' => flowAutoShow($total),
  99. ]);
  100. }
  101. // 检查是否超过阈值(仅统计总流量)
  102. if (is_null($node_id)) {
  103. $trafficBanValue = sysConfig('traffic_ban_value');
  104. if ($total > $trafficBanValue * GB) {
  105. $user = User::find($user_id);
  106. $email = $user->email ?? '未知邮箱';
  107. Log::warning("⚠️ 用户 [ID: $user_id, 邮箱: $email] 最近1小时流量异常:已使用 ".flowAutoShow($total));
  108. echo "⚠️ 异常用户: $email, 使用 ".flowAutoShow($total)."\n";
  109. }
  110. }
  111. }
  112. }