dress/app/Http/Controllers/Admin/System/LogController.php

91 lines
2.6 KiB
PHP

<?php
namespace App\Http\Controllers\Admin\System;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Inertia\Inertia;
use Inertia\Response;
class LogController extends Controller
{
/**
* Display a listing of log entries.
*/
public function index(Request $request): Response
{
$logFiles = $this->getLogFiles();
// Default to the latest log file if not specified or doesn't exist
$selectedFile = $request->input('file');
if (! $selectedFile || ! in_array($selectedFile, $logFiles)) {
$selectedFile = $logFiles[0] ?? null;
}
$logs = $selectedFile ? $this->parseLogFile($selectedFile) : [];
return Inertia::render('admin/system/logs/index', [
'logFiles' => $logFiles,
'selectedFile' => $selectedFile,
'logs' => $logs,
]);
}
/**
* Get all .log files from storage/logs.
*/
private function getLogFiles(): array
{
$path = storage_path('logs');
if (! File::exists($path)) {
return [];
}
$files = File::files($path);
return collect($files)
->map(fn ($file) => $file->getFilename())
->filter(fn ($filename) => str_ends_with($filename, '.log'))
->sortDesc() // Latest dates first
->values()
->toArray();
}
/**
* Parse a log file into an array of entries.
*/
private function parseLogFile($filename): array
{
$path = storage_path("logs/{$filename}");
if (! File::exists($path)) {
return [];
}
// Limit file reading to prevent memory issues with huge logs
// For simplicity, we read the whole file here, but in production consider chunking.
$content = File::get($path);
// Pattern: [timestamp] environment.LEVEL: Message
// Handles multi-line messages (like stack traces) using lookahead
$pattern = '/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (\w+)\.(\w+): ([\s\S]*?)(?=\n^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]|$)/m';
preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);
$logs = [];
foreach ($matches as $index => $match) {
$logs[] = [
'id' => $index,
'timestamp' => $match[1],
'env' => $match[2],
'level' => strtoupper($match[3]),
'message' => trim($match[4]),
];
}
// Return latest logs first
return array_reverse($logs);
}
}