web-dev-qa-db-fra.com

Attrapez toutes les uncaughtException pour Node js app

J'ai une question: comment puis-je gérer toutes les exceptions non capturées (une erreur d'opération/de développement enlève tout le service) pour mon application de nœud. Ensuite, je peux envoyer une alerte par courrier électronique à chaque fois que vous détectez une erreur.

16
Nam Tran Thanh

Vous pouvez utiliser les événements process 'uncaughtException' et 'unhandledRejection'.

Rappelez-vous également qu’il ne peut pas reprendre en toute sécurité fonctionnement normal après 'uncaughtException', car le système est corrompu :

L'utilisation correcte de 'uncaughtException' consiste à effectuer une opération synchrone nettoyage des ressources allouées (descripteurs de fichier, descripteurs de fichier, etc.) avant d'arrêter le processus.

Exemple:

process
  .on('unhandledRejection', (reason, p) => {
    console.error(reason, 'Unhandled Rejection at Promise', p);
  })
  .on('uncaughtException', err => {
    console.error(err, 'Uncaught Exception thrown');
    process.exit(1);
  });
34
Dario

Vous pouvez utiliser l'API de domaine: https://nodejs.org/api/domain.html Mais il est déconseillé et de toute façon déconseillé. 

En général, vous souhaitez gérer les erreurs où qu'elles se produisent et éviter une approche "interceptable". 

Si une erreur se produit, l'ignorer ne constitue pas une incitation à la réparer et peut même vous empêcher de savoir que votre programme fonctionne mal. 

Au lieu de cela, le meilleur moyen de le gérer consiste à faire planter votre programme, à le consigner (et au vidage de la pile/du noyau), puis à le redémarrer automatiquement, à l'aide de pm2 ou de nodemon.

Pour un discours (très) long mais perspicace de Joyent (créateurs de nœuds), je vous recommande fortement de lire ce lien: Traitement des erreurs dans Node.JS

Il y a aussi un événement process.on('uncaughtException') (que vous ne devriez pas non plus utiliser)

Edit: Un peu plus de détails et une tentative de résolution de votre problème . En utilisant un logiciel tel que pm2 pour redémarrer votre application en cas de plantage, vous pourrez également voir error.log, qui vous donnera le trace de la pile. Il semble donc que la seule chose dont vous ayez encore besoin, c'est d'être alerté du crash. 

Pour cela, vous voudrez peut-être jeter un œil sur des interfaces telles que Keymetrics (les mêmes qui ont créé pm2) qui pourraient éventuellement vous alerter sur des erreurs.

Voici une solution intéressante que j'ai utilisée une fois, il y a très longtemps:

  • lorsque votre application (re) démarre, elle recherche un journal des erreurs
  • S'il en trouve un, il vous alerte avec le contenu du fichier journal
  • il renomme/déplace ensuite le fichier journal des erreurs à un autre emplacement

Je ne recommanderais pas nécessairement cette solution, mais elle répond à toutes les spécifications dont vous avez besoin, alors amusez-vous!

Edit2: Si vous souhaitez approfondir les sujets relatifs au développement de services et aux meilleures pratiques, consultez son lien suggéré par @Paul dans les commentaires: https://12factor.net/

8
xShirase

le mieux est de laisser l’application se bloquer, de consigner l’erreur puis de relancer le processus. vous pouvez le faire simplement comme ça 

var cluster = require('cluster');

var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  for (var i = 0; i < numCPUs; ++i) {
    cluster.fork();
  }
  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`);
    cluster.fork();
  });
} else {
  var http = require('http');
  var httpServer = http.createServer(app).listen(httpPort, function () {
      console.log('process id local', process.pid)
      console.log("http server started at port " + httpPort);
  });
}

process.on('uncaughtException', function (err) {
  console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
  console.error(err.stack)
  process.exit(1)
})

`

0
Suman