diff --git a/app/Models/ServerProcess.php b/app/Models/ServerProcess.php index db5b545..a899812 100644 --- a/app/Models/ServerProcess.php +++ b/app/Models/ServerProcess.php @@ -8,6 +8,8 @@ use Illuminate\Database\Eloquent\Model; class ServerProcess extends Model { + protected static ?string $latestBatchIdCache = null; + protected $fillable = [ 'batch_id', 'rank', @@ -27,9 +29,11 @@ class ServerProcess extends Model public function scopeLatestBatch($query) { - $latestBatchId = static::orderBy('captured_at', 'desc')->value('batch_id'); + if (static::$latestBatchIdCache === null) { + static::$latestBatchIdCache = static::orderBy('captured_at', 'desc')->value('batch_id'); + } - return $query->where('batch_id', $latestBatchId); + return $query->where('batch_id', static::$latestBatchIdCache); } public static function captureProcesses(array $processes, int $total = 0): string @@ -44,11 +48,16 @@ class ServerProcess extends Model ->limit(10) ->pluck('batch_id'); - static::whereNotIn('batch_id', $keepBatches)->delete(); + if ($keepBatches->isNotEmpty()) { + static::whereNotIn('batch_id', $keepBatches)->delete(); + } + + static::$latestBatchIdCache = $batchId; // Insert new processes + $rows = []; foreach ($processes as $index => $proc) { - static::create([ + $rows[] = [ 'batch_id' => $batchId, 'rank' => $index + 1, 'pid' => $proc['pid'] ?? 0, @@ -57,7 +66,11 @@ class ServerProcess extends Model 'cpu' => $proc['cpu'] ?? 0, 'memory' => $proc['memory'] ?? 0, 'captured_at' => $now, - ]); + ]; + } + + if ($rows) { + static::insert($rows); } return $batchId; diff --git a/app/Services/SysstatMetrics.php b/app/Services/SysstatMetrics.php index cafa564..d17490b 100644 --- a/app/Services/SysstatMetrics.php +++ b/app/Services/SysstatMetrics.php @@ -95,6 +95,9 @@ class SysstatMetrics $samples = []; $current = $start->startOfDay(); $lastDay = $end->startOfDay(); + $startTimestamp = $start->getTimestamp(); + $endTimestamp = $end->getTimestamp(); + $useDailyCache = ($endTimestamp - $startTimestamp) > 21600; while ($current <= $lastDay) { $fileLong = sprintf('/var/log/sysstat/sa%s', $current->format('Ymd')); @@ -106,15 +109,22 @@ class SysstatMetrics continue; } - $dayStart = $current->isSameDay($start) ? $start : $current->startOfDay(); - $dayEnd = $current->isSameDay($end) ? $end : $current->endOfDay(); - $statistics = $this->readSadf($file, $dayStart, $dayEnd, $options); + if ($useDailyCache) { + $statistics = $this->readSadfDay($file, $current, $options); + } else { + $dayStart = $current->isSameDay($start) ? $start : $current->startOfDay(); + $dayEnd = $current->isSameDay($end) ? $end : $current->endOfDay(); + $statistics = $this->readSadf($file, $dayStart, $dayEnd, $options); + } foreach ($statistics as $stat) { $parsed = $this->parseSample($stat); if ($parsed === null) { continue; } + if ($parsed['timestamp'] < $startTimestamp || $parsed['timestamp'] > $endTimestamp) { + continue; + } $samples[] = $parsed; } @@ -148,6 +158,8 @@ class SysstatMetrics ], ); $process = new Process($args); + $process->setTimeout(8); + $process->setIdleTimeout(5); $process->run(); if (! $process->isSuccessful()) { @@ -167,6 +179,23 @@ class SysstatMetrics return $stats; } + /** + * @return array> + */ + private function readSadfDay(string $file, CarbonImmutable $day, array $options): array + { + $mtime = @filemtime($file) ?: 0; + $optionsKey = implode(',', $options); + $cacheKey = sprintf('sysstat.sadf.day.%s.%d.%s', md5($file), $mtime, md5($optionsKey)); + + return Cache::remember($cacheKey, now()->addMinutes(10), function () use ($file, $day, $options): array { + $dayStart = $day->startOfDay(); + $dayEnd = $day->endOfDay(); + + return $this->readSadf($file, $dayStart, $dayEnd, $options); + }); + } + /** * @return array */