feat(logs): accept all for log lines and keep -1

API log endpoints and the GetLogs UI now treat `all` as unbounded
output, with `-1` remaining as a compatibility alias. MCP still
falls back to a positive default. Traefik version checks run from
CheckForUpdatesJob instead of a weekly schedule.
This commit is contained in:
Andras Bacsai
2026-09-13 15:25:20 +02:00
parent 6f58ad4b97
commit 7d11bc92f7
15 changed files with 186 additions and 39 deletions
-3
View File
@@ -6,7 +6,6 @@ use App\Jobs\ApiTokenExpirationWarningJob;
use App\Jobs\CheckForUpdatesJob;
use App\Jobs\CheckHelperImageJob;
use App\Jobs\CheckMissingDatabaseBackupsJob;
use App\Jobs\CheckTraefikVersionJob;
use App\Jobs\CleanupInstanceStuffsJob;
use App\Jobs\CleanupOrphanedPreviewContainersJob;
use App\Jobs\CleanupStaleMultiplexedConnections;
@@ -91,8 +90,6 @@ class Kernel extends ConsoleKernel
$this->scheduleInstance->job(new RegenerateSslCertJob)->twiceDaily()->onOneServer();
$this->scheduleInstance->job(new CheckTraefikVersionJob)->weekly()->sundays()->at('00:00')->timezone($this->instanceTimezone)->onOneServer();
$this->scheduleInstance->command('cleanup:database --yes')->daily();
$this->scheduleInstance->command('uploads:clear')->everyTwoMinutes();
@@ -2410,13 +2410,12 @@ class ApplicationsController extends Controller
new OA\Parameter(
name: 'lines',
in: 'query',
description: 'Number of lines to show from the end of the logs.',
description: 'Number of lines to show from the end of the logs. Use `all` to return all logs. `-1` remains available as a compatibility alias.',
required: false,
schema: new OA\Schema(
type: 'integer',
format: 'int32',
default: 100,
)
schema: new OA\Schema(oneOf: [
new OA\Schema(type: 'integer', format: 'int32', default: 100, minimum: -1, maximum: 10000),
new OA\Schema(type: 'string', enum: ['all']),
])
),
new OA\Parameter(
name: 'show_timestamps',
@@ -2433,13 +2433,12 @@ class DatabasesController extends Controller
new OA\Parameter(
name: 'lines',
in: 'query',
description: 'Number of lines to show from the end of the logs.',
description: 'Number of lines to show from the end of the logs. Use `all` to return all logs. `-1` remains available as a compatibility alias.',
required: false,
schema: new OA\Schema(
type: 'integer',
format: 'int32',
default: 100,
)
schema: new OA\Schema(oneOf: [
new OA\Schema(type: 'integer', format: 'int32', default: 100, minimum: -1, maximum: 10000),
new OA\Schema(type: 'string', enum: ['all']),
])
),
new OA\Parameter(
name: 'show_timestamps',
@@ -402,9 +402,12 @@ class ServiceApplicationsController extends Controller
new OA\Parameter(
name: 'lines',
in: 'query',
description: 'Number of lines to show from the end of the logs.',
description: 'Number of lines to show from the end of the logs. Use `all` to return all logs. `-1` remains available as a compatibility alias.',
required: false,
schema: new OA\Schema(type: 'integer', format: 'int32', default: 100)
schema: new OA\Schema(oneOf: [
new OA\Schema(type: 'integer', format: 'int32', default: 100, minimum: -1, maximum: 10000),
new OA\Schema(type: 'string', enum: ['all']),
])
),
],
responses: [
@@ -451,7 +454,16 @@ class ServiceApplicationsController extends Controller
parameters: [
new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
new OA\Parameter(name: 'app_uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
new OA\Parameter(name: 'lines', in: 'query', required: false, schema: new OA\Schema(type: 'integer', format: 'int32', default: 100)),
new OA\Parameter(
name: 'lines',
in: 'query',
description: 'Number of lines to show from the end of the logs. Use `all` to return all logs. `-1` remains available as a compatibility alias.',
required: false,
schema: new OA\Schema(oneOf: [
new OA\Schema(type: 'integer', format: 'int32', default: 100, minimum: -1, maximum: 10000),
new OA\Schema(type: 'string', enum: ['all']),
]),
),
],
responses: [
new OA\Response(
@@ -288,7 +288,16 @@ class ServiceDatabasesController extends Controller
parameters: [
new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
new OA\Parameter(name: 'database_uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
new OA\Parameter(name: 'lines', in: 'query', required: false, schema: new OA\Schema(type: 'integer', format: 'int32', default: 100)),
new OA\Parameter(
name: 'lines',
in: 'query',
description: 'Number of lines to show from the end of the logs. Use `all` to return all logs. `-1` remains available as a compatibility alias.',
required: false,
schema: new OA\Schema(oneOf: [
new OA\Schema(type: 'integer', format: 'int32', default: 100, minimum: -1, maximum: 10000),
new OA\Schema(type: 'string', enum: ['all']),
]),
),
],
responses: [
new OA\Response(response: 200, description: 'Logs.', content: new OA\JsonContent(type: 'object', properties: [new OA\Property(property: 'logs', type: 'string')])),
@@ -869,13 +869,12 @@ class ServicesController extends Controller
new OA\Parameter(
name: 'lines',
in: 'query',
description: 'Number of lines to show from the end of the logs.',
description: 'Number of lines to show from the end of the logs. Use `all` to return all logs. `-1` remains available as a compatibility alias.',
required: false,
schema: new OA\Schema(
type: 'integer',
format: 'int32',
default: 100,
)
schema: new OA\Schema(oneOf: [
new OA\Schema(type: 'integer', format: 'int32', default: 100, minimum: -1, maximum: 10000),
new OA\Schema(type: 'string', enum: ['all']),
])
),
new OA\Parameter(
name: 'show_timestamps',
+2
View File
@@ -73,6 +73,8 @@ class CheckForUpdatesJob implements ShouldBeEncrypted, ShouldQueue
// Invalidate cache to ensure fresh data is loaded
invalidate_versions_cache();
CheckTraefikVersionJob::dispatch();
// Only mark new version available if Coolify version actually increased
if (version_compare($latest_version, $current_version, '>')) {
// New version available
+15 -6
View File
@@ -131,6 +131,12 @@ class GetLogs extends Component
$this->streamLogs = ! $this->streamLogs;
}
public function showAllLogs(): void
{
$this->numberOfLines = -1;
$this->getLogs(true);
}
public function getLogs($refresh = false)
{
if (! Server::ownedByCurrentTeam()->where('id', $this->server->id)->exists()) {
@@ -149,22 +155,25 @@ class GetLogs extends Component
if (! $refresh && ! $this->expandByDefault && ($this->resource?->getMorphClass() === Service::class || str($this->container)->contains('-pr-'))) {
return;
}
if ($this->numberOfLines <= 0 || is_null($this->numberOfLines)) {
$logTail = $this->numberOfLines === -1 ? 'all' : $this->numberOfLines;
if ($logTail !== 'all' && ($logTail <= 0 || is_null($logTail))) {
$this->numberOfLines = 1000;
$logTail = $this->numberOfLines;
}
if ($this->numberOfLines > self::MAX_LOG_LINES) {
if ($logTail !== 'all' && $logTail > self::MAX_LOG_LINES) {
$this->numberOfLines = self::MAX_LOG_LINES;
$logTail = $this->numberOfLines;
}
if ($this->container) {
if ($this->showTimeStamps) {
if ($this->server->isSwarm()) {
$command = "docker service logs -n {$this->numberOfLines} -t {$this->container}";
$command = "docker service logs -n {$logTail} -t {$this->container}";
if ($this->server->isNonRoot()) {
$command = parseCommandsByLineForSudo(collect($command), $this->server);
$command = $command[0];
}
} else {
$command = "docker logs -n {$this->numberOfLines} -t {$this->container}";
$command = "docker logs -n {$logTail} -t {$this->container}";
if ($this->server->isNonRoot()) {
$command = parseCommandsByLineForSudo(collect($command), $this->server);
$command = $command[0];
@@ -172,13 +181,13 @@ class GetLogs extends Component
}
} else {
if ($this->server->isSwarm()) {
$command = "docker service logs -n {$this->numberOfLines} {$this->container}";
$command = "docker service logs -n {$logTail} {$this->container}";
if ($this->server->isNonRoot()) {
$command = parseCommandsByLineForSudo(collect($command), $this->server);
$command = $command[0];
}
} else {
$command = "docker logs -n {$this->numberOfLines} {$this->container}";
$command = "docker logs -n {$logTail} {$this->container}";
if ($this->server->isNonRoot()) {
$command = parseCommandsByLineForSudo(collect($command), $this->server);
$command = $command[0];
+3 -1
View File
@@ -98,6 +98,8 @@ trait ResolvesResource
*/
protected function normalizeMcpLogLines(mixed $lines): int
{
return normalizeLogLines($lines, default: 100, max: 500);
$lines = normalizeLogLines($lines, default: 100, max: 500);
return is_int($lines) && $lines > 0 ? $lines : 100;
}
}