From 8feea445d30178c155d0a492d1f6baf20e2e15d4 Mon Sep 17 00:00:00 2001 From: Matthieu Marcillaud <marcimat@rezo.net> Date: Sat, 6 Jan 2024 17:19:03 +0100 Subject: [PATCH] feat: Utiliser spip/logger (Monolog) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduction de `spip_logger()` qui retourne un logger compatible Psr\Log\LoggerInterface. Le logger utilise en interne Monolog (mais écrit à peu près comme faisait SPIP) Ce logger écrit par défaut comme avant dans le fichier `spip.log` On peut indiquer un autre canal de log (ie: fichier de log ici): `spip_logger('autoriser')` Dans ce cas là , ça loge comme avant dans `autoriser.log` et dans `spip.log` Exemple: `spip_logger('autoriser')->notice('Un log d’une certaine importance');` La fonction `spip_log()` est dépréciée, au profit de `spip_logger()`. --- ecrire/bootstrap/inc/logging.php | 198 +++++++++++++++++++++++-------- ecrire/src/ErrorHandler.php | 2 +- 2 files changed, 149 insertions(+), 51 deletions(-) diff --git a/ecrire/bootstrap/inc/logging.php b/ecrire/bootstrap/inc/logging.php index a66001cfbc..93ebeaf87f 100644 --- a/ecrire/bootstrap/inc/logging.php +++ b/ecrire/bootstrap/inc/logging.php @@ -1,25 +1,100 @@ <?php +use Monolog\Level; +use Psr\Log\LoggerInterface; +use Spip\Component\Filesystem\Filesystem; +use Spip\Component\Logger\Config; +use Spip\Component\Logger\Factory; +use Spip\Component\Logger\LineFormatter; + /** - * Enregistrement des événements + * Obtenir un logger compatible Psr\Log * - * Signature : `spip_log(message[,niveau|type|type.niveau])` + * @api + * @example + * ``` + * spip_logger()->notice('mon message'); * - * Le niveau de log par défaut est la valeur de la constante `_LOG_INFO` + * $logger = spip_logger(); + * $logger->info('mon message'); + * $logger->debug('mon debug'); * - * Les différents niveaux possibles sont : + * $logger = spip_logger('mysql'); + * $logger->info('mon message sur le canal mysql'); + * $logger->debug('mon debug sur le canal mysql'); + * ``` + */ +function spip_logger(?string $name = null): LoggerInterface { + /* @var array<string,LoggerInterface> */ + static $loggers = []; + /* @var ?Factory */ + static $loggerFactory = null; + + $name ??= 'spip'; + + if ($loggerFactory === null) { + $spipToMonologLevels = [ + Level::Emergency, // _LOG_HS + Level::Alert, // _LOG_ALERTE_ROUGE + Level::Critical, // _LOG_CRITIQUE + Level::Error, // _LOG_ERREUR + Level::Warning, // _LOG_AVERTISSEMENT + Level::Notice, // _LOG_INFO_IMPORTANTE + Level::Info, // _LOG_INFO + Level::Debug, // _LOG_DEBUG + ]; + + $config = [ + 'siteDir' => _ROOT_RACINE, + 'filesystem' => new Filesystem(), + // max log par hit + 'max_log' => defined('_MAX_LOG') ? constant('_MAX_LOG') : null, + // pour indiquer le chemin du fichier qui envoie le log + 'fileline' => defined('_LOG_FILELINE') ? constant('_LOG_FILELINE') : null, + // échappement des log + 'brut' => defined('_LOG_BRUT') ? constant('_LOG_BRUT') : null, + // à quel level on commence à logguer + 'max_level' => defined('_LOG_FILTRE_GRAVITE') ? $spipToMonologLevels[constant('_LOG_FILTRE_GRAVITE')] ?? Level::Info : Level::Info, + // rotation: nombre de fichiers + 'max_files' => $GLOBALS['nombre_de_logs'] ??= 4, + // rotation: taille max d’un fichier + 'max_size' => ($GLOBALS['taille_des_logs'] ??= 100) * 1024, + // chemin du fichier de log + 'log_path' => (function() { + $log_dir = defined('_DIR_LOG') ? str_replace(_DIR_RACINE, '', constant('_DIR_LOG')) : 'tmp/log/'; + $log_file = defined('_FILE_LOG') ? constant('_FILE_LOG') : 'spip'; + $log_suffix = defined('_FILE_LOG_SUFFIX') ? constant('_FILE_LOG_SUFFIX') : '.log'; + + $log_file = str_replace('spip', '%s', $log_file); + return sprintf('%s%s%s', $log_dir, $log_file, $log_suffix); + })(), + ]; + $env = getenv('APP_ENV') ?? 'prod'; + if ($env === 'dev') { + $config = [ + ...$config, + 'fileline' => true, + 'max_level' => Level::Debug, + ]; + } + $config = array_filter($config); + + $loggerFactory = new Factory(new Config(...$config), new LineFormatter()); + unset($args, $env, $spipToMonologLevels); + } + + return $loggers[$name] ??= $loggerFactory->createFromFilename($name); +} + + +/** + * Enregistrement des événements * - * - `_LOG_HS` : écrira 'HS' au début de la ligne logguée - * - `_LOG_ALERTE_ROUGE` : 'ALERTE' - * - `_LOG_CRITIQUE` : 'CRITIQUE' - * - `_LOG_ERREUR` : 'ERREUR' - * - `_LOG_AVERTISSEMENT` : 'WARNING' - * - `_LOG_INFO_IMPORTANTE` : '!INFO' - * - `_LOG_INFO` : 'info' - * - `_LOG_DEBUG` : 'debug' + * Signature : `spip_log(message, ?name)` * * @example * ``` + * # Les appels ci-dessous sont "deprecated" depuis 5.0 * spip_log($message) * spip_log($message, 'recherche') * spip_log($message, _LOG_DEBUG) @@ -28,50 +103,73 @@ * * @api * @link https://programmer.spip.net/spip_log - * @uses inc_log_dist() + * @see spip_logger() + * @deprecated 5.0 Utiliser spip_logger() * - * @param string $message - * Message à loger - * @param string|int $name - * - * - int indique le niveau de log, tel que `_LOG_DEBUG` - * - string indique le type de log - * - `string.int` indique les 2 éléments. - * Cette dernière notation est controversée mais le 3ème - * paramètre est planté pour cause de compatibilité ascendante. + * @param mixed $message Message à consigner + * @param int|string|null $name Nom du fichier de log, "spip" par défaut */ -function spip_log($message = null, $name = null) { - static $pre = []; - static $log; - preg_match('/^([a-z_]*)\.?(\d)?$/iS', (string)$name, $regs); - if (!isset($regs[1]) || !$logname = $regs[1]) { - $logname = null; - } +function spip_log($message, $name = null): void +{ + static $spipToMonologLevels = [ + Level::Emergency, // _LOG_HS + Level::Alert, // _LOG_ALERTE_ROUGE + Level::Critical, // _LOG_CRITIQUE + Level::Error, // _LOG_ERREUR + Level::Warning, // _LOG_AVERTISSEMENT + Level::Notice, // _LOG_INFO_IMPORTANTE + Level::Info, // _LOG_INFO + Level::Debug, // _LOG_DEBUG + ]; + + # Éviter de trop polluer les logs de dépréciation + static $deprecated = []; + + preg_match('/^([a-z_]*)\.?(\d)?$/iS', (string) $name, $regs); + $logFile = 'spip'; + if (isset($regs[1]) && strlen($regs[1])) { + $logFile = $regs[1]; + } + if (!isset($regs[2])) { - $niveau = _LOG_INFO; - } - else { - $niveau = intval($regs[2]); + $level = Level::Info; + } else { + $level = $spipToMonologLevels[intval($regs[2])] ?? Level::Info; } - if ($niveau <= (defined('_LOG_FILTRE_GRAVITE') ? _LOG_FILTRE_GRAVITE : _LOG_INFO_IMPORTANTE)) { - if (!$pre) { - $pre = [ - _LOG_HS => 'HS:', - _LOG_ALERTE_ROUGE => 'ALERTE:', - _LOG_CRITIQUE => 'CRITIQUE:', - _LOG_ERREUR => 'ERREUR:', - _LOG_AVERTISSEMENT => 'WARNING:', - _LOG_INFO_IMPORTANTE => '!INFO:', - _LOG_INFO => 'info:', - _LOG_DEBUG => 'debug:' - ]; - $log = charger_fonction('log', 'inc'); - } - if (!is_string($message)) { - $message = print_r($message, true); + $logger = spip_logger($logFile); + $logger->log($level, preg_replace( + "/\n*$/", + "\n", + is_string($message) ? $message : print_r($message, true) + )); + + + if (!array_key_exists($logFile, $deprecated)) { + $deprecated[$logFile] = true; + if ($logFile === 'spip') { + trigger_deprecation( + 'spip', + '5.0', + sprintf( + 'spip_log(\'message\') function is deprecated ; use spip_logger().' + . ' Example: spip_logger()->info(\'message\').', + $logFile, + $logFile, + ) + ); + } else { + trigger_deprecation( + 'spip', + '5.0', + sprintf( + 'spip_log(\'message\', \'%s\') function is deprecated ; use spip_logger().' + . ' Example: spip_logger(\'%s\')->info(\'message\').', + $logFile, + $logFile, + ) + ); } - $log($pre[$niveau] . ' ' . $message, $logname); } } diff --git a/ecrire/src/ErrorHandler.php b/ecrire/src/ErrorHandler.php index 5ef9ad2f72..860ffc034b 100644 --- a/ecrire/src/ErrorHandler.php +++ b/ecrire/src/ErrorHandler.php @@ -33,7 +33,7 @@ final class ErrorHandler { $errfile = $t['file']; $errline = $t['line']; - spip_log(sprintf('%s in %s on line %s', $errstr, $errfile, $errline), 'deprecated.' . _LOG_INFO); + spip_logger('deprecated')->info(sprintf('%s in %s on line %s', $errstr, $errfile, $errline)); return false; } } -- GitLab