217 lines
7.1 KiB
PHP
217 lines
7.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Filament\Admin\Widgets;
|
|
|
|
use App\Services\Agent\AgentClient;
|
|
use Filament\Actions\Concerns\InteractsWithActions;
|
|
use Filament\Actions\Contracts\HasActions;
|
|
use Filament\Schemas\Concerns\InteractsWithSchemas;
|
|
use Filament\Schemas\Contracts\HasSchemas;
|
|
use Filament\Tables\Columns\TextColumn;
|
|
use Filament\Tables\Concerns\InteractsWithTable;
|
|
use Filament\Tables\Contracts\HasTable;
|
|
use Filament\Tables\Table;
|
|
use Livewire\Component;
|
|
|
|
class SystemInfoTableWidget extends Component implements HasActions, HasSchemas, HasTable
|
|
{
|
|
use InteractsWithActions;
|
|
use InteractsWithSchemas;
|
|
use InteractsWithTable;
|
|
|
|
public array $info = [];
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->loadInfo();
|
|
}
|
|
|
|
protected function loadInfo(): void
|
|
{
|
|
try {
|
|
$agent = new AgentClient;
|
|
$overview = $agent->metricsOverview();
|
|
$network = $agent->metricsNetwork()['data'] ?? [];
|
|
|
|
// Get primary interface IP
|
|
$primaryIp = '127.0.0.1';
|
|
$interfaces = $network['interfaces'] ?? [];
|
|
foreach ($interfaces as $name => $iface) {
|
|
if ($name !== 'lo' && ! empty($iface['ip'])) {
|
|
$primaryIp = explode('/', $iface['ip'])[0];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Parse OS info
|
|
$osInfo = $overview['os'] ?? [];
|
|
$osName = is_array($osInfo) ? ($osInfo['name'] ?? 'Linux') : 'Linux';
|
|
$osVersion = is_array($osInfo) ? ($osInfo['version'] ?? '') : '';
|
|
|
|
// Format memory
|
|
$ramTotal = $overview['memory']['total'] ?? 0;
|
|
$ramUsed = $overview['memory']['used'] ?? 0;
|
|
$ramPercent = round($overview['memory']['usage_percent'] ?? 0, 1);
|
|
|
|
// Shorten CPU model
|
|
$cpuModel = $overview['cpu']['model'] ?? 'Unknown';
|
|
$cpuModel = str_replace(['(R)', '(TM)', 'CPU', '@'], '', $cpuModel);
|
|
$cpuModel = preg_replace('/\s+/', ' ', trim($cpuModel));
|
|
if (strlen($cpuModel) > 35) {
|
|
$cpuModel = substr($cpuModel, 0, 32).'...';
|
|
}
|
|
|
|
$this->info = [
|
|
[
|
|
'category' => __('Server'),
|
|
'property' => __('Hostname'),
|
|
'value' => $overview['hostname'] ?? gethostname(),
|
|
],
|
|
[
|
|
'category' => __('Server'),
|
|
'property' => __('Uptime'),
|
|
'value' => $overview['uptime']['human'] ?? 'N/A',
|
|
],
|
|
[
|
|
'category' => __('Server'),
|
|
'property' => __('OS'),
|
|
'value' => trim("$osName $osVersion") ?: 'Linux',
|
|
],
|
|
[
|
|
'category' => __('Server'),
|
|
'property' => __('IP Address'),
|
|
'value' => $primaryIp,
|
|
],
|
|
[
|
|
'category' => __('Server'),
|
|
'property' => __('Connections'),
|
|
'value' => number_format($network['connections'] ?? 0),
|
|
],
|
|
[
|
|
'category' => __('Hardware'),
|
|
'property' => __('Processor'),
|
|
'value' => $cpuModel,
|
|
],
|
|
[
|
|
'category' => __('Hardware'),
|
|
'property' => __('CPU Cores'),
|
|
'value' => (string) ($overview['cpu']['cores'] ?? 1),
|
|
],
|
|
[
|
|
'category' => __('Hardware'),
|
|
'property' => __('Memory'),
|
|
'value' => $this->formatMb($ramUsed).' / '.$this->formatMb($ramTotal)." ({$ramPercent}%)",
|
|
],
|
|
[
|
|
'category' => __('Software'),
|
|
'property' => 'PHP',
|
|
'value' => PHP_VERSION,
|
|
],
|
|
[
|
|
'category' => __('Software'),
|
|
'property' => __('Database'),
|
|
'value' => $this->getDatabaseVersion(),
|
|
],
|
|
[
|
|
'category' => __('Software'),
|
|
'property' => __('Web Server'),
|
|
'value' => $this->getWebserverVersion(),
|
|
],
|
|
[
|
|
'category' => __('Software'),
|
|
'property' => 'Laravel',
|
|
'value' => app()->version(),
|
|
],
|
|
];
|
|
} catch (\Exception $e) {
|
|
$this->info = [];
|
|
}
|
|
}
|
|
|
|
protected function formatMb(int $mb): string
|
|
{
|
|
if ($mb >= 1024) {
|
|
return round($mb / 1024, 1).' GB';
|
|
}
|
|
|
|
return $mb.' MB';
|
|
}
|
|
|
|
protected function getDatabaseVersion(): string
|
|
{
|
|
// Try SQL query first
|
|
try {
|
|
$version = \DB::select('SELECT VERSION() as version')[0]->version ?? '';
|
|
if (preg_match('/^(\d+\.\d+\.\d+)/', $version, $matches)) {
|
|
$dbType = str_contains(strtolower($version), 'mariadb') ? 'MariaDB' : 'MySQL';
|
|
|
|
return "$dbType {$matches[1]}";
|
|
}
|
|
|
|
if ($version) {
|
|
return $version;
|
|
}
|
|
} catch (\Exception $e) {
|
|
// Fall through to command line fallback
|
|
}
|
|
|
|
// Fallback to mysqld --version command
|
|
$output = shell_exec('mysqld --version 2>/dev/null');
|
|
if ($output && preg_match('/Ver\s+(\d+\.\d+\.\d+)-?(MariaDB)?/i', $output, $matches)) {
|
|
$dbType = ! empty($matches[2]) ? 'MariaDB' : 'MySQL';
|
|
|
|
return "$dbType {$matches[1]}";
|
|
}
|
|
|
|
return 'N/A';
|
|
}
|
|
|
|
protected function getWebserverVersion(): string
|
|
{
|
|
$version = shell_exec('nginx -v 2>&1');
|
|
if ($version && preg_match('/nginx\/(\d+\.\d+\.\d+)/', $version, $matches)) {
|
|
return "Nginx {$matches[1]}";
|
|
}
|
|
|
|
return 'Nginx';
|
|
}
|
|
|
|
public function makeFilamentTranslatableContentDriver(): ?\Filament\Support\Contracts\TranslatableContentDriver
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public function table(Table $table): Table
|
|
{
|
|
return $table
|
|
->records(fn () => $this->info)
|
|
->columns([
|
|
TextColumn::make('category')
|
|
->label(__('Category'))
|
|
->badge()
|
|
->color(fn (string $state): string => match ($state) {
|
|
__('Server') => 'primary',
|
|
__('Hardware') => 'warning',
|
|
__('Software') => 'success',
|
|
default => 'gray',
|
|
}),
|
|
TextColumn::make('property')
|
|
->label(__('Property'))
|
|
->weight('medium'),
|
|
TextColumn::make('value')
|
|
->label(__('Value'))
|
|
->fontFamily('mono')
|
|
->color('gray'),
|
|
])
|
|
->paginated(false)
|
|
->striped();
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return $this->getTable()->render();
|
|
}
|
|
}
|