mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-12 15:53:46 -04:00
feat(metrics): build and dispatch fleet trend chart payloads
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Concerns;
|
||||
|
||||
use App\Services\FleetMetricsAggregator;
|
||||
|
||||
trait BuildsMetricsChartPayload
|
||||
{
|
||||
/**
|
||||
* @param array{cpu: array, memory: array, disk: array, load: array, networkRx: array, networkTx: array} $seriesByServer
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function buildChartPayload(array $seriesByServer): array
|
||||
{
|
||||
return [
|
||||
'range' => $this->range,
|
||||
'cpu' => FleetMetricsAggregator::sumSeriesByBucket($seriesByServer['cpu'], 'avg'),
|
||||
'memory' => FleetMetricsAggregator::sumSeriesByBucket($seriesByServer['memory'], 'sum'),
|
||||
'disk' => FleetMetricsAggregator::sumSeriesByBucket($seriesByServer['disk'], 'avg'),
|
||||
'load' => FleetMetricsAggregator::sumSeriesByBucket($seriesByServer['load'], 'avg'),
|
||||
'networkRx' => FleetMetricsAggregator::sumSeriesByBucket($seriesByServer['networkRx'], 'sum'),
|
||||
'networkTx' => FleetMetricsAggregator::sumSeriesByBucket($seriesByServer['networkTx'], 'sum'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Livewire\Fleet;
|
||||
|
||||
use App\Livewire\Concerns\BuildsMetricsChartPayload;
|
||||
use App\Models\Application;
|
||||
use App\Models\Server;
|
||||
use App\Services\FleetMetricsAggregator;
|
||||
@@ -15,6 +16,8 @@ use Livewire\Component;
|
||||
#[Lazy]
|
||||
class Metrics extends Component
|
||||
{
|
||||
use BuildsMetricsChartPayload;
|
||||
|
||||
public string $chartId = 'fleet-metrics';
|
||||
|
||||
/** Metrics-enabled servers owned by the current team. */
|
||||
@@ -103,6 +106,8 @@ class Metrics extends Component
|
||||
|
||||
$rows = [];
|
||||
$containers = [];
|
||||
$series = ['cpu' => [], 'memory' => [], 'disk' => [], 'load' => [], 'networkRx' => [], 'networkTx' => []];
|
||||
$from = SentinelMetricsClient::rangeFrom($this->range);
|
||||
|
||||
foreach ($this->targetServers() as $server) {
|
||||
$client = $this->metricsClient($server);
|
||||
@@ -129,13 +134,21 @@ class Metrics extends Component
|
||||
$meta = $this->resolveContainer($server, $c['id']);
|
||||
$containers[] = array_merge($c, ['server' => $server->name, 'name' => $meta['name'], 'link' => $meta['link']]);
|
||||
}
|
||||
|
||||
$series['cpu'][] = $client->history('cpu', $from);
|
||||
$series['memory'][] = $client->history('memory', $from);
|
||||
$series['disk'][] = $client->history('disk', $from);
|
||||
$series['load'][] = $client->history('load', $from);
|
||||
$net = $client->networkHistory($from);
|
||||
$series['networkRx'][] = $net['rx'];
|
||||
$series['networkTx'][] = $net['tx'];
|
||||
}
|
||||
|
||||
$this->serverRows = $rows;
|
||||
$this->kpis = FleetMetricsAggregator::fleetKpis($rows);
|
||||
$this->topContainers = FleetMetricsAggregator::rankContainers($containers, $this->containerMetric);
|
||||
|
||||
$this->dispatch("refreshChartData-{$this->chartId}", $this->chartPayload());
|
||||
$this->dispatch("refreshChartData-{$this->chartId}", $this->buildChartPayload($series));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,14 +199,6 @@ class Metrics extends Component
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function chartPayload(): array
|
||||
{
|
||||
return ['range' => $this->range];
|
||||
}
|
||||
|
||||
public function placeholder(): View
|
||||
{
|
||||
return view('livewire.fleet.metrics-placeholder');
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
use App\Livewire\Fleet\Metrics;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\PrivateKey;
|
||||
use App\Models\Server;
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use App\Services\SentinelMetricsClient;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Livewire\Livewire;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
class ChartStubClient extends SentinelMetricsClient
|
||||
{
|
||||
public function summary(): ?array
|
||||
{
|
||||
return ['online' => true, 'cpu' => 10.0, 'memUsed' => 1, 'memTotal' => 2,
|
||||
'diskUsed' => 1, 'diskTotal' => 2, 'diskPercent' => 50.0, 'load1' => 0.1, 'netRx' => 0.0, 'netTx' => 0.0];
|
||||
}
|
||||
|
||||
public function containersCurrent(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function history(string $metric, string $from): array
|
||||
{
|
||||
return [[1000, 10.0], [2000, 20.0]];
|
||||
}
|
||||
|
||||
public function networkHistory(string $from): array
|
||||
{
|
||||
return ['rx' => [[1000, 5.0]], 'tx' => [[1000, 1.0]]];
|
||||
}
|
||||
}
|
||||
|
||||
class ChartTestableMetrics extends Metrics
|
||||
{
|
||||
protected function metricsClient(Server $server): SentinelMetricsClient
|
||||
{
|
||||
return new ChartStubClient($server);
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
InstanceSettings::unguarded(fn () => InstanceSettings::query()->create(['id' => 0]));
|
||||
$user = User::factory()->create();
|
||||
$team = Team::factory()->create();
|
||||
$user->teams()->attach($team, ['role' => 'owner']);
|
||||
$this->actingAs($user);
|
||||
session(['currentTeam' => $team]);
|
||||
$this->privateKey = PrivateKey::factory()->create(['team_id' => $team->id]);
|
||||
$this->team = $team;
|
||||
});
|
||||
|
||||
it('dispatches a chart payload with every trend series', function () {
|
||||
$s = Server::factory()->create(['team_id' => $this->team->id, 'private_key_id' => $this->privateKey->id]);
|
||||
$s->settings->update(['is_metrics_enabled' => true]);
|
||||
|
||||
Livewire::test(ChartTestableMetrics::class)
|
||||
->call('loadData')
|
||||
->assertDispatched('refreshChartData-fleet-metrics', function ($event, $params) {
|
||||
$payload = $params[0];
|
||||
|
||||
// Livewire JSON-serializes event params, so whole floats arrive as ints;
|
||||
// compare loosely (10 == 10.0).
|
||||
return $payload['cpu'] == [[1000, 10], [2000, 20]]
|
||||
&& $payload['networkRx'] == [[1000, 5]]
|
||||
&& array_key_exists('load', $payload);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user