Table des matières :
- Définir un monitoring d’erreurs exploitable sur PrestaShop (côté serveur et côté navigateur)
- Logs PHP : PHP-FPM, exceptions PrestaShop, et “fatal errors” que vous ne voyez pas
- Logs MySQL/MariaDB : erreurs, deadlocks et lenteurs qui dégénèrent en erreurs PHP
- Logs JavaScript : capturer les erreurs front qui cassent le checkout sans rien écrire côté serveur
- Centralisation des logs : corréler Nginx/Apache, PHP, PrestaShop et MySQL sans devenir archiviste
- Alertes e-mail : déclencher au bon moment, avec le bon niveau de bruit
- Implémentation côté PrestaShop : journaliser proprement et envoyer une alerte sans casser la prod
- Runbook de corrélation rapide : de l’erreur à la cause racine en moins de 15 minutes
Définir un monitoring d’erreurs exploitable sur PrestaShop (côté serveur et côté navigateur)
Le monitoring d’erreurs PrestaShop n’est pas un écran Grafana “qui bouge”. C’est une chaîne d’observabilité centrée sur un objectif simple : réduire le MTTR (Mean Time To Recovery) quand la boutique casse (checkout, recherche, BO), en vous donnant des preuves (logs) corrélables entre couches : reverse proxy (HAProxy/Nginx/Apache), PHP-FPM, PrestaShop (legacy + Symfony), MySQL/MariaDB et JavaScript front.
Sur PrestaShop 8.1.x et 9.x (PHP 8.2/8.3), la réalité opérationnelle est que le core n’offre pas un “error monitoring” prêt pour la prod. Vous avez des logs Symfony dans var/logs/, un historique d’événements dans la table ps_log, et beaucoup de bruit si vous activez le debug. Le reste (centralisation, corrélation, alerting) est à construire au niveau infra et/ou via un module.
Pour que ce monitoring soit exploitable, posez dès le départ un périmètre clair (ce qui est collecté, par qui, combien de temps, et comment on déclenche une action). Une checklist simple (qui évite 80% des “on a des logs mais on ne s’en sert pas”) :
- Objectif : quelles pannes devez-vous réduire en priorité ? (paiement/checkout, BO, recherche, import, webservice…)
- Sources : proxy → PHP-FPM → PrestaShop → DB → JS, + OS (OOM killer, disque plein, saturation I/O).
- Corrélation : au moins un identifiant de requête (request id) et un horodatage cohérent (timezone, NTP).
- Rétention : 7/14/30 jours selon le volume et la capacité d’investigation (les incidents “intermittents” dépassent souvent 7 jours).
- RGPD : minimisation des données (ne pas logguer d’email, d’adresse, de contenu de formulaire), contrôle d’accès, journalisation des accès aux logs si vous centralisez.
- Process : “qui reçoit quoi” (P0/P1/P2), et quel runbook est appliqué (sinon l’alerte ne réduit pas le MTTR, elle augmente le stress).
Enfin, ne confondez pas journalisation et alerting. Tout log ne doit pas devenir une alerte e-mail, sinon vous obtiendrez l’effet inverse : plus personne ne lit. OWASP le résume brutalement dans sa classification A09 (Top 10 2021) : « Without logging and monitoring, breaches cannot be detected. » (OWASP Top 10 2021 – Security Logging and Monitoring Failures, OWASP Top10).
Logs PHP : PHP-FPM, exceptions PrestaShop, et “fatal errors” que vous ne voyez pas
Côté PHP, la base (en prod) est non négociable : display_errors=0, log_errors=1, et un error_reporting aligné sur votre stratégie (souvent E_ALL mais filtré par handler). Sur PHP-FPM, préférez une configuration par pool (/etc/php/8.2/fpm/pool.d/www.conf ou équivalent) avec un fichier dédié :
; php-fpm pool
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php-fpm/prestashop-error.log
php_admin_value[memory_limit] = 512M
; utile si vos workers écrivent sur stdout/stderr
catch_workers_output = yes
Le point qui piège : beaucoup d’incidents PrestaShop ne remontent pas dans var/logs/prod.log parce qu’ils sont fatals (OOM, segmentation fault d’extension, timeout FPM, max_execution_time) ou parce qu’ils se produisent avant l’initialisation complète de Symfony/Monolog. Dans ces cas, c’est le log PHP-FPM et/ou le log du serveur web qui racontent l’histoire (ex. Primary script unknown, Allowed memory size exhausted, FastCGI sent in stderr). Si vous diagnostiquez des indisponibilités, recoupez systématiquement avec votre runbook HTTP (voir l’article interne sur le diagnostic Erreur HTTP 503 : diagnostic serveur, logs et ressources).
Deux réglages PHP-FPM “pratiques” pour transformer un incident intermittent en preuve lisible (sans mettre PS_MODE_DEV à true) :
request_slowlog_timeout+slowlog(côté FPM) : si une requête dépasse X secondes, FPM dump un backtrace côté serveur. Très utile quand un endpoint “freeze” (paiement, search, BO) sans forcément générer d’exception.pm.status_path: exposer l’état du pool (avec restriction IP) pour voir rapidementmax_children reached,listen queue, etc. Cela se corrèle très bien avec les 503.
Côté PrestaShop, distinguez :
- Symfony (8.x/9.x) : logs applicatifs dans
var/logs/(prod.log,dev.log), gérés par Monolog. - Legacy : événements enregistrés via
PrestaShopLogger/ tableps_log(utile en BO, peu utile pour une corrélation infra).
En prod, gardez PS_MODE_DEV désactivé : vous voulez des logs, pas une fuite d’info. Pour le debug développeur, utilisez un environnement local/staging avec Xdebug (voir Xdebug VS Code : configurer le débogage PHP en local) et remontez les erreurs structurées vers un agrégateur plutôt que d’ouvrir le robinet de display_errors.
Un repère simple quand vous cherchez “où est l’erreur” :
- Erreur visible dans le navigateur (page blanche/500), mais
prod.logvide → regardez d’abord PHP-FPM + webserver. - 503 au niveau proxy → regardez d’abord upstream (FPM saturé, timeout, file descriptors), puis DB.
- Erreurs aléatoires sur quelques pages → cherchez des exceptions applicatives (Monolog) + requêtes SQL lentes + erreurs JS.
Logs MySQL/MariaDB : erreurs, deadlocks et lenteurs qui dégénèrent en erreurs PHP
Sur une boutique qui “tombe”, MySQL est souvent l’élément déclencheur, mais rarement l’élément regardé en premier. Pour un monitoring d’erreurs PrestaShop sérieux, vous devez activer (au minimum) :
- error log MySQL/MariaDB : crash InnoDB, erreurs de tables, problèmes de droits.
- slow query log : requêtes dépassant
long_query_timeet/ou non indexées. - (optionnel, avancé) Performance Schema pour profiler proprement sans activer le general log.
Le slow query log est l’outil le plus rentable parce qu’il transforme un “site lent / timeouts aléatoires” en liste de requêtes corrigeables. Procédez proprement (impact perf, rotation, volume) ; si vous êtes sur PrestaShop, vous avez déjà un guide pas-à-pas : Requêtes MySQL lentes PrestaShop : activer slow query log.
Deux erreurs classiques en production (et leurs “traductions” côté PHP) :
- Lenteur DB → timeout PHP-FPM → 504/503 : côté PHP vous verrez parfois juste une erreur “execution time exceeded” ou un timeout upstream, sans mention explicite de la requête.
- Verrous/transactions → timeouts : côté PHP, des messages comme
Lock wait timeout exceededouMySQL server has gone away, alors que la cause est un pic de contention sur des tables critiques.
Ensuite, reliez le slow log à des actions :
- si les requêtes lentes portent sur
ps_product,ps_category_product,ps_specific_price, vous êtes souvent face à une combinaison catalogue + modules + filtres qui explose en JOIN. - si vous voyez des patterns
ORDER BY RAND(),LIKE '%term%', ou desWHEREnon couverts, passez à l’optimisation index/EXPLAIN (voir Index MySQL : optimiser WHERE, JOIN et ORDER BY avec EXPLAIN).
Ne négligez pas les deadlocks et verrous (très visibles sur pics de commandes). Quand des transactions se bloquent, votre PHP finit par timeout, et votre log PHP ne vous dira que “MySQL server has gone away” ou “Lock wait timeout exceeded”. Le réflexe : SHOW ENGINE INNODB STATUS\G au moment de l’incident, plus extraction des métriques (threads running, buffer pool) et corrélation avec le trafic.
Astuce “exploitation” : si vous êtes en pleine période de charge (soldes, Black Friday, diffusion TV), logguer tous les deadlocks peut vous faire gagner du temps. Sur MariaDB/MySQL, l’option innodb_print_all_deadlocks (si disponible selon version) permet de les écrire dans l’error log, ce qui évite d’attendre le “bon moment” pour lancer SHOW ENGINE INNODB STATUS\G.
Enfin, côté conformité : le slow query log peut contenir des données “métier” si vos requêtes embarquent des valeurs directement (ce qui arrive via modules ou requêtes non préparées). En contexte UE/France, appliquez une règle simple : ne conservez pas plus longtemps que nécessaire et restreignez l’accès (les logs restent des données potentiellement sensibles). Pour une vue plus macro (ressources serveur, saturation I/O), vous pouvez coupler à un agent (voir Netdata monitoring : surveiller AWS, Kubernetes, bases de données et serveurs web).
Logs JavaScript : capturer les erreurs front qui cassent le checkout sans rien écrire côté serveur
La partie la plus sous-monitorée sur PrestaShop reste le JavaScript. Un thème ou un module peut casser le panier, l’auth, ou le paiement avec une simple exception (TypeError, undefined is not a function) sans générer d’erreur serveur. Résultat : conversion en chute, serveur “healthy”, et un MTTR énorme parce qu’on n’a pas de signal.
Techniquement, le minimum viable est de capter error et unhandledrejection et d’envoyer un payload vers un endpoint serveur (module) :
window.addEventListener('error', (e) => {
navigator.sendBeacon('/module/yourmodule/jslog', JSON.stringify({
message: e.message,
file: e.filename,
line: e.lineno,
col: e.colno,
stack: e.error?.stack,
url: location.href,
ua: navigator.userAgent,
}));
});
window.addEventListener('unhandledrejection', (e) => {
navigator.sendBeacon('/module/yourmodule/jslog', JSON.stringify({
message: String(e.reason),
stack: e.reason?.stack,
url: location.href,
}));
});
Trois points importants si vous voulez que ce soit actionnable : (1) dédupliquez côté serveur (hash message+stack+page), sinon un bug sur la home va générer des milliers d’événements ; (2) contextualisez (idshop, idlang, id_currency, panier si disponible, route PrestaShop, version thème/module) ; (3) protégez les données (ne logguez jamais tokens, emails, numéros, contenus de formulaire). Si votre organisation impose des règles RGPD strictes, recoupez avec vos pratiques d’audit (voir Audit RGPD PrestaShop : 88 points de contrôle pour boutiques).
Deux raffinements qui font une grosse différence en e-commerce (sans tomber dans l’usine à gaz) :
- Échantillonnage (sampling) : sur une page à fort trafic (home), remonter 100% des erreurs peut saturer votre collecte. Échantillonnez (ex. 10% des sessions) sauf sur les pages critiques (panier/checkout/paiement) où vous conservez 100%.
- Marqueurs fonctionnels : logguez un mini “breadcrumb” (ex.
add_to_cart_clicked,payment_iframe_loaded,place_order_clicked) avant l’erreur. Ça évite le diagnostic “ça casse quelque part dans le checkout” et permet de localiser l’étape.
Enfin, si votre front est minifié (CCC, bundlers, thème), vous avez besoin de source maps pour transformer un stacktrace inutilisable en fichier/ligne réel. Sans ça, votre monitoring JS est un cimetière de app.min.js:1:12345. Si vous déployez une CSP stricte, profitez de Content-Security-Policy-Report-Only et des rapports CSP pour attraper certaines classes d’erreurs (scripts bloqués, inline refusé). Pour la partie headers, voir HTTP Security Headers en PHP : guide CSP, HSTS, X-Frame-Options.
Centralisation des logs : corréler Nginx/Apache, PHP, PrestaShop et MySQL sans devenir archiviste
Le problème, ce n’est pas d’avoir des logs. C’est d’avoir trop de fichiers, sur trop de machines, sans identifiant commun. La centralisation est ce qui transforme une chasse au trésor (SSH, grep, timestamps) en diagnostic en quelques minutes.
Le principe à viser : normaliser au format structuré (JSON) quand c’est possible, ou parser via pipeline (grok) quand ça ne l’est pas. Côté reverse proxy (Nginx/HAProxy), ajoutez un request id (ex. X-Request-Id) et logguez-le. Côté PHP, récupérez cet id et propagez-le dans vos logs applicatifs (Monolog processor côté Symfony, ou pré-traitement dans un front controller legacy). Ça permet ensuite de faire : “requête X → erreur PHP → requête SQL lente → exception checkout”.
Mini-scénario très fréquent : à 18h (heure FR) pendant une opération promo, vous voyez des 503. Sans corrélation, vous alternez “ça vient du thème ? du paiement ? du serveur ?”. Avec un X-Request-Id, vous pouvez :
1) isoler les requêtes en 503 dans le log proxy,
2) retrouver le même request_id dans les logs FPM (upstream timed out / max_children reached),
3) constater au même timestamp une flambée de Threads_running et des requêtes lentes sur ps_specific_price (discounts),
4) conclure : montée en charge → DB lente → workers PHP bloqués → saturation FPM → 503.
Si vous utilisez HAProxy, son logging est très riche (timers Tq/Tw/Tc/Tr/Tt) et se prête bien à la corrélation (voir HAProxy reverse proxy : terminaison TLS, rate limiting et supervision Prometheus).
Pour l’outillage, plusieurs stacks tiennent la route :
- ELK / OpenSearch (Filebeat/Vector → Logstash → Elasticsearch/OpenSearch → Kibana/OpenSearch Dashboards). Si vous parsez beaucoup, Logstash reste une référence (voir Logstash : plugins Input, Filter, Output pour Elasticsearch et Kafka).
- Grafana + Loki (agent promtail/vector → Loki → Grafana). Plus simple pour la recherche de logs, très bon couplage avec métriques.
Gardez en tête une règle opérationnelle (et anti “logs sur disque”) qui reste valide en 2026 : « A twelve-factor app never concerns itself with routing or storage of its output stream. It should not attempt to write to or manage logfiles. » (The Twelve-Factor App, Logs, 12factor.net/logs). Sur PrestaShop, vous n’êtes pas dans une app 12-factor pure, mais l’idée est applicable : écrivez des logs, puis externalisez la collecte (rotation + expédition). Coupez court à la question “où stocker ?” : sur une plateforme dédiée, avec rétention (7/14/30 jours) et contrôle d’accès.
Alertes e-mail : déclencher au bon moment, avec le bon niveau de bruit
L’alerte e-mail est utile pour les pannes et les régressions à fort impact, pas pour chaque notice PHP. Définissez des classes d’alertes :
- P0 : checkout/paiement indisponible, BO inaccessible, erreurs 5xx massives.
- P1 : hausse anormale d’exceptions, explosion de requêtes lentes, erreurs JS sur pages panier/paiement.
- P2 : warnings récurrents, dégradations lentes, dette technique.
Pour rendre ces niveaux opérationnels, formalisez une matrice “signal → action”. Exemple (à adapter à votre volumétrie) :
| Signal | Fenêtre | Seuil | Niveau | Action |
|---|---|---|---|---|
5xx sur /order / /checkout |
5 min | > 2% des requêtes | P0 | mail + escalade, investigation immédiate |
max_children reached PHP-FPM |
5 min | > 0 | P0/P1 | mail, vérifier saturation + DB |
| Requêtes lentes > 2s | 10 min | > 50 | P1 | mail résumé “top requêtes”, plan correctif |
| Erreurs JS sur page paiement | 10 min | > 20 événements uniques | P1 | mail au dev/theme, rollback si régression |
| Disque > 90% | 15 min | > 90% | P1 | mail + purge/rotation |
Sur un VPS/dédié, la voie la plus simple est souvent de déclencher des e-mails sur événements système : systemd (journal), logwatch, swatchdog, ou un script cron qui grepe un fichier et envoie un mail. Exemple minimal (à adapter) : un timer qui envoie un mail si journalctl -p err sur 5 minutes contient des erreurs PHP-FPM. L’avantage : pas de dépendance à PrestaShop. L’inconvénient : corrélation applicative limitée.
Sur une architecture déjà instrumentée (Prometheus, Grafana), la bonne pratique est de faire remonter des compteurs (ex. nginx_http_requests_total{status=~"5.."}) et de laisser Alertmanager gérer déduplication, silence, escalade. Pour la partie “réduction des fausses alertes” (qui conditionne la survie de votre système d’alerting), alignez-vous sur une démarche seuils + fenêtres + budgets d’erreurs : Surveillance PrestaShop : tableau de bord, seuils et réduction des-fausses-alertes.
Côté transport e-mail, n’ignorez pas les contraintes infra : port 25 filtré, réputation IP, SPF/DKIM/DMARC. Sur OVHcloud et autres hébergeurs, la livraison mail est souvent le vrai point de défaillance d’un système d’alerting “fait maison”. Si vous êtes sur VPS, vérifiez les limitations SMTP et la configuration (voir VPS OVHcloud : sécurité, anti-DDoS, SMTP 25 et bonnes pratiques admin).
Implémentation côté PrestaShop : journaliser proprement et envoyer une alerte sans casser la prod
Si vous devez capter des erreurs métier PrestaShop (ex. exceptions d’un module paiement, erreurs de webservice, échecs de génération PDF), un module peut compléter l’infra. Le but n’est pas de “réinventer Sentry”, mais d’attraper des événements précis, enrichis, et de les pousser vers votre collecte (HTTP, syslog, filebeat) ou vers une alerte e-mail P0/P1.
Côté Symfony (PrestaShop 8/9), privilégiez l’intégration Monolog : processor pour injecter id_shop, employee, cart, X-Request-Id, et handler “fingers crossed” (buffer jusqu’à une erreur) afin d’éviter la verbosité permanente. Côté legacy, PrestaShopLogger::addLog() remplit la table ps_log, mais ça ne suffit pas pour corréler avec PHP-FPM/Nginx.
Un bon compromis “prod-friendly” consiste à logger plus riche, mais moins souvent :
- enrichir seulement les événements au-dessus d’un niveau (error/critical),
- “tagger” les erreurs par domaine (paiement, stock, transporteur, BO),
- inclure un identifiant stable (hash) pour dédupliquer et agréger.
Si vous partez sur un fichier, respectez : permissions (utilisateur FPM), rotation (logrotate), et pas de PII. Concrètement : privilégiez des identifiants techniques (idcart, idorder) plutôt que des emails, et ne logguez jamais le contenu complet d’une requête HTTP (body) sur un endpoint checkout.
Pour l’alerte e-mail, utilisez la classe Mail de PrestaShop (qui s’appuie selon versions sur les bibliothèques mail disponibles) en appliquant une règle stricte : rate-limit + déduplication. Un exemple de pattern robuste :
1) écrire l’événement (avec hash) dans une table dédiée ps_yourmodule_error_event ;
2) un cron (ou commande CLI) agrège sur 5 minutes ;
3) envoie un mail unique “top 10 des erreurs” si un seuil est dépassé ;
4) marque les événements “notifiés”.
Cette approche a un avantage très “terrain” : si un module part en boucle (même exception 2 000 fois), vous ne recevez pas 2 000 emails. Vous recevez un email exploitable avec :
- top erreurs (message + page + version module/thème),
- volume sur la fenêtre,
- premiers/derniers timestamps,
- lien vers la recherche dans votre outil de logs (si centralisé).
Si vous n’avez pas encore industrialisé vos tâches planifiées, appuyez-vous sur les commandes CLI PrestaShop et un cron serveur plutôt que sur du “cron web” fragile (voir Commandes CLI PrestaShop : liste, catégories et options d’aide). Et si vous exploitez déjà une chaîne CI/CD, testez ces chemins d’erreur en staging (synthetic checkout, tests module) au lieu d’attendre la prod.
Runbook de corrélation rapide : de l’erreur à la cause racine en moins de 15 minutes
Quand on parle “monitoring d’erreurs : logs PHP, MySQL, JavaScript et alertes e-mail”, l’objectif final est un runbook que l’équipe applique sans improviser. Voici un chemin de corrélation qui marche bien sur PrestaShop en incident réel.
Symptôme A : 500/503 sur panier/checkout. Commencez par le reverse proxy (Nginx/HAProxy) : ratio 5xx, latences, erreurs upstream. En 503, vérifiez saturation (workers FPM, limites OS, files descriptors) et recoupez avec votre guide (voir Erreur HTTP 503 : diagnostic serveur, logs et ressources). Ensuite seulement, allez sur PHP-FPM (slowlog, pm.status_path, max_children reached) et enfin sur var/logs/prod.log.
Un enchaînement “15 minutes” qui marche bien :
- minutes 0–3 : proxy → top endpoints en 5xx, latences,
upstream_response_time - minutes 3–7 : FPM → saturation (
max_children reached), erreurs fatales, slowlog si activé - minutes 7–12 : DB → threads, slow log, deadlocks au timestamp
- minutes 12–15 : app → exceptions Symfony/legacy + identification du module/feature incriminé
Si vous faites des soldes/flash sales, ce runbook doit vivre dans votre routine perf (voir PrestaShop performance : monitoring, tests de charge et runbooks soldes).
Symptôme B : backoffice lent, requêtes admin interminables, timeouts aléatoires. Regardez MySQL : Threads_running, Innodb_row_lock_time, slow query log. Sur PrestaShop, beaucoup de lenteurs admin viennent d’agrégations catalogue/commandes et de modules qui surchargent les grilles. Si vous avez des listings personnalisés, sachez précisément ce que vous avez ajouté (voir PrestaShop module CRUD : personnaliser les listings, actions et vues détail). Et n’oubliez pas que l’optimisation DB est souvent plus rentable que de “mettre plus de CPU” (voir aussi Performance PrestaShop : benchmarks et optimisation PHP-FPM, OPCache, MySQL).
Symptôme C : conversion en baisse, mais serveur OK. Priorité au monitoring JS : erreurs sur pages panier/paiement, scripts tiers, CSP, erreurs de modules front. Ensuite, test fonctionnel ciblé (synthetic) sur les parcours critiques. Et si votre diagnostic dérive vers “c’est peut-être le cache / CCC / bundling”, recoupez avec votre discipline cache front/back (voir PrestaShop soldes : optimiser le cache multi-niveaux et CCC).
Ce runbook est volontairement agressif : il vous pousse à regarder d’abord les couches qui expliquent les pannes fatales (proxy/PHP-FPM/MySQL) puis à remonter vers l’applicatif. C’est exactement ce qui fait la différence entre “on a vu l’erreur dans prod.log” et “on a identifié la cause racine, corrigé, et ajouté une alerte e-mail qui se déclenche uniquement quand ça recommence”.
