Created
April 3, 2025 00:11
-
-
Save diogogpinto/d70a795e0e1ba705d82102cefb6331f1 to your computer and use it in GitHub Desktop.
Show CPU Load chart with Filament
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Filament\Widgets; | |
use Carbon\Carbon; | |
use Filament\Widgets\ChartWidget; | |
use Spatie\Health\Models\HealthCheckResultHistoryItem; | |
class CpuLoadChart extends ChartWidget | |
{ | |
protected static ?string $heading = 'Server Load History'; | |
protected static ?string $maxHeight = '250px'; | |
protected static ?string $pollingInterval = '30s'; | |
protected static string $color = 'info'; | |
protected function getData(): array | |
{ | |
// Get data from the health check results table | |
// Moved from custom to Spatie, Spatie does it better | |
$cpuLoadResults = HealthCheckResultHistoryItem::where('check_name', 'CPU Load') | |
->orderBy('created_at', 'desc') | |
->limit(20) | |
->get(); | |
$history = []; | |
foreach ($cpuLoadResults as $result) { | |
// I suck at regex, a LLM did this because the notification is stored as a long string | |
preg_match('/CPU Load: ([\d.]+)%/', $result->notification_message, $matches); | |
if (! empty($matches)) { | |
$loadPercentage = (float) $matches[1]; | |
$time = Carbon::parse($result->created_at)->format('H:i:s'); | |
// Need to reverse later | |
$history[] = [ | |
'time' => $time, | |
'load' => $loadPercentage, | |
]; | |
} | |
} | |
$history = array_reverse($history); | |
$labels = []; | |
$data = []; | |
foreach ($history as $item) { | |
$labels[] = $item['time']; | |
$data[] = $item['load']; | |
} | |
// If we have no data, add a placeholder | |
if (empty($data)) { | |
$labels = [Carbon::now()->format('H:i:s')]; | |
$data = [0]; | |
} | |
return [ | |
'datasets' => [ | |
[ | |
'label' => 'Server Load (%)', | |
'data' => $data, | |
'borderColor' => 'rgb(22, 184, 167)', | |
'backgroundColor' => 'rgba(22, 184, 167, 0.1)', | |
'borderWidth' => 2, | |
'tension' => 0.3, | |
'fill' => true, | |
'pointRadius' => 3, | |
'pointBackgroundColor' => 'rgb(59, 130, 246)', | |
'pointBorderColor' => '#fff', | |
'pointBorderWidth' => 1, | |
], | |
], | |
'labels' => $labels, | |
]; | |
} | |
protected function getOptions(): array | |
{ | |
return [ | |
'scales' => [ | |
'y' => [ | |
'min' => 0, | |
'max' => 400, | |
'ticks' => [ | |
'stepSize' => 20, | |
], | |
'title' => [ | |
'display' => true, | |
'text' => 'Load (%)', | |
], | |
'grid' => [ | |
'color' => 'rgba(0, 0, 0, 0.05)', | |
], | |
], | |
'x' => [ | |
'title' => [ | |
'display' => true, | |
'text' => 'Time', | |
], | |
'grid' => [ | |
'display' => false, | |
], | |
], | |
], | |
'plugins' => [ | |
'legend' => [ | |
'display' => false, | |
], | |
'tooltip' => [ | |
'mode' => 'index', | |
'intersect' => false, | |
'backgroundColor' => 'rgba(0, 0, 0, 0.7)', | |
], | |
], | |
'animation' => [ | |
'duration' => 0, | |
], | |
'responsive' => true, | |
'maintainAspectRatio' => false, | |
'interaction' => [ | |
'mode' => 'index', | |
'intersect' => false, | |
], | |
'elements' => [ | |
'line' => [ | |
'tension' => 0.3, | |
], | |
], | |
]; | |
} | |
public function getType(): string | |
{ | |
return 'line'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment