diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index 1dd998646..5b8505970 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -2,6 +2,7 @@
namespace App\Console;
+use App\Jobs\NodeStatistics;
use App\Models\ActivityLog;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Database\Console\PruneCommand;
@@ -32,6 +33,8 @@ class Kernel extends ConsoleKernel
$schedule->command(ProcessRunnableCommand::class)->everyMinute()->withoutOverlapping();
$schedule->command(CleanServiceBackupFilesCommand::class)->daily();
+ $schedule->job(new NodeStatistics())->everyFiveSeconds()->withoutOverlapping();
+
if (config('backups.prune_age')) {
// Every 30 minutes, run the backup pruning command so that any abandoned backups can be deleted.
$schedule->command(PruneOrphanedBackupsCommand::class)->everyThirtyMinutes();
diff --git a/app/Filament/Resources/NodeResource/Pages/EditNode.php b/app/Filament/Resources/NodeResource/Pages/EditNode.php
index 94ea3a8a4..c6fd0e451 100644
--- a/app/Filament/Resources/NodeResource/Pages/EditNode.php
+++ b/app/Filament/Resources/NodeResource/Pages/EditNode.php
@@ -3,12 +3,11 @@
namespace App\Filament\Resources\NodeResource\Pages;
use App\Filament\Resources\NodeResource;
-use App\Filament\Resources\NodeResource\Widgets\NodeMemoryChart;
-use App\Filament\Resources\NodeResource\Widgets\NodeStorageChart;
use App\Models\Node;
use App\Services\Nodes\NodeUpdateService;
use Filament\Actions;
use Filament\Forms;
+use Filament\Forms\Components\Fieldset;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Tabs;
@@ -17,6 +16,7 @@ use Filament\Forms\Components\TagsInput;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\ToggleButtons;
+use Filament\Forms\Components\View;
use Filament\Forms\Get;
use Filament\Forms\Set;
use Filament\Notifications\Notification;
@@ -41,6 +41,32 @@ class EditNode extends EditRecord
->persistTabInQueryString()
->columnSpanFull()
->tabs([
+ Tab::make('')
+ ->label('Overview')
+ ->icon('tabler-chart-area-line-filled')
+ ->columns(6)
+ ->schema([
+ Fieldset::make()
+ ->label('Node Information')
+ ->columns(4)
+ ->schema([
+ Placeholder::make('')
+ ->label('Wings Version')
+ ->content(fn (Node $node) => $node->systemInformation()['version']),
+ Placeholder::make('')
+ ->label('CPU Threads')
+ ->content(fn (Node $node) => $node->systemInformation()['cpu_count']),
+ Placeholder::make('')
+ ->label('Architecture')
+ ->content(fn (Node $node) => $node->systemInformation()['architecture']),
+ Placeholder::make('')
+ ->label('Kernel')
+ ->content(fn (Node $node) => $node->systemInformation()['kernel_version']),
+ ]),
+ View::make('filament.components.node-cpu-chart')->columnSpan(3),
+ View::make('filament.components.node-memory-chart')->columnSpan(3),
+ // TODO: Make purdy View::make('filament.components.node-storage-chart')->columnSpan(3),
+ ]),
Tab::make('Basic Settings')
->icon('tabler-server')
->schema([
@@ -437,16 +463,17 @@ class EditNode extends EditRecord
];
}
- protected function getFooterWidgets(): array
- {
- return [
- NodeStorageChart::class,
- NodeMemoryChart::class,
- ];
- }
-
protected function afterSave(): void
{
$this->fillForm();
}
+
+ protected function getColumnSpan()
+ {
+ return null;
+ }
+ protected function getColumnStart()
+ {
+ return null;
+ }
}
diff --git a/app/Filament/Resources/NodeResource/Widgets/NodeCpuChart.php b/app/Filament/Resources/NodeResource/Widgets/NodeCpuChart.php
new file mode 100644
index 000000000..ecc6bc592
--- /dev/null
+++ b/app/Filament/Resources/NodeResource/Widgets/NodeCpuChart.php
@@ -0,0 +1,81 @@
+record;
+ $threads = $node->systemInformation()['cpu_count'];
+
+ $cpu = collect(cache()->get("nodes.$node->id.cpu_percent"))
+ ->slice(-10)
+ ->map(fn ($value, $key) => [
+ 'cpu' => number_format($value * $threads, 2),
+ 'timestamp' => Carbon::createFromTimestamp($key, (auth()->user()->timezone ?? 'UTC'))->format('H:i:s'),
+ ])
+ ->all();
+
+ return [
+ 'datasets' => [
+ [
+ 'data' => array_column($cpu, 'cpu'),
+ 'backgroundColor' => [
+ 'rgba(96, 165, 250, 0.3)',
+ ],
+ 'tension' => '0.3',
+ 'fill' => true,
+ ],
+ ],
+ 'labels' => array_column($cpu, 'timestamp'),
+ ];
+ }
+
+ protected function getType(): string
+ {
+ return 'line';
+ }
+
+ protected function getOptions(): RawJs
+ {
+ return RawJs::make(<<<'JS'
+ {
+ scales: {
+ y: {
+ min: 0,
+ },
+ },
+ plugins: {
+ legend: {
+ display: false,
+ }
+ }
+ }
+ JS);
+ }
+
+ public function getHeading(): string
+ {
+ /** @var Node $node */
+ $node = $this->record;
+ $threads = $node->systemInformation()['cpu_count'];
+
+ $cpu = number_format(collect(cache()->get("nodes.$node->id.cpu_percent"))->last() * $threads, 2);
+ $max = number_format($threads * 100) . '%';
+
+ return 'CPU - ' . $cpu . '% Of ' . $max;
+ }
+}
diff --git a/app/Filament/Resources/NodeResource/Widgets/NodeMemoryChart.php b/app/Filament/Resources/NodeResource/Widgets/NodeMemoryChart.php
index 8ed87046a..3d8762447 100644
--- a/app/Filament/Resources/NodeResource/Widgets/NodeMemoryChart.php
+++ b/app/Filament/Resources/NodeResource/Widgets/NodeMemoryChart.php
@@ -3,66 +3,83 @@
namespace App\Filament\Resources\NodeResource\Widgets;
use App\Models\Node;
+use Carbon\Carbon;
+use Filament\Support\RawJs;
use Filament\Widgets\ChartWidget;
use Illuminate\Database\Eloquent\Model;
class NodeMemoryChart extends ChartWidget
{
- protected static ?string $heading = 'Memory';
-
- protected static ?string $pollingInterval = '60s';
+ protected static ?string $pollingInterval = '5s';
+ protected static ?string $maxHeight = '300px';
public ?Model $record = null;
- protected static ?array $options = [
- 'scales' => [
- 'x' => [
- 'grid' => [
- 'display' => false,
- ],
- 'ticks' => [
- 'display' => false,
- ],
- ],
- 'y' => [
- 'grid' => [
- 'display' => false,
- ],
- 'ticks' => [
- 'display' => false,
- ],
- ],
- ],
- ];
-
protected function getData(): array
{
/** @var Node $node */
$node = $this->record;
- $total = ($node->statistics()['memory_total'] ?? 0) / 1024 / 1024 / 1024;
- $used = ($node->statistics()['memory_used'] ?? 0) / 1024 / 1024 / 1024;
- $unused = $total - $used;
+ $memUsed = collect(cache()->get("nodes.$node->id.memory_used"))->slice(-10)
+ ->map(fn ($value, $key) => [
+ 'memory' => config('panel.use_binary_prefix') ? $value / 1024 / 1024 / 1024 : $value / 1000 / 1000 / 1000,
+ 'timestamp' => Carbon::createFromTimestamp($key, (auth()->user()->timezone ?? 'UTC'))->format('H:i:s'),
+ ])
+ ->all();
return [
'datasets' => [
[
- 'label' => 'Data Cool',
- 'data' => [$used, $unused],
+ 'data' => array_column($memUsed, 'memory'),
'backgroundColor' => [
- 'rgb(255, 99, 132)',
- 'rgb(54, 162, 235)',
- 'rgb(255, 205, 86)',
+ 'rgba(96, 165, 250, 0.3)',
],
+ 'tension' => '0.3',
+ 'fill' => true,
],
- // 'backgroundColor' => [],
],
- 'labels' => ['Used', 'Unused'],
+ 'labels' => array_column($memUsed, 'timestamp'),
];
}
protected function getType(): string
{
- return 'pie';
+ return 'line';
+ }
+
+ protected function getOptions(): RawJs
+ {
+ return RawJs::make(<<<'JS'
+ {
+ scales: {
+ y: {
+ min: 0,
+ },
+ },
+ plugins: {
+ legend: {
+ display: false,
+ }
+ }
+ }
+ JS);
+ }
+
+ public function getHeading(): string
+ {
+ /** @var Node $node */
+ $node = $this->record;
+ $latestMemoryUsed = collect(cache()->get("nodes.$node->id.memory_used"))->last();
+ $totalMemory = collect(cache()->get("nodes.$node->id.memory_total"))->last();
+
+ $used = config('panel.use_binary_prefix')
+ ? number_format($latestMemoryUsed / 1024 / 1024 / 1024, 2) .' GiB'
+ : number_format($latestMemoryUsed / 1000 / 1000 / 1000, 2) . ' GB';
+
+ $total = config('panel.use_binary_prefix')
+ ? number_format($totalMemory / 1024 / 1024 / 1024, 2) .' GiB'
+ : number_format($totalMemory / 1000 / 1000 / 1000, 2) . ' GB';
+
+ return 'Memory - ' . $used . ' Of ' . $total;
}
}
diff --git a/app/Filament/Resources/NodeResource/Widgets/NodeStorageChart.php b/app/Filament/Resources/NodeResource/Widgets/NodeStorageChart.php
index bcfbfcf4f..b841d84ef 100644
--- a/app/Filament/Resources/NodeResource/Widgets/NodeStorageChart.php
+++ b/app/Filament/Resources/NodeResource/Widgets/NodeStorageChart.php
@@ -9,8 +9,8 @@ use Illuminate\Database\Eloquent\Model;
class NodeStorageChart extends ChartWidget
{
protected static ?string $heading = 'Storage';
-
protected static ?string $pollingInterval = '60s';
+ protected static ?string $maxHeight = '300px';
public ?Model $record = null;
@@ -47,7 +47,6 @@ class NodeStorageChart extends ChartWidget
return [
'datasets' => [
[
- 'label' => 'Data Cool',
'data' => [$used, $unused],
'backgroundColor' => [
'rgb(255, 99, 132)',
@@ -55,7 +54,6 @@ class NodeStorageChart extends ChartWidget
'rgb(255, 205, 86)',
],
],
- // 'backgroundColor' => [],
],
'labels' => ['Used', 'Unused'],
];
diff --git a/app/Jobs/NodeStatistics.php b/app/Jobs/NodeStatistics.php
new file mode 100644
index 000000000..19fae9b9d
--- /dev/null
+++ b/app/Jobs/NodeStatistics.php
@@ -0,0 +1,46 @@
+statistics();
+ $timestamp = now()->getTimestamp();
+
+ foreach ($stats as $key => $value) {
+ $cacheKey = "nodes.{$node->id}.$key";
+ $data = cache()->get($cacheKey, []);
+
+ // Add current timestamp and value to the data array
+ $data[$timestamp] = $value;
+
+ // Update the cache with the new data, expires in 1 minute
+ cache()->put($cacheKey, $data, now()->addMinute());
+ }
+ }
+ }
+
+}
diff --git a/resources/views/filament/components/node-cpu-chart.blade.php b/resources/views/filament/components/node-cpu-chart.blade.php
new file mode 100644
index 000000000..d2627c42d
--- /dev/null
+++ b/resources/views/filament/components/node-cpu-chart.blade.php
@@ -0,0 +1,3 @@
+
+ @livewire(\App\Filament\Resources\NodeResource\Widgets\NodeCpuChart::class, ['record'=> $getRecord()])
+
diff --git a/resources/views/filament/components/node-memory-chart.blade.php b/resources/views/filament/components/node-memory-chart.blade.php
new file mode 100644
index 000000000..cb934d007
--- /dev/null
+++ b/resources/views/filament/components/node-memory-chart.blade.php
@@ -0,0 +1,3 @@
+
+ @livewire(\App\Filament\Resources\NodeResource\Widgets\NodeMemoryChart::class, ['record'=> $getRecord()])
+
diff --git a/resources/views/filament/components/node-storage-chart.blade.php b/resources/views/filament/components/node-storage-chart.blade.php
new file mode 100644
index 000000000..ea7b5358c
--- /dev/null
+++ b/resources/views/filament/components/node-storage-chart.blade.php
@@ -0,0 +1,3 @@
+
+ @livewire(\App\Filament\Resources\NodeResource\Widgets\NodeStorageChart::class, ['record'=> $getRecord()])
+