Administration Serveur angularforall.com

- Logs et monitoring d'une app Angular en prod

Monitoring Angular Pm2 Logs Nginx Logs Journalctl Production Alerting Logrotate Observabilite
Logs et monitoring d'une app Angular en prod

Pipeline complet de logs Angular SSR : access logs Nginx instrumentes, logs PM2 structures, journalctl, alertes cron et rotation automatique pour une exploitation fiable.

Pourquoi monitorer une app Angular en production

Une application Angular deployee en SSR derriere Nginx ne tombe presque jamais d'un coup. Elle se degrade progressivement : un endpoint API qui ralentit, une instance PM2 qui consomme plus de RAM apres une fuite, un certificat qui expire dans 7 jours, un crash silencieux d'un worker. Le monitoring sert a voir ces signaux faibles avant qu'ils deviennent un incident visible.

Sans monitoring, vous decouvrez les problemes par les utilisateurs. Avec un minimum de monitoring bien place, vous les decouvrez avant eux. La difference n'est pas la sophistication des outils, mais le fait d'avoir trois ou quatre signaux fiables : taux d'erreur HTTP, latence moyenne, RAM par worker, espace disque. Ces quatre indicateurs couvrent l'essentiel des incidents reels.

Cet article reste pragmatique : pas de stack ELK ni de Prometheus pour commencer. Juste les outils deja presents sur tout serveur Linux (logs Nginx, PM2, journalctl, cron) combines pour donner une vue d'exploitation utile et stable. Ces fondations sont compatibles avec une migration ulterieure vers un APM (Datadog, New Relic, Grafana Cloud).

Principe directeur : commencez par savoir quand votre app va mal, avant de chercher pourquoi. Une alerte qui declenche au bon moment vaut mieux qu'un dashboard qui personne ne regarde.

Personnaliser les access logs Nginx

Le format par defaut des access logs Nginx (`combined`) est correct mais limite. Pour une app Angular en production, ajoutez le temps de reponse upstream et le statut du cache pour analyser les performances cote SSR.

# /etc/nginx/nginx.conf
http {
    log_format angular_app '$remote_addr - $remote_user [$time_local] '
                          '"$request" $status $body_bytes_sent '
                          '"$http_referer" "$http_user_agent" '
                          'rt=$request_time uct=$upstream_connect_time '
                          'uht=$upstream_header_time urt=$upstream_response_time '
                          'cache=$upstream_cache_status';

    access_log /var/log/nginx/angular-app.access.log angular_app;
}

Apres `sudo systemctl reload nginx`, chaque ligne contient maintenant les temps detailles. Exemples d'analyses utiles avec awk :

# Top 10 des URLs les plus lentes
awk '{print $NF, $7}' /var/log/nginx/angular-app.access.log | sort -rn | head

# Latence moyenne par status code
awk '{sum[$9]+=$NF; count[$9]++} END {for (s in sum) print s, sum[s]/count[s]"s"}' /var/log/nginx/angular-app.access.log

# Requetes > 1 seconde
awk '$NF > 1 {print $0}' /var/log/nginx/angular-app.access.log | tail -20

Le statut cache permet de mesurer l'efficacite du cache SSR (voir l'article Angular SSR + PM2) :

# Repartition cache HIT/MISS
grep -oP 'cache=\w+' /var/log/nginx/angular-app.access.log | sort | uniq -c | sort -rn

# Output typique :
#   8423 cache=HIT
#   1156 cache=MISS
#    234 cache=BYPASS
Astuce production : creez un access log dedie a chaque application au lieu d'un fichier global. Cela simplifie l'analyse et les filtres logrotate.

Exploiter les error logs Nginx

L'error log de Nginx revele les problemes que l'access log masque : timeout upstream (PM2 ne repond plus), connexion refusee (PM2 plante), certificats expires, limites de descripteurs depassees.

# Streaming en direct
sudo tail -f /var/log/nginx/error.log

# Erreurs des dernieres 24 h
sudo grep "$(date '+%Y/%m/%d')" /var/log/nginx/error.log | head -50

# Compter les types d'erreur
grep -oP '\[(error|warn|crit)\]' /var/log/nginx/error.log | sort | uniq -c

Les patterns les plus frequents pour une app SSR :

  • `upstream timed out` : PM2 met trop de temps a repondre. Augmenter `proxy_read_timeout` ou debugger Node.
  • `connect() failed (111: Connection refused)` : PM2 est arrete. `pm2 status` puis `pm2 restart`.
  • `worker_connections are not enough` : Nginx sature. Augmenter `worker_connections` dans `nginx.conf`.
  • `SSL_do_handshake() failed` : Probleme TLS, souvent un client avec une suite de chiffrement ancienne.

Pour creer un script d'alerte qui detecte les pics d'erreur :

#!/usr/bin/env bash
# /usr/local/bin/check-nginx-errors.sh
set -euo pipefail

LOG="/var/log/nginx/error.log"
THRESHOLD=10
SINCE_MIN=15

ERRORS=$(awk -v d="$(date -d "-${SINCE_MIN} minutes" '+%Y/%m/%d %H:%M')" \
  '$1" "$2 >= d && /\[error\]/' "$LOG" | wc -l)

if [ "$ERRORS" -gt "$THRESHOLD" ]; then
    echo "ALERTE : $ERRORS erreurs Nginx ces $SINCE_MIN dernieres minutes" \
      | mail -s "Nginx errors $(hostname)" admin@exemple.com
fi

Et planifiez via cron pour qu'il tourne toutes les 15 minutes :

*/15 * * * * /usr/local/bin/check-nginx-errors.sh

Capturer et tracer les logs PM2

PM2 separe automatiquement stdout et stderr en deux fichiers par application. Avec un `ecosystem.config.js` propre, ces fichiers se trouvent dans un emplacement previsible (cf. article SSR + PM2).

# Logs en streaming pour toutes les apps
pm2 logs

# Logs d'une app precise, derniere heure
pm2 logs angular-ssr --lines 200

# Logs en JSON (pour piping dans jq)
pm2 logs angular-ssr --json --lines 50 | jq '.message'

# Vider les logs PM2
pm2 flush

Pour ajouter du contexte structurant dans Angular SSR, loggez en JSON cote application. Cela permet ensuite un filtrage performant via `grep`/`jq` ou ingestion dans un APM.

// Dans server.ts (Angular SSR)
const log = (level: string, message: string, meta = {}) => {
  console.log(JSON.stringify({
    timestamp: new Date().toISOString(),
    level,
    message,
    ...meta
  }));
};

app.get('*', (req, res) => {
  log('info', 'request', { path: req.path, ua: req.get('user-agent') });
  // ... rendu SSR
});

Cote serveur, vous pouvez filtrer avec jq :

# Toutes les requetes /admin
pm2 logs angular-ssr --raw | jq 'select(.path | startswith("/admin"))'

# Erreurs uniquement
pm2 logs angular-ssr --raw | jq 'select(.level == "error")'

PM2 propose aussi un dashboard temps reel particulierement utile pour detecter une fuite memoire :

# Dashboard interactif (CPU, RAM par worker)
pm2 monit

# Liste etendue
pm2 list

# Detail d'un process specifique
pm2 show angular-ssr
A configurer absolument : `max_memory_restart` dans `ecosystem.config.js`. Cette option redemarre automatiquement un worker qui depasse un seuil RAM. Tres efficace contre les fuites memoire pendant que vous diagnostiquez.

Surveiller via systemd et journalctl

Sur une distribution moderne (Ubuntu 20+, Debian 11+), `journalctl` centralise tous les logs systeme. C'est l'outil de reference pour voir ce qui s'est passe au niveau OS : redemarrages Nginx, OOM killer, problemes disque, etc.

# Logs Nginx via journalctl
sudo journalctl -u nginx -n 100 --no-pager

# Logs Nginx en live
sudo journalctl -u nginx -f

# Erreurs systeme depuis 1 heure
sudo journalctl -p err --since "1 hour ago"

# Logs du boot actuel
sudo journalctl -b

Si une app PM2 est gere par systemd (cas typique apres `pm2 startup systemd`), vous accedez aussi a ses logs systeme :

# Logs du service PM2 systeme
sudo journalctl -u pm2-angularapp -n 50

# Filtrer par niveau
sudo journalctl -u pm2-angularapp -p err --since today

Pour debusquer un probleme de memoire (`Out Of Memory Killer`) :

# Detecter un processus tue par OOM
sudo journalctl --grep "killed process" --since "24 hours ago"

# Output exemple :
# kernel: Out of memory: Killed process 1234 (node) total-vm:2.1G

L'article systemd et journalctl couvre ces commandes en profondeur. Pour Angular en production, c'est aussi utile que les logs applicatifs.

Mesurer les metriques cles

Au-dela des logs, quelques metriques systeme suffisent pour avoir une vue de sante stable. Sur une app Angular SSR, surveillez :

# CPU et load average
uptime
# 22:14:01 up 12 days, load average: 0.45, 0.52, 0.58

# Memoire utilisee/libre
free -h
#               total  used  free  shared  buff/cache  available
# Mem:          3.8Gi  1.2Gi 800Mi 100Mi   1.7Gi       2.4Gi

# Espace disque
df -h /
#  /dev/vda1   50G  18G   32G   37%  /

# Memoire par process Node (worker PM2)
ps -eo pid,user,%mem,cmd --sort=-%mem | grep node | head

Pour un monitoring en continu plus visuel :

# Top interactif
htop

# Detail des connexions reseau Nginx
sudo ss -tunap | grep nginx

# Nombre de connexions actives sur le port 443
sudo ss -tn | grep :443 | wc -l

Cote application, exposez un endpoint `/health` simple dans votre app SSR. Cela permet de checker l'app sans passer par les pages reelles :

// Dans server.ts
app.get('/health', (req, res) => {
  res.json({
    status: 'ok',
    uptime: process.uptime(),
    memory: process.memoryUsage(),
    timestamp: Date.now()
  });
});

Et un check externe via cron toutes les minutes :

* * * * * curl -f https://votre-domaine.com/health > /dev/null 2>&1 || echo "App DOWN" | mail -s "ALERT" admin@exemple.com

Mettre en place des alertes cron

Le minimum vital : 3-4 alertes simples planifiees via cron. Inutile de courir vers Prometheus si vous n'avez pas encore l'essentiel.

# /usr/local/bin/check-disk.sh
#!/usr/bin/env bash
set -euo pipefail

USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
THRESHOLD=85

if [ "$USAGE" -gt "$THRESHOLD" ]; then
    echo "Disque a ${USAGE}% sur $(hostname)" \
      | mail -s "[ALERT] Disque" admin@exemple.com
fi

Trois alertes essentielles a deployer :

# /etc/cron.d/monitoring-angular
# Disque toutes les heures
0 * * * * root /usr/local/bin/check-disk.sh

# Health check app toutes les minutes
* * * * * root /usr/local/bin/check-app-health.sh

# Erreurs Nginx toutes les 15 minutes
*/15 * * * * root /usr/local/bin/check-nginx-errors.sh

Pour eviter le bruit, ajoutez un mecanisme anti-flood : ne renvoyez pas la meme alerte plus d'une fois par heure.

# /usr/local/bin/check-app-health.sh
#!/usr/bin/env bash
LOCK="/tmp/.alert-app-health.lock"
COOLDOWN=3600  # 1 heure

if curl -sf https://votre-domaine.com/health > /dev/null; then
    rm -f "$LOCK"
    exit 0
fi

if [ -f "$LOCK" ] && [ $(($(date +%s) - $(stat -c %Y "$LOCK"))) -lt "$COOLDOWN" ]; then
    exit 0  # Deja alerte recemment
fi

touch "$LOCK"
echo "App $(hostname) down at $(date)" | mail -s "[ALERT] App down" admin@exemple.com
Erreur courante : envoyer trop d'alertes sur trop de canaux. Une alerte critique doit declencher 1 mail + 1 message Slack, pas 5 systemes.

Configurer la rotation des logs

Sans rotation, les logs Nginx et PM2 finissent par occuper plusieurs Go et ralentir les recherches. Sur Ubuntu/Debian, `logrotate` gere deja Nginx automatiquement (`/etc/logrotate.d/nginx`).

# Verifier la conf logrotate Nginx
cat /etc/logrotate.d/nginx

# Test sans appliquer
sudo logrotate -d /etc/logrotate.d/nginx

# Force une rotation immediate
sudo logrotate -f /etc/logrotate.d/nginx

Pour PM2, le module `pm2-logrotate` fait l'equivalent cote Node :

# Installation
pm2 install pm2-logrotate

# Configuration recommandee
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 14
pm2 set pm2-logrotate:compress true
pm2 set pm2-logrotate:rotateInterval '0 0 * * *'

Pour les logs custom de votre application (ex: `/var/log/angular-ssr/app.log`), creez une regle logrotate dediee :

# /etc/logrotate.d/angular-ssr
/var/log/angular-ssr/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 angularapp angularapp
    sharedscripts
    postrotate
        pm2 reloadLogs > /dev/null
    endscript
}

Verifiez la rotation effective une semaine apres le deploiement. Vous devez voir des fichiers `app.log.1`, `app.log.2.gz`, etc.

Conclusion

Le monitoring d'une app Angular en production tient en quatre piliers : access logs Nginx instrumentes, error logs Nginx surveilles, logs PM2 structures et alertes cron simples. Avec ces quatre elements, vous detectez la grande majorite des incidents reels avant les utilisateurs.

L'erreur classique consiste a vouloir tout instrumenter d'un coup. Demarrez plutot par `pm2 monit` + un check `/health` toutes les minutes + un `df -h` quotidien. Vous verrez immediatement les premiers signaux. Les outils plus avances (Prometheus, Grafana, Sentry) prennent leur sens une fois que ces fondations sont stables.

L'enjeu reel reste de transformer les logs en signal exploitable. Un fichier de 500 Mo qui personne n'ouvre n'apporte rien : meilleur format, parser jq, alerte cron simple. Plus la chaine est courte entre l'evenement et l'alerte, plus le monitoring sert.

Partager