Logviewer hinzugefügt und dokploy-widget-fehler behoben
This commit is contained in:
157
app/Filament/SuperAdmin/Pages/LogViewerPage.php
Normal file
157
app/Filament/SuperAdmin/Pages/LogViewerPage.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\SuperAdmin\Pages;
|
||||
|
||||
use BackedEnum;
|
||||
use Filament\Pages\Page;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class LogViewerPage extends Page
|
||||
{
|
||||
protected static ?string $navigationLabel = 'Logs';
|
||||
|
||||
protected static ?string $title = 'Application Logs';
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-rectangle-stack';
|
||||
|
||||
protected string $view = 'filament.super-admin.pages.log-viewer';
|
||||
|
||||
public array $logFiles = [];
|
||||
|
||||
public string $selectedFile = '';
|
||||
|
||||
public string $filter = '';
|
||||
|
||||
public int $limit = 200;
|
||||
|
||||
public array $entries = [];
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->logFiles = $this->discoverLogFiles();
|
||||
$this->selectedFile = $this->logFiles[0]['name'] ?? '';
|
||||
$this->refreshLines();
|
||||
}
|
||||
|
||||
public function updatedSelectedFile(): void
|
||||
{
|
||||
$this->refreshLines();
|
||||
}
|
||||
|
||||
public function updatedFilter(): void
|
||||
{
|
||||
$this->refreshLines();
|
||||
}
|
||||
|
||||
public function updatedLimit(): void
|
||||
{
|
||||
$this->limit = max(50, min(1000, $this->limit));
|
||||
$this->refreshLines();
|
||||
}
|
||||
|
||||
protected function discoverLogFiles(): array
|
||||
{
|
||||
$paths = File::glob(storage_path('logs/*.log')) ?: [];
|
||||
|
||||
$files = collect($paths)
|
||||
->map(fn (string $path) => [
|
||||
'name' => basename($path),
|
||||
'path' => $path,
|
||||
'modified' => File::lastModified($path) ?: 0,
|
||||
'size' => File::size($path) ?: 0,
|
||||
])
|
||||
->sortByDesc('modified')
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
protected function refreshLines(): void
|
||||
{
|
||||
$path = storage_path('logs/'.$this->selectedFile);
|
||||
|
||||
if (! File::exists($path)) {
|
||||
$this->entries = [];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$rawLines = $this->tailFile($path, $this->limit * 2);
|
||||
|
||||
if ($this->filter !== '') {
|
||||
$needle = mb_strtolower($this->filter);
|
||||
$rawLines = array_values(array_filter(
|
||||
$rawLines,
|
||||
fn (string $line) => str_contains(mb_strtolower($line), $needle)
|
||||
));
|
||||
}
|
||||
|
||||
$rawLines = array_slice($rawLines, -$this->limit * 2);
|
||||
$rawLines = $this->mergeStackTraces($rawLines);
|
||||
$rawLines = array_slice(array_reverse($rawLines), 0, $this->limit);
|
||||
|
||||
$this->entries = array_map([$this, 'formatLine'], $rawLines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return last $lines lines of file. Simpler approach is fine for small logs in admin view.
|
||||
*/
|
||||
protected function tailFile(string $path, int $lines = 200): array
|
||||
{
|
||||
try {
|
||||
$contents = File::get($path);
|
||||
} catch (\Throwable) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$all = preg_split('/\r\n|\r|\n/', (string) $contents) ?: [];
|
||||
|
||||
return array_slice($all, -$lines);
|
||||
}
|
||||
|
||||
protected function mergeStackTraces(array $lines): array
|
||||
{
|
||||
$merged = [];
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$trimmed = ltrim($line);
|
||||
$isStackLine = str_starts_with($trimmed, '#')
|
||||
|| str_starts_with($trimmed, 'Stack trace:')
|
||||
|| str_starts_with($line, ' ');
|
||||
|
||||
if ($isStackLine && ! empty($merged)) {
|
||||
$merged[array_key_last($merged)] .= PHP_EOL.$line;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($line === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$merged[] = $line;
|
||||
}
|
||||
|
||||
return $merged;
|
||||
}
|
||||
|
||||
protected function formatLine(string $line): array
|
||||
{
|
||||
$level = 'info';
|
||||
$timestamp = null;
|
||||
|
||||
if (preg_match('/\\[(?<ts>[^\\]]+)\\]/', $line, $matches)) {
|
||||
$timestamp = $matches['ts'] ?? null;
|
||||
}
|
||||
|
||||
if (preg_match('/\\.(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)/i', $line, $matches)) {
|
||||
$level = strtolower($matches[1]);
|
||||
}
|
||||
|
||||
return [
|
||||
'text' => $line,
|
||||
'level' => $level,
|
||||
'timestamp' => $timestamp,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user