feat(logs): structured cron run history + read endpoint
Adds unifi_cron_runs table (one row per scheduled-task execution) and
UnifiCronRun::record() wrapper that captures start/finish/status and
exceptions. The three scheduled commands now write through it:
- reboot-all-aps → rebooted/failed AP names per run
- rotate-passwords → rotated SSIDs + PPSKs, failures (when actually
rotating; the "is it due" early-return is silent
so we don't flood the log with no-op rows every
minute)
- sync-ppsk-schedules → enabled/disabled PPSKs (silent when there's
no work)
UnifiCronLogsController returns the most-recent 200 runs as JSON,
filterable by command + status. Behind permission:unifi.settings; no
super-admin required — read-only history is fine for any operator
who can see settings.
v1.5.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
43
src/Http/Controllers/UnifiCronLogsController.php
Normal file
43
src/Http/Controllers/UnifiCronLogsController.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Dashboard\Unifi\Http\Controllers;
|
||||
|
||||
use Dashboard\Unifi\Models\UnifiCronRun;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
class UnifiCronLogsController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$filters = $request->only(['command', 'status']);
|
||||
|
||||
$runs = UnifiCronRun::query()
|
||||
->with('triggeredByUser:id,name,email')
|
||||
->when($filters['command'] ?? null, fn ($q, $c) => $q->where('command', $c))
|
||||
->when($filters['status'] ?? null, fn ($q, $s) => $q->where('status', $s))
|
||||
->orderByDesc('started_at')
|
||||
->limit(200)
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'runs' => $runs->map(fn ($r) => [
|
||||
'id' => $r->id,
|
||||
'command' => $r->command,
|
||||
'triggered_by' => $r->triggered_by,
|
||||
'triggered_user' => $r->triggeredByUser ? [
|
||||
'id' => $r->triggeredByUser->id,
|
||||
'name' => $r->triggeredByUser->name,
|
||||
'email' => $r->triggeredByUser->email,
|
||||
] : null,
|
||||
'started_at' => $r->started_at?->toIso8601String(),
|
||||
'finished_at' => $r->finished_at?->toIso8601String(),
|
||||
'duration_ms' => $r->finished_at && $r->started_at
|
||||
? (int) $r->finished_at->diffInMilliseconds($r->started_at)
|
||||
: null,
|
||||
'status' => $r->status,
|
||||
'details' => $r->details,
|
||||
])->values(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user