diff --git a/TODO.md b/TODO.md index 3e2a15c..9f22083 100644 --- a/TODO.md +++ b/TODO.md @@ -51,3 +51,5 @@ - [x] Fix repertoire Années column: sort reverse chronological (newest first) instead of ascending alpha - [x] TFE website embed: wrap iframe + button in overlay-style div with "Site web" pill badge on left corner, clearer link text - [x] Redirect internal metadata links on TFE page from /repertoire to /search (orientation, AP, finalité, year, keywords); add query= for search bar prefill; fix filter
visibility on desktop; add keyword to filterKeys badge; add hidden keyword input + visible chip to filter form so keyword filter survives form submission +- [x] Fix Logger default level: production default was WARNING, but all facades (AppLogger, AdminLogger, Audit) write at INFO — causing submission/admin/audit logs to be silently discarded +- [x] Add structured logging to PeerTube upload/delete: replace raw error_log() with Logger::get('app')->info() for successes and ErrorHandler::log() for failures in PeerTubeService, FilepondHandler, ThesisCreateController, ThesisFileHandler diff --git a/app/src/Controllers/ThesisCreateController.php b/app/src/Controllers/ThesisCreateController.php index c7add75..fac0aa6 100644 --- a/app/src/Controllers/ThesisCreateController.php +++ b/app/src/Controllers/ThesisCreateController.php @@ -677,9 +677,21 @@ class ThesisCreateController null, null ); - error_log('ThesisCreateController: PeerTube upload OK → ' . $result['watchUrl']); + Logger::get('app')->info(json_encode([ + 'timestamp' => date('c'), + 'source' => 'thesis_create', + 'action' => 'peertube_attach', + 'status' => 'success', + 'thesis_id' => $thesisId, + 'file_type' => $fileType, + 'uuid' => $result['uuid'], + 'watch_url' => $result['watchUrl'], + ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); } catch (\Throwable $e) { - error_log('ThesisCreateController: PeerTube upload failed — ' . $e->getMessage()); + ErrorHandler::log('thesis_create_peertube', $e, [ + 'thesis_id' => $thesisId, + 'file_type' => $fileType, + ]); // Non-fatal: thesis already saved; admin can re-upload manually. } } diff --git a/app/src/Controllers/ThesisFileHandler.php b/app/src/Controllers/ThesisFileHandler.php index 7455298..3ce6bd3 100644 --- a/app/src/Controllers/ThesisFileHandler.php +++ b/app/src/Controllers/ThesisFileHandler.php @@ -1050,7 +1050,15 @@ trait ThesisFileHandler null, null ); - error_log("ThesisFileHandler: PeerTube file associated → $uuid"); + Logger::get('app')->info(json_encode([ + 'timestamp' => date('c'), + 'source' => 'filepond', + 'action' => 'peertube_associate', + 'status' => 'success', + 'uuid' => $uuid, + 'file_type' => $fileType, + 'thesis_id' => $thesisId, + ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); continue; } diff --git a/app/src/FilepondHandler.php b/app/src/FilepondHandler.php index 86ede63..2f11d2b 100644 --- a/app/src/FilepondHandler.php +++ b/app/src/FilepondHandler.php @@ -168,14 +168,26 @@ class FilepondHandler $fileId = 'peertube:' . $ptFileType . ':' . $result['uuid']; @unlink($targetPath); @rmdir($tmpDir); - error_log($this->logPrefix . ':process PeerTube upload OK | uuid=' . $result['uuid'] . ' | url=' . $result['watchUrl']); + Logger::get('app')->info(json_encode([ + 'timestamp' => date('c'), + 'source' => 'filepond', + 'action' => 'peertube_upload', + 'status' => 'success', + 'uuid' => $result['uuid'], + 'queue_type' => $queueType, + 'mime' => $mimeType, + 'instance' => PeerTubeService::getSettings(new Database())['instance_url'], + ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); header('Content-Type: text/plain; charset=utf-8'); echo $fileId; exit; } catch (\Throwable $e) { @unlink($targetPath); @rmdir($tmpDir); - error_log($this->logPrefix . ':process PeerTube upload FAILED: ' . $e->getMessage()); + ErrorHandler::log('filepond_peertube', $e, [ + 'queue_type' => $queueType, + 'mime' => $mimeType, + ]); http_response_code(500); die('Erreur lors du téléversement vers PeerTube.'); } diff --git a/app/src/Logger.php b/app/src/Logger.php index e0287cd..32cc0b3 100644 --- a/app/src/Logger.php +++ b/app/src/Logger.php @@ -79,14 +79,19 @@ class Logger /** * Read the LOG_LEVEL env var with sensible defaults. + * + * All facades (AppLogger, AdminLogger, Audit) write at INFO level, + * so the production default must be at least INFO — otherwise + * submission logs, admin action logs, and audit traces are silently + * discarded. */ private static function level(): Level { $level = strtoupper(getenv('LOG_LEVEL') ?: ''); - // Default: WARNING in production (always set in .env), DEBUG otherwise + // Default: INFO in production, DEBUG in dev (cli-server) if ($level === '') { - return php_sapi_name() === 'cli-server' ? Level::Debug : Level::Warning; + return php_sapi_name() === 'cli-server' ? Level::Debug : Level::Info; } return Level::fromName($level); diff --git a/app/src/PeerTubeService.php b/app/src/PeerTubeService.php index 9d1e03e..af6ce1d 100644 --- a/app/src/PeerTubeService.php +++ b/app/src/PeerTubeService.php @@ -1,5 +1,8 @@ = 300) { $errJson = json_decode($resp['body'], true); $msg = $errJson['error'] ?? $errJson['detail'] ?? $resp['body']; - error_log('PeerTubeService: simple upload FAILED | status=' . $resp['status'] . ' | body=' . substr($resp['body'], 0, 500)); - throw new \RuntimeException('PeerTube upload failed (' . $resp['status'] . '): ' . $msg); + $ex = new \RuntimeException('PeerTube upload failed (' . $resp['status'] . '): ' . $msg); + ErrorHandler::log('peertube_upload', $ex, [ + 'status' => $resp['status'], + 'title' => $title, + 'instance' => $s['instance_url'], + 'channel' => $s['channel_name'], + ]); + throw $ex; } $json = json_decode($resp['body'], true); $shortUuid = $json['video']['shortUUID'] ?? $json['video']['uuid'] ?? null; if ($shortUuid === null) { - error_log('PeerTubeService: simple upload OK but no UUID | body=' . substr($resp['body'], 0, 500)); - throw new \RuntimeException('PeerTube upload: no video UUID in response.'); + $ex = new \RuntimeException('PeerTube upload: no video UUID in response.'); + ErrorHandler::log('peertube_upload', $ex, [ + 'body_sample' => substr($resp['body'], 0, 500), + 'instance' => $s['instance_url'], + ]); + throw $ex; } $watchUrl = rtrim($baseUrl, '/') . '/videos/watch/' . $shortUuid; - error_log('PeerTubeService: simple upload OK | uuid=' . $shortUuid . ' | watchUrl=' . $watchUrl); + Logger::get('app')->info(json_encode([ + 'timestamp' => date('c'), + 'source' => 'peertube', + 'action' => 'upload', + 'status' => 'success', + 'uuid' => $shortUuid, + 'watch_url' => $watchUrl, + 'title' => $title, + 'instance' => $s['instance_url'], + 'channel' => $s['channel_name'], + ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); return ['uuid' => $shortUuid, 'watchUrl' => $watchUrl]; } @@ -348,7 +371,9 @@ class PeerTubeService { $s = self::getSettings($db); if ($s['instance_url'] === '') { - error_log('PeerTubeService::deleteVideo: instance not configured'); + ErrorHandler::log('peertube_delete', new \RuntimeException( + 'PeerTube instance not configured' + ), ['uuid' => $uuid]); return false; } try { @@ -359,13 +384,21 @@ class PeerTubeService 'timeout' => 30, ]); if ($resp['status'] === 204 || $resp['status'] === 200) { - error_log('PeerTubeService: deleted video ' . $uuid); + Logger::get('app')->info(json_encode([ + 'timestamp' => date('c'), + 'source' => 'peertube', + 'action' => 'delete', + 'status' => 'success', + 'uuid' => $uuid, + ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); return true; } - error_log('PeerTubeService::deleteVideo: unexpected status ' . $resp['status'] . ' for ' . $uuid . ' | body=' . substr($resp['body'], 0, 300)); + ErrorHandler::log('peertube_delete', new \RuntimeException( + 'PeerTube delete unexpected status ' . $resp['status'] . ' for ' . $uuid + ), ['status' => $resp['status'], 'uuid' => $uuid]); return false; } catch (\Throwable $e) { - error_log('PeerTubeService::deleteVideo failed: ' . $e->getMessage()); + ErrorHandler::log('peertube_delete', $e, ['uuid' => $uuid]); return false; } }