From e128b45caa577cdc6045fd6b410ce74d79ecebfd Mon Sep 17 00:00:00 2001 From: tristan Date: Tue, 7 Apr 2026 12:16:45 +0200 Subject: [PATCH] fix : affichage log docker et symfony --- frontend/i18n/locales/fr.json | 1 + frontend/pages/applications/[slug].vue | 2 +- src/Service/LogService.php | 80 +++++++++++++++++++++++--- src/State/SymfonyLogProvider.php | 1 + 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/frontend/i18n/locales/fr.json b/frontend/i18n/locales/fr.json index 82b9d14..88aa979 100644 --- a/frontend/i18n/locales/fr.json +++ b/frontend/i18n/locales/fr.json @@ -119,6 +119,7 @@ "deployScriptPath": "Chemin du script de deploiement", "maintenanceFilePath": "Chemin du fichier de maintenance", "pathHint": "Prefixe automatique : /mnt/apps", + "pathHintLog": "Chemin dans le container, ex : var/log/prod.log", "appUrl": "URL de l'application", "save": "Enregistrer", "cancel": "Annuler" diff --git a/frontend/pages/applications/[slug].vue b/frontend/pages/applications/[slug].vue index 1fa3499..a241b0e 100644 --- a/frontend/pages/applications/[slug].vue +++ b/frontend/pages/applications/[slug].vue @@ -579,7 +579,7 @@ onMounted(loadApplication)
- +
setTimeout(10); $process->run(); - return $process->getOutput() . $process->getErrorOutput(); + $output = $process->getOutput() . $process->getErrorOutput(); + + return $this->formatDockerOutput($output); } - public function getSymfonyLog(string $relativePath, int $lines = 100, ?string $level = null): string + private function formatDockerOutput(string $output): string { - $path = $this->pathResolver->resolve($relativePath); + $rawLines = explode("\n", trim($output)); + $formatted = []; - if (!file_exists($path)) { - return sprintf('Log file not found: %s', $path); + foreach ($rawLines as $line) { + if ('' === $line) { + continue; + } + + // Try parsing as Symfony monolog JSON format + $parsed = $this->parseSymfonyLogLine($line); + + if (null !== $parsed) { + if ('doctrine' === $parsed['channel']) { + continue; + } + $formatted[] = sprintf('[%s] %s.%s: %s', $parsed['date'], $parsed['channel'], $parsed['level'], $parsed['message']); + continue; + } + + // Try parsing as JSON log ({"message":"...","level":...}) + $json = json_decode($line, true); + if (\is_array($json) && isset($json['message'])) { + $date = isset($json['datetime']) ? substr($json['datetime'], 0, 19) : ''; + $date = str_replace('T', ' ', $date); + $channel = $json['channel'] ?? 'app'; + $level = $json['level_name'] ?? 'INFO'; + + if ('doctrine' === $channel) { + continue; + } + + $formatted[] = sprintf('[%s] %s.%s: %s', $date, $channel, $level, $json['message']); + continue; + } + + // Keep raw lines that don't match any format (nginx access logs, etc.) + $formatted[] = $line; + } + + return implode("\n", $formatted); + } + + public function getSymfonyLog(string $containerName, string $logPath, int $lines = 100, ?string $level = null): string + { + $check = new Process(['which', 'docker']); + $check->setTimeout(5); + $check->run(); + + if (!$check->isSuccessful()) { + // Fallback: try reading from filesystem (dev mode) + $localPath = $this->pathResolver->resolve($logPath); + if (!file_exists($localPath)) { + return sprintf('Log file not found: %s (Docker CLI unavailable, local path: %s)', $logPath, $localPath); + } + $readLines = (null !== $level && '' !== $level) ? $lines * 5 : $lines; + $process = new Process(['tail', '-n', (string) $readLines, $localPath]); + $process->setTimeout(10); + $process->run(); + return $this->formatSymfonyOutput($process->getOutput(), $lines, $level); } // Read more lines than requested to compensate for filtering $readLines = (null !== $level && '' !== $level) ? $lines * 5 : $lines; - $process = new Process(['tail', '-n', (string) $readLines, $path]); + $process = new Process(['docker', 'exec', $containerName, 'tail', '-n', (string) $readLines, $logPath]); $process->setTimeout(10); $process->run(); - $rawLines = explode("\n", trim($process->getOutput())); + if (!$process->isSuccessful()) { + return sprintf('Error reading log: %s', trim($process->getErrorOutput())); + } + + return $this->formatSymfonyOutput($process->getOutput(), $lines, $level); + } + + private function formatSymfonyOutput(string $output, int $lines, ?string $level): string + { + $rawLines = explode("\n", trim($output)); $formatted = []; foreach ($rawLines as $line) { diff --git a/src/State/SymfonyLogProvider.php b/src/State/SymfonyLogProvider.php index 27f903e..4754547 100644 --- a/src/State/SymfonyLogProvider.php +++ b/src/State/SymfonyLogProvider.php @@ -42,6 +42,7 @@ final readonly class SymfonyLogProvider implements ProviderInterface $level = $request?->query->get('level'); $content = $this->logService->getSymfonyLog( + $environment->getContainerName(), $logFile->getPath(), $lines, $level,