**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)
287 lines
8.2 KiB
Markdown
287 lines
8.2 KiB
Markdown
# 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`:**
|
|
|
|
```javascript
|
|
// 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):**
|
|
```javascript
|
|
// 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:**
|
|
```ini
|
|
[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`
|
|
```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)
|
|
|
|
```bash
|
|
# É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)
|
|
|
|
```bash
|
|
# 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é)
|
|
|
|
```bash
|
|
# Modifier .env
|
|
# LOG_LEVEL=warn
|
|
|
|
# Redémarrer le service
|
|
sudo systemctl restart anchorage-api
|
|
```
|
|
|
|
## Modalités d'analyse
|
|
|
|
### Vérification du volume de logs
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# Espace utilisé par journald
|
|
journalctl --disk-usage
|
|
|
|
# Espace disque disponible
|
|
df -h /var/log
|
|
```
|
|
|
|
### Analyse des types de logs
|
|
|
|
```bash
|
|
# 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
|