1. [Machine Model] 實作智慧抖動偵測邏輯 (Jitter Detection),判定 1 小時內斷線 3 次以上為不穩定機台。
2. [Machine Model] 優化 calculated_status,機台在線時自動忽略歷史斷線警告,並修正 scopeHasAnyAlert 排除連線類告警。
3. [ProcessStatus Job] 實作自動消警機制 (Auto-resolve),機台恢復連線時自動處理舊的斷線告警。
4. [Dashboard] 同步儀表板「待處理告警」統計,確保與機台列表狀態一致。
5. [UI] 於機台列表與儀表板同步新增琥珀色閃電圖示 (⚡) 與不穩定提示 Tooltip。
6. [i18n] 新增連線不穩定相關之繁體中文翻譯詞條。
86 lines
2.6 KiB
PHP
86 lines
2.6 KiB
PHP
<?php
|
||
|
||
namespace App\Jobs\Machine;
|
||
|
||
use App\Models\Machine\Machine;
|
||
use App\Jobs\Machine\ProcessStateLog;
|
||
use Illuminate\Bus\Queueable;
|
||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||
use Illuminate\Foundation\Bus\Dispatchable;
|
||
use Illuminate\Queue\InteractsWithQueue;
|
||
use Illuminate\Queue\SerializesModels;
|
||
use Illuminate\Support\Facades\Log;
|
||
|
||
class ProcessStatus implements ShouldQueue
|
||
{
|
||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||
|
||
protected $serialNo;
|
||
protected $payload;
|
||
|
||
/**
|
||
* Create a new job instance.
|
||
*/
|
||
public function __construct($serialNo, $payload)
|
||
{
|
||
$this->serialNo = $serialNo;
|
||
$this->payload = $payload;
|
||
}
|
||
|
||
/**
|
||
* Execute the job.
|
||
*/
|
||
public function handle(): void
|
||
{
|
||
$machine = Machine::withoutGlobalScopes()->where('serial_no', $this->serialNo)->first();
|
||
|
||
if (!$machine) {
|
||
Log::warning("ProcessStatus: Machine not found [{$this->serialNo}]");
|
||
return;
|
||
}
|
||
|
||
// Get status from payload, e.g. {"status": "offline"}
|
||
$status = $this->payload['status'] ?? null;
|
||
|
||
if (!$status) {
|
||
Log::warning("ProcessStatus: Missing status in payload", ['payload' => $this->payload]);
|
||
return;
|
||
}
|
||
|
||
$oldStatus = $machine->status;
|
||
|
||
$updateData = ['status' => $status];
|
||
if ($status === 'online') {
|
||
$updateData['last_heartbeat_at'] = now();
|
||
|
||
// 自動消警:當機台恢復連線時,自動標記之前的「斷線 (LWT)」警告為已解決
|
||
$machine->logs()
|
||
->where('type', 'status')
|
||
->where('level', 'warning')
|
||
->where('message', 'Connection lost (LWT)')
|
||
->where('is_resolved', false)
|
||
->update(['is_resolved' => true]);
|
||
}
|
||
|
||
$machine->update($updateData);
|
||
|
||
// 若是計畫性重啟狀態,靜默處理,不寫 log(避免管理後台誤報)
|
||
if ($status === 'restarting') {
|
||
Log::info("ProcessStatus: Machine [{$machine->serial_no}] is restarting (planned), suppressing log.");
|
||
return;
|
||
}
|
||
|
||
// If status changed, log it
|
||
if ($oldStatus !== $status) {
|
||
$level = ($status === 'offline') ? 'warning' : 'info';
|
||
$message = ($status === 'offline')
|
||
? "Connection lost (LWT)"
|
||
: "Connection restored";
|
||
|
||
ProcessStateLog::dispatch($machine->id, $machine->company_id, $message, $level);
|
||
|
||
Log::info("ProcessStatus: Machine [{$machine->serial_no}] status changed to [{$status}]");
|
||
}
|
||
}
|
||
}
|