anchorage_layer_simple/fixKnowledge/api-anchorage-logs-volumineux.md
ncantu 0960e43a45 Optimisation mémoire api-anchorage avec base de données SQLite
**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)
2026-01-27 21:12:22 +01:00

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-api seul
  • 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

  1. 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
  2. Logs détaillés des transactions d'ancrage

    • Anchor request received - 1 log par transaction
    • Anchor transaction with provisioning - 1 log avec détails
    • Fetched UTXOs - 1 log avec liste des UTXOs (peut être volumineux)
    • Available UTXOs - 1 log avec statistiques
    • Selected UTXO - 1 log
    • Adding change output - 1 log
    • OP_RETURN metadata created - 1 log
    • Anchor transaction sent to mempool - 1 log avec détails
    • Total: ~8-10 logs par transaction d'ancrage
  3. 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

  1. api-anchorage/src/server.js - Réduire le logging des requêtes HTTP
  2. api-anchorage/src/routes/anchor.js - Réduire le nombre de logs par transaction
  3. api-anchorage/src/bitcoin-rpc.js - Réduire les logs détaillés (optionnel)
  4. /etc/systemd/journald.conf - Configuration de rotation des logs

Fichiers de configuration

  • .env - Changer LOG_LEVEL=warn pour 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

  1. Configuration journald (priorité haute) - Prévention immédiate de la saturation
  2. Réduction du logging HTTP (priorité haute) - Impact immédiat sur le volume
  3. Réduction des logs de transaction (priorité moyenne) - Impact significatif
  4. 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