Nessuna descrizione

LogMonitorWarn.php 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Models\Sys\SysLogRecord;
  4. use App\Support\EmailQueue;
  5. use App\Support\EsModel;
  6. use Illuminate\Console\Command;
  7. class LogMonitorWarn extends Command
  8. {
  9. /**
  10. * The name and signature of the console command.
  11. *
  12. * @var string
  13. */
  14. protected $signature = 'LogMonitorWarn';
  15. /**
  16. * The console command description.
  17. *
  18. * @var string
  19. */
  20. protected $description = '日志监控预警';
  21. /**
  22. * Create a new command instance.
  23. *
  24. * @return void
  25. */
  26. public function __construct()
  27. {
  28. parent::__construct();
  29. }
  30. /**
  31. * Execute the console command.
  32. *
  33. * @return int
  34. */
  35. public function handle()
  36. {
  37. $this->info(date('H:i') . ' 开始执行');
  38. $this->start();
  39. $this->info(date('H:i') . ' 结束执行');
  40. return 0;
  41. }
  42. public function start()
  43. {
  44. list($D, $H, $I) = explode('-', date('d-H-i'));
  45. # 监测
  46. if ((($H % 1) == 0) && ($I == 0)) {
  47. // $this->check("-1 hour");
  48. }
  49. # 清除上个月索引
  50. // if ($D == 1 && $H == 1 && $I == 0) {
  51. // $this->lastMonIdxClear();
  52. // }
  53. # 清除sql记录
  54. if ($H == 1 && $I == 0) {
  55. $this->sqlClear();
  56. }
  57. }
  58. public function check($timeRag)
  59. {
  60. $emails = env('EXCEPTION_REPORT_EMAIL');
  61. if (empty($emails)) return true;
  62. // list($total, $examples, $exFileCnt) = self::esQuery($timeRag);
  63. list($total, $examples, $exFileCnt) = self::sqlQuery($timeRag);
  64. if (!empty($examples)) {
  65. # 发送邮件
  66. EmailQueue::rPush("日志监控预警", $timeRag."监测:总共 {$total} 错误,包含 {$exFileCnt} 文件<br>示例:<br>".implode("<br>", $examples), explode(',', $emails));
  67. }
  68. }
  69. public function lastMonIdxClear()
  70. {
  71. $index = 'kwaiad-log-'.date('Y.m', strtotime("-1 month"));
  72. if (EsModel::existsIdx($index)) EsModel::deleteIdx($index);
  73. }
  74. protected function esQuery($timeRag)
  75. {
  76. $_source = ["level", "msg", "exFile"];
  77. $filter = [
  78. [
  79. "term" => [
  80. "level" => "ERROR"
  81. ]
  82. ],
  83. [
  84. "range" => [
  85. "fTime" => [
  86. 'gte' => date('Y-m-d H:i:s', strtotime($timeRag)),
  87. 'lte' => date('Y-m-d H:i:s')
  88. ]
  89. ]
  90. ]
  91. ];
  92. $aggs = [
  93. "exFileCnt" => [
  94. "cardinality" => [
  95. "field" => "exFile"
  96. ]
  97. ]
  98. ];
  99. # 拼装搜索条件
  100. $searchData = [
  101. "index" => "kwaiad-log-".date('Y.m'),
  102. "body" => [
  103. "_source" => $_source,
  104. "query" => [
  105. "bool" => [
  106. "filter" => $filter,
  107. ]
  108. ],
  109. "size" => 1000,
  110. "aggs" => $aggs
  111. ]
  112. ];
  113. # 查询
  114. $data = EsModel::searchDoc($searchData);
  115. if(!isset($data['hits']['total']['value']) || $data['hits']['total']['value'] == 0) {
  116. return true;
  117. }
  118. # 错误总数
  119. $total = $data['hits']['total']['value'];
  120. # 示例展示
  121. $examples = [];
  122. $hits = $data['hits']['hits'];
  123. foreach($hits as $hit) {
  124. $item = $hit['_source'];
  125. $key = md5($item['exFile'].'###'.$item['msg']);
  126. if (isset($examples[$key])) continue;
  127. $examples[$key] = '文件:'.$item['exFile'].' 错误信息:'.$item['msg'];
  128. }
  129. # 文件数
  130. $exFileCnt = $data['aggregations']['exFileCnt']['value'];
  131. return [$total, $examples, $exFileCnt];
  132. }
  133. public function sqlClear()
  134. {
  135. SysLogRecord::query()
  136. ->where('created_at', '<', date('Y-m-d H:i:s', strtotime("-5 day")))
  137. ->delete();
  138. }
  139. protected function sqlQuery($timeRag)
  140. {
  141. $query = SysLogRecord::query()
  142. ->select(['content', 'file'])
  143. ->where('level', 'ERROR')
  144. ->whereBetween('created_at', [
  145. date('Y-m-d H:i:s', strtotime($timeRag)),
  146. date('Y-m-d H:i:s')
  147. ]);
  148. $total = $query->count();
  149. if ($total == 0) return [0, [], 0];
  150. $list = $query->groupBy(['file', 'content'])->get();
  151. $exFileCnt = count(array_unique($list->pluck('file')->all()));
  152. $examples = [];
  153. foreach ($list as $item) {
  154. $examples[] = '文件:'.$item->file.' 错误信息:'.$item->content;
  155. }
  156. return [$total, $examples, $exFileCnt];
  157. }
  158. }