Une extension chargée de synchroniser quotidiennement les écritures comptables d’un cabinet d’expertise avec son logiciel bancaire produisait, en cas d’échec, des messages noyés dans le fichier error_log général du serveur, partagé avec des dizaines d’autres messages PHP sans rapport. Après quelques mois de fonctionnement, ce fichier avait atteint douze mégaoctets, rendant toute recherche d’un incident précis pénible. Il fallait un système de journalisation dédié, avec ses propres niveaux et sa propre rotation.
Une classe de log minimale
class Kaolin_Logger {
const DEBUG = 'debug';
const INFO = 'info';
const WARNING = 'warning';
const ERROR = 'error';
private static $niveau_minimum = self::INFO;
public static function log( $niveau, $message, $contexte = array() ) {
if ( ! self::doit_journaliser( $niveau ) ) {
return;
}
$ligne = sprintf(
"[%s] [%s] %s %s\n",
current_time( 'mysql' ),
strtoupper( $niveau ),
$message,
! empty( $contexte ) ? wp_json_encode( $contexte ) : ''
);
self::ecrire( $ligne );
}
private static function doit_journaliser( $niveau ) {
$ordre = array( self::DEBUG => 0, self::INFO => 1, self::WARNING => 2, self::ERROR => 3 );
return $ordre[ $niveau ] >= $ordre[ self::$niveau_minimum ];
}
}
Séparer les niveaux dès la conception permet de garder debug et info silencieux en production, tout en conservant automatiquement les warning et error qui méritent une attention immédiate, sans devoir commenter ou décommenter du code selon l’environnement.
Écrire dans un fichier protégé, pas dans les uploads publics

Le répertoire wp-content/uploads est, par défaut, entièrement accessible publiquement via HTTP. Y écrire un journal contenant potentiellement des identifiants de transaction ou des messages d’erreur techniques serait une fuite d’information évitable. La solution retenue combine un sous-répertoire dédié et un fichier .htaccess qui en interdit l’accès direct.
private static function ecrire( $ligne ) {
$upload_dir = wp_upload_dir();
$dossier = trailingslashit( $upload_dir['basedir'] ) . 'kaolin-logs';
if ( ! file_exists( $dossier ) ) {
wp_mkdir_p( $dossier );
file_put_contents( $dossier . '/.htaccess', "Deny from all\n" );
file_put_contents( $dossier . '/index.php', "<?php\n// Silence is golden.\n" );
}
$fichier = $dossier . '/synchro-' . gmdate( 'Y-m-d' ) . '.log';
error_log( $ligne, 3, $fichier );
}
Le fichier index.php vide complète la protection sur les configurations serveur où .htaccess ne serait pas pris en compte (Nginx par exemple), en évitant qu’un listage de répertoire n’expose la liste des journaux disponibles.
Un fichier par jour, pour une rotation naturelle
Plutôt que d’écrire indéfiniment dans un unique fichier, nommer chaque fichier de journal avec la date du jour (synchro-2022-09-22.log) offre une rotation naturelle, sans dépendance à un outil externe comme logrotate, pas toujours accessible sur un hébergement mutualisé.
add_action( 'kaolin_nettoyer_vieux_journaux', 'kaolin_supprimer_journaux_anciens' );
function kaolin_supprimer_journaux_anciens() {
$upload_dir = wp_upload_dir();
$dossier = trailingslashit( $upload_dir['basedir'] ) . 'kaolin-logs';
$fichiers = glob( $dossier . '/synchro-*.log' );
$limite = strtotime( '-30 days' );
foreach ( (array) $fichiers as $fichier ) {
if ( filemtime( $fichier ) < $limite ) {
unlink( $fichier );
}
}
}
if ( ! wp_next_scheduled( 'kaolin_nettoyer_vieux_journaux' ) ) {
wp_schedule_event( time(), 'daily', 'kaolin_nettoyer_vieux_journaux' );
}
Une conservation de trente jours s’est avérée suffisante pour ce cabinet comptable : largement assez pour investiguer un incident signalé avec retard, sans laisser les journaux s’accumuler indéfiniment sur le serveur.
Désactiver le niveau debug en production
Le niveau minimum de journalisation ne doit jamais rester à DEBUG en production : le volume de lignes générées deviendrait rapidement disproportionné par rapport à leur utilité réelle. Un filtre dédié permet d’ajuster ce seuil sans modifier le code de la classe elle-même.
add_filter( 'kaolin_logger_niveau_minimum', function ( $niveau ) {
return defined( 'WP_DEBUG' ) && WP_DEBUG ? Kaolin_Logger::DEBUG : Kaolin_Logger::INFO;
} );
Cette bascule automatique, calquée sur la constante WP_DEBUG déjà présente dans le fichier wp-config.php, évite d’introduire un réglage supplémentaire à gérer manuellement pour chaque environnement de déploiement.
Ce que ce système ne remplace pas
Ce mécanisme reste un journal applicatif simple, pas un système de monitoring. Pour une alerte en temps réel en cas d’échec répété de la synchronisation bancaire, une notification par courriel ou l’intégration d’un outil de supervision externe reste nécessaire en complément : lire un fichier de log après coup ne suffit jamais à réagir dans l’urgence.
En résumé
Un système de journalisation minimal, avec niveaux, stockage protégé et rotation quotidienne, tient en une centaine de lignes de code et évite les deux écueils les plus fréquents : un error_log général illisible, et un journal exposé publiquement par mégarde dans le répertoire des uploads. Pour ce cabinet comptable, ce système a transformé un débogage de plusieurs heures en une recherche de quelques minutes dans le fichier du jour concerné.