From b484c0cc253ff9845fda130671004f5451fea84f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 29 Dec 2025 17:52:35 +0000 Subject: [PATCH 1/2] fix(logs): Remove hardcoded 2000 line display limit The log viewer was artificially limiting display to 2000 lines regardless of user's requested amount. Users could request 10k, 40k, or 50k lines but only 2000 were ever shown. Changes: - Remove the hardcoded $maxDisplayLines = 2000 limit in the view - Add MAX_LOG_LINES constant (50,000) in GetLogs component - Enforce maximum limit in backend to prevent extremely large requests - Update input field with max attribute and tooltip Fixes #7803 --- app/Livewire/Project/Shared/GetLogs.php | 5 +++++ .../livewire/project/shared/get-logs.blade.php | 16 +++------------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/app/Livewire/Project/Shared/GetLogs.php b/app/Livewire/Project/Shared/GetLogs.php index 8fda35a4a..0f8c4ad15 100644 --- a/app/Livewire/Project/Shared/GetLogs.php +++ b/app/Livewire/Project/Shared/GetLogs.php @@ -21,6 +21,8 @@ class GetLogs extends Component { + public const MAX_LOG_LINES = 50000; + public string $outputs = ''; public string $errors = ''; @@ -123,6 +125,9 @@ public function getLogs($refresh = false) if ($this->numberOfLines <= 0 || is_null($this->numberOfLines)) { $this->numberOfLines = 1000; } + if ($this->numberOfLines > self::MAX_LOG_LINES) { + $this->numberOfLines = self::MAX_LOG_LINES; + } if ($this->container) { if ($this->showTimeStamps) { if ($this->server->isSwarm()) { diff --git a/resources/views/livewire/project/shared/get-logs.blade.php b/resources/views/livewire/project/shared/get-logs.blade.php index 03c049874..8deee486d 100644 --- a/resources/views/livewire/project/shared/get-logs.blade.php +++ b/resources/views/livewire/project/shared/get-logs.blade.php @@ -251,8 +251,8 @@ class="flex items-center justify-between gap-2 px-4 py-2 border-b dark:border-co
Lines: -
@if ($outputs) @php - // Limit rendered lines to prevent memory exhaustion - $maxDisplayLines = 2000; - $allLines = collect(explode("\n", $outputs))->filter(fn($line) => trim($line) !== ''); - $totalLines = $allLines->count(); - $hasMoreLines = $totalLines > $maxDisplayLines; - $displayLines = $hasMoreLines ? $allLines->slice(-$maxDisplayLines)->values() : $allLines; + $displayLines = collect(explode("\n", $outputs))->filter(fn($line) => trim($line) !== ''); @endphp
- @if ($hasMoreLines) -
- Showing last {{ number_format($maxDisplayLines) }} of {{ number_format($totalLines) }} lines -
- @endif
No matches found. From bbb2aa9ad4e0c14517d32272b5e6d83318fde493 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 29 Dec 2025 17:59:23 +0000 Subject: [PATCH 2/2] feat(logs): Add dropdown to download displayed or all logs Users can now choose between downloading only the currently displayed logs or fetching and downloading all available logs from the container. Changes: - Add downloadAllLogs() method that fetches all logs without limit - Replace download button with dropdown menu - Options: "Download displayed logs" and "Download all logs" Addresses #7803 --- app/Livewire/Project/Shared/GetLogs.php | 44 ++++++++++++++++ .../project/shared/get-logs.blade.php | 51 ++++++++++++++++--- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/app/Livewire/Project/Shared/GetLogs.php b/app/Livewire/Project/Shared/GetLogs.php index 0f8c4ad15..5f8046efd 100644 --- a/app/Livewire/Project/Shared/GetLogs.php +++ b/app/Livewire/Project/Shared/GetLogs.php @@ -188,6 +188,50 @@ public function copyLogs(): string return sanitizeLogsForExport($this->outputs); } + public function downloadAllLogs(): string + { + if (! $this->server->isFunctional() || ! $this->container) { + return ''; + } + + if ($this->showTimeStamps) { + if ($this->server->isSwarm()) { + $command = "docker service logs -t {$this->container}"; + } else { + $command = "docker logs -t {$this->container}"; + } + } else { + if ($this->server->isSwarm()) { + $command = "docker service logs {$this->container}"; + } else { + $command = "docker logs {$this->container}"; + } + } + + if ($this->server->isNonRoot()) { + $command = parseCommandsByLineForSudo(collect($command), $this->server); + $command = $command[0]; + } + + $sshCommand = SshMultiplexingHelper::generateSshCommand($this->server, $command); + + $allLogs = ''; + Process::run($sshCommand, function (string $type, string $output) use (&$allLogs) { + $allLogs .= removeAnsiColors($output); + }); + + if ($this->showTimeStamps) { + $allLogs = str($allLogs)->split('/\n/')->sort(function ($a, $b) { + $a = explode(' ', $a); + $b = explode(' ', $b); + + return $a[0] <=> $b[0]; + })->join("\n"); + } + + return sanitizeLogsForExport($allLogs); + } + public function render() { return view('livewire.project.shared.get-logs'); diff --git a/resources/views/livewire/project/shared/get-logs.blade.php b/resources/views/livewire/project/shared/get-logs.blade.php index 8deee486d..2d964f0bb 100644 --- a/resources/views/livewire/project/shared/get-logs.blade.php +++ b/resources/views/livewire/project/shared/get-logs.blade.php @@ -316,14 +316,49 @@ class="p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text- d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" /> - +
+ +
+
+ + +
+
+