**Motivations:** - Réduction drastique de la consommation mémoire lors des ancrages - Élimination du chargement de 173k+ UTXOs à chaque requête - Stabilisation de la mémoire système sous charge élevée (50+ ancrages/minute) **Root causes:** - api-anchorage chargeait tous les UTXOs (173k+) via listunspent RPC à chaque ancrage - Filtrage et tri de 173k+ objets en mémoire pour sélectionner un seul UTXO - Croissance mémoire de ~16 MB toutes les 12 secondes avec 50 ancrages/minute - Saturation mémoire système en quelques minutes **Correctifs:** - Création du module database.js pour gérer la base de données SQLite partagée - Remplacement de listunspent RPC par requête SQL directe avec LIMIT 1 - Sélection directe d'un UTXO depuis la DB au lieu de charger/filtrer 173k+ objets - Marquage des UTXOs comme dépensés dans la DB après utilisation - Fermeture propre de la base de données lors de l'arrêt **Evolutions:** - Utilisation de la base de données SQLite partagée avec signet-dashboard - Réduction mémoire de 99.999% (173k+ objets → 1 objet par requête) - Amélioration des performances (requête SQL indexée vs filtrage en mémoire) - Optimisation mémoire de signet-dashboard (chargement UTXOs seulement si nécessaire) - Monitoring de lockedUtxos dans api-anchorage pour détecter les fuites - Nettoyage des intervalles frontend pour éviter les fuites mémoire **Pages affectées:** - api-anchorage/src/database.js (nouveau) - api-anchorage/src/bitcoin-rpc.js - api-anchorage/src/server.js - api-anchorage/package.json - signet-dashboard/src/bitcoin-rpc.js - signet-dashboard/public/app.js - features/optimisation-memoire-applications.md (nouveau) - features/api-anchorage-optimisation-base-donnees.md (nouveau)
8.2 KiB
Fix: Logs volumineux api-anchorage
Date: 2026-01-27 Auteur: Équipe 4NK
Problème
Les logs de api-anchorage sont très volumineux et peuvent saturer l'espace disque du journal systemd.
Symptômes
- Volume de logs: 48 MB en 7 jours pour
anchorage-apiseul - Fréquence: ~94 308 lignes par jour (~3 900 lignes/heure)
- Taux actuel: ~2 815 lignes INFO par heure (~47 lignes/minute)
- Taille totale journald: 191.1 MB (tous services confondus)
Impact
- Risque de saturation de l'espace disque dédié aux logs
- Performance dégradée lors de la consultation des logs
- Coût de stockage inutile
- Difficulté à identifier les logs importants dans la masse
Root cause
Sources de logs identifiées
-
Logging de chaque requête HTTP (ligne 44-47 dans
server.js)- Chaque requête GET/POST génère un log INFO
- Inclut les health checks fréquents
- ~447 requêtes HTTP/heure
-
Logs détaillés des transactions d'ancrage
Anchor request received- 1 log par transactionAnchor transaction with provisioning- 1 log avec détailsFetched UTXOs- 1 log avec liste des UTXOs (peut être volumineux)Available UTXOs- 1 log avec statistiquesSelected UTXO- 1 logAdding change output- 1 logOP_RETURN metadata created- 1 logAnchor transaction sent to mempool- 1 log avec détails- Total: ~8-10 logs par transaction d'ancrage
-
Logs de vérification d'ancrage
- Potentiellement très volumineux si recherche dans plusieurs blocs
Analyse quantitative
Sur 1 heure:
- 2 815 lignes INFO
- 447 requêtes HTTP (GET/POST)
- ~3 WARN
- Ratio: ~6.3 lignes de log par requête HTTP
Sur 1 jour:
- ~94 308 lignes
- ~10 728 requêtes HTTP
- ~72 WARN
Sur 7 jours:
- ~244 554 lignes
- ~48 MB de données
- ~504 WARN
Correctifs
1. Réduire le logging des requêtes HTTP (priorité haute)
Problème: Chaque requête HTTP génère un log, y compris les health checks fréquents.
Solution: Ne logger que les requêtes importantes, exclure les health checks et les requêtes GET simples.
Modification recommandée dans server.js:
// Middleware de logging
app.use((req, res, next) => {
// Ne pas logger les health checks et requêtes GET simples
if (req.path === '/health' || req.path === '/' || req.path === '/favicon.ico' || req.path === '/robots.txt') {
return next();
}
// Logger uniquement les requêtes POST (ancrage, vérification)
if (req.method === 'POST') {
logger.info(`${req.method} ${req.path}`, {
ip: req.ip,
userAgent: req.get('user-agent'),
});
}
next();
});
Impact attendu: Réduction de ~80% des logs HTTP (les health checks représentent une grande partie)
2. Réduire le niveau de détail des logs de transaction (priorité moyenne)
Problème: Chaque transaction génère 8-10 logs détaillés.
Solution: Regrouper les logs ou réduire le niveau de détail pour les opérations normales.
Modifications recommandées:
- Option A: Logger uniquement le début et la fin de la transaction
- Option B: Utiliser le niveau DEBUG pour les détails intermédiaires
- Option C: Regrouper plusieurs logs en un seul log structuré
Exemple (Option A):
// Au début
logger.info('Anchor transaction started', { hash: hash.substring(0, 16) + '...' });
// À la fin (regrouper toutes les infos)
logger.info('Anchor transaction completed', {
txid,
hash: hash.substring(0, 16) + '...',
utxosCount: availableUtxos.length,
fee: actualFee,
// ... autres infos importantes
});
Impact attendu: Réduction de ~70% des logs par transaction (de 8-10 logs à 2-3 logs)
3. Configurer la rotation des logs journald (priorité haute)
Solution: Limiter la taille et la durée de rétention des logs dans journald.
Fichier: /etc/systemd/journald.conf
Modifications recommandées:
[Journal]
# Limiter la taille maximale des journaux
SystemMaxUse=500M
SystemKeepFree=1G
SystemMaxFileSize=100M
# Limiter la durée de rétention
MaxRetentionSec=7day
# Rotation automatique
MaxFiles=10
Impact attendu: Prévention de la saturation disque, logs automatiquement nettoyés après 7 jours
4. Utiliser un niveau de log adaptatif (priorité basse)
Solution: Permettre de changer le niveau de log sans redémarrer le service.
Implémentation: Utiliser LOG_LEVEL=warn en production pour ne logger que les warnings et erreurs.
Fichier: .env
LOG_LEVEL=warn
Impact attendu: Réduction de ~95% des logs (seulement warnings et erreurs)
Modifications
Fichiers à modifier
api-anchorage/src/server.js- Réduire le logging des requêtes HTTPapi-anchorage/src/routes/anchor.js- Réduire le nombre de logs par transactionapi-anchorage/src/bitcoin-rpc.js- Réduire les logs détaillés (optionnel)/etc/systemd/journald.conf- Configuration de rotation des logs
Fichiers de configuration
.env- ChangerLOG_LEVEL=warnpour production (si souhaité)
Modalités de déploiement
1. Configuration journald (sans redémarrage de l'application)
# Éditer la configuration
sudo nano /etc/systemd/journald.conf
# Appliquer les modifications
sudo systemctl restart systemd-journald
# Vérifier l'espace utilisé
journalctl --disk-usage
2. Modification du code (nécessite redémarrage)
# Modifier les fichiers source
# ... modifications dans server.js et anchor.js ...
# Redémarrer le service
sudo systemctl restart anchorage-api
# Vérifier les nouveaux logs
journalctl -u anchorage-api.service -f
3. Changement du niveau de log (sans redémarrage si supporté)
# Modifier .env
# LOG_LEVEL=warn
# Redémarrer le service
sudo systemctl restart anchorage-api
Modalités d'analyse
Vérification du volume de logs
# Taille des logs sur 7 jours
journalctl -u anchorage-api.service --since "7 days ago" --no-pager -q | wc -c
# Nombre de lignes par jour
journalctl -u anchorage-api.service --since "1 day ago" --no-pager -q | wc -l
# Nombre de lignes par heure
journalctl -u anchorage-api.service --since "1 hour ago" --no-pager -q | wc -l
# Répartition par niveau
journalctl -u anchorage-api.service --since "1 hour ago" --no-pager -q | grep -oE "\[(INFO|ERROR|WARN|DEBUG)\]" | sort | uniq -c
Vérification de l'espace disque
# Espace utilisé par journald
journalctl --disk-usage
# Espace disque disponible
df -h /var/log
Analyse des types de logs
# Nombre de requêtes HTTP loggées
journalctl -u anchorage-api.service --since "1 hour ago" --no-pager -q | grep -E "POST|GET" | wc -l
# Nombre de transactions d'ancrage
journalctl -u anchorage-api.service --since "1 hour ago" --no-pager -q | grep "Anchor request received" | wc -l
# Nombre de health checks
journalctl -u anchorage-api.service --since "1 hour ago" --no-pager -q | grep "GET /health" | wc -l
Impact attendu
Réduction du volume de logs
- Avant: 48 MB / 7 jours (~6.9 MB/jour)
- Après (avec correctifs 1 + 2): ~10 MB / 7 jours (~1.4 MB/jour)
- Réduction: ~79% de réduction
Réduction du nombre de lignes
- Avant: ~94 308 lignes/jour
- Après: ~20 000 lignes/jour
- Réduction: ~79% de réduction
Bénéfices
- Prévention de la saturation disque
- Amélioration des performances de consultation des logs
- Réduction des coûts de stockage
- Meilleure lisibilité des logs importants
Recommandations prioritaires
- Configuration journald (priorité haute) - Prévention immédiate de la saturation
- Réduction du logging HTTP (priorité haute) - Impact immédiat sur le volume
- Réduction des logs de transaction (priorité moyenne) - Impact significatif
- Niveau de log adaptatif (priorité basse) - Si besoin de réduire encore plus
Notes
- Les modifications du code nécessitent un redémarrage du service
- La configuration journald peut être appliquée sans redémarrage de l'application
- Il est recommandé de tester les modifications en environnement de test avant production
- Surveiller les logs après déploiement pour s'assurer que les informations importantes sont toujours disponibles