@extends('layouts.app') @section('title', 'Log 分析收集器') @section('content') @php $activeTab = request('tab', 'logs'); $kibanaUrl = config('services.elasticsearch.kibana_url'); if (!$kibanaUrl || str_contains($kibanaUrl, 'localhost')) { $kibanaUrl = request()->getScheme() . '://' . request()->getHost() . ':5601'; } @endphp
{{-- 頁首 --}}

Log 分析收集器

@if(session('success'))
{{ session('success') }}
@endif {{-- ── 頁籤導航 ─────────────────────────────────────────────────── --}} {{-- ════════════════════════════════════════════════════════════════ --}} {{-- Tab: Log 記錄 --}} {{-- ════════════════════════════════════════════════════════════════ --}} @if($activeTab === 'logs') {{-- 頂部統計 --}}
{{ $stats['hosts'] }}
主機數
{{ number_format($stats['total']) }}
全部筆數
{{ number_format($stats['errors']) }}
錯誤筆數
{{ number_format($stats['warnings']) }}
警告筆數
{{ number_format($stats['info']) }}
資訊筆數
{{-- Log 類型分布 --}}
LOG 類型分布
@php $typeColors = ['syslog'=>'primary','auth'=>'warning','apache_access'=>'info','apache_error'=>'danger','nginx_access'=>'info','nginx_error'=>'danger','app'=>'success','other'=>'secondary']; $typeLabels = ['syslog'=>'Syslog','auth'=>'Auth','apache_access'=>'Apache','apache_error'=>'Apache Err','nginx_access'=>'Nginx','nginx_error'=>'Nginx Err','app'=>'App','other'=>'其他']; @endphp @forelse($stats['by_type'] as $ltype => $row)
{{ $typeLabels[$ltype] ?? $ltype }} {{ number_format($row->cnt) }} @if($row->errs > 0)({{ $row->errs }}E)@endif
@empty @endforelse
{{-- 主體:左側主機 + 右側表格 --}}
{{-- 左側主機列表 --}}
主機列表
{{-- 搜尋框 --}}
@php $paramsNoHost = array_filter([ 'log_type' => request('log_type'), 'severity' => request('severity'), ]); $groupedHosts = $hostList->groupBy('client_name'); @endphp {{-- 全部 --}} 全部 {{ $stats['total'] }} {{-- 依客戶分組 --}} @foreach($groupedHosts as $clientName => $items)
{{ $clientName }} {{ $items->count() }}
@foreach($items as $hItem) @php $hKey = $hItem->host_id ? (string)$hItem->host_id : 'ip_'.str_replace('.','_',$hItem->source_ip); $hActive = request('host') == $hKey; $label = $hItem->host_name ?? $hItem->hostname ?? $hItem->source_ip; @endphp @if($hItem->err_sum > 0 && !$hActive) @else @endif {{ $label }} {{ $hItem->cnt }} @endforeach
{{-- /host-group --}} @endforeach
{{-- /hostListScroll --}}
{{-- 右側 --}}
{{-- 篩選列 --}} @php $logTypeDefs = [ 'syslog' => ['label'=>'Syslog', 'color'=>'primary', 'icon'=>'bi-activity'], 'auth' => ['label'=>'Auth', 'color'=>'warning', 'icon'=>'bi-shield-lock'], 'apache_access' => ['label'=>'Apache Access', 'color'=>'info', 'icon'=>'bi-globe'], 'apache_error' => ['label'=>'Apache Error', 'color'=>'danger', 'icon'=>'bi-exclamation-circle'], 'nginx_access' => ['label'=>'Nginx Access', 'color'=>'teal', 'icon'=>'bi-globe2'], 'nginx_error' => ['label'=>'Nginx Error', 'color'=>'danger', 'icon'=>'bi-x-circle'], 'app' => ['label'=>'App', 'color'=>'success', 'icon'=>'bi-code-square'], 'other' => ['label'=>'Other', 'color'=>'secondary', 'icon'=>'bi-file-text'], ]; $paramsNoType = array_filter(['host'=>request('host'), 'severity'=>request('severity')]); $paramsNoSev = array_filter(['host'=>request('host'), 'log_type'=>request('log_type')]); @endphp
類型 全部 @foreach($logTypeDefs as $typeKey => $typeDef) {{ $typeDef['label'] }} @endforeach
{{-- Log 記錄表格 --}}
{{-- 預設工具列 --}}
@if(request('host')) {{ $selectedHostName }} @else 全部主機 @endif @if(request('log_type') && isset($logTypeDefs[request('log_type')])) @php $td = $logTypeDefs[request('log_type')]; @endphp {{ $td['label'] }} @endif @if(request('severity') === 'error') 有 Error @elseif(request('severity') === 'warning') 有 Warning @elseif(request('severity') === 'info') 正常 @endif 共 {{ $collections->total() }} 筆 @if(request('host') || request('log_type') || request('severity')) 清除篩選 @endif
{{-- 批量工具列(選取後替換預設) --}}
@forelse($collections as $c) {{-- 未讀紅點 --}} @empty @endforelse
主機 Log 類型 來源 E W 狀態 收到時間
@if(!$c->is_read) @endif @if($c->host) @php $hKey = (string)$c->host_id; @endphp {{ $c->host->name }} @else {{ $c->hostname ?? $c->source_ip ?? '—' }} @endif {{ $c->typeLabel() }} @if($c->receive_method === 'rsyslog') rsyslog @elseif($c->receive_method === 'http_upload') API @else 手動 @endif {{ $c->error_count > 0 ? $c->error_count : '·' }} {{ $c->warning_count > 0 ? $c->warning_count : '·' }} {{ $c->line_count ? number_format($c->line_count) : '—' }} @php $sc = ['pending'=>'secondary','analyzing'=>'info','done'=>'success','error'=>'danger'][$c->status] ?? 'secondary'; $sl = ['pending'=>'待分析','analyzing'=>'分析中','done'=>'完成','error'=>'錯誤'][$c->status] ?? $c->status; @endphp @if($c->status === 'analyzing') {{ $sl }} @else {{ $sl }} @endif {{ $c->created_at->format('m-d H:i') }}
@if(!$c->is_read) @endif @if($c->status === 'done') @endif
@csrf @method('DELETE')
尚無符合條件的 Log 記錄 @if(!request('host') && !request('log_type') && !request('severity')) , 或參考 設定說明 @endif
@if($collections->hasPages()) @endif
{{-- /col-md-10 --}}
{{-- /row --}} {{-- ════════════════════════════════════════════════════════════════ --}} {{-- Tab: 告警規則 --}} {{-- ════════════════════════════════════════════════════════════════ --}} @elseif($activeTab === 'alerts')
{{-- 最近告警事件 --}}
最近告警事件 @if($recentAlerts->isNotEmpty()) {{ $recentAlerts->count() }} @endif
@if($recentAlerts->isNotEmpty())
@foreach($recentAlerts as $ev) @endforeach
規則主機符合內容時間
{{ $ev->rule->name ?? '—' }} {{ $ev->host?->name ?? '—' }} {{ $ev->matched_line }} {{ $ev->occurred_at?->format('m-d H:i') }}
@else
尚無告警事件
@endif
{{-- 告警規則列表 --}}
告警規則 @if($alertRules->isNotEmpty()) {{ $alertRules->count() }} @endif
@if($alertRules->isNotEmpty())
@foreach($alertRules as $rule) @endforeach
名稱關鍵字嚴重度主機通知狀態
{{ $rule->name }} {{ Str::limit($rule->pattern, 45) }} {{ ['any'=>'任意','error'=>'Error+','critical'=>'Critical+','warning'=>'Warning'][$rule->severity_filter] ?? $rule->severity_filter }} {{ $rule->host?->name ?? '全部' }} @if($rule->notify_email) @endif @if($rule->notify_webhook) @endif @if(!$rule->notify_email && !$rule->notify_webhook)—@endif {{ $rule->enabled ? '啟用' : '停用' }}
{{-- 編輯 --}} {{-- 啟用 / 停用 --}}
@csrf
{{-- 刪除 --}}
@csrf @method('DELETE')
@else
尚無告警規則,
@endif
{{-- 右側說明 --}}
告警規則說明

當 Log 分析後發現符合規則的內容,系統會立即送出通知。

  • 關鍵字:純文字比對(不區分大小寫)
  • Regex:用 /pattern/i 格式
  • 嚴重度過濾:只對指定等級以上的 log 行比對
  • 主機:可限定只對特定主機的 log 套用規則
範例規則
名稱:SSH 登入失敗
關鍵字:Failed password
嚴重度:任意
{{-- ════════════════════════════════════════════════════════════════ --}} {{-- Tab: 趨勢分析(ES 自訂看板) --}} {{-- ════════════════════════════════════════════════════════════════ --}} @elseif($activeTab === 'es')
原始 Kibana
{{-- 摘要卡片 --}}
總筆數
錯誤
警告
主機數
{{-- 等級分佈 --}}
等級分佈
{{-- Log 類型 --}}
Log 類型
{{-- 主機分佈 --}}
主機分佈
{{-- 日誌列表 --}}
最新日誌
時間 等級 主機 類型 訊息
載入中…
{{-- ════════════════════════════════════════════════════════════════ --}} {{-- Tab: 設定說明 --}} {{-- ════════════════════════════════════════════════════════════════ --}} @elseif($activeTab === 'setup') @include('log_analysis._setup') @endif
{{-- 上傳 Modal --}} {{-- 編輯告警規則 Modal --}} {{-- 告警規則 Modal --}} @push('scripts') @endpush @endsection