La réalisation de webapp avec javascript soulève de nouveaux problèmes.
L'un d'entre eux est la collecte des erreurs générée par le code s'exécutant sur le navigateur d'un utilisateur.
Problème
En effet quelque soit la qualité de votre travail, de la quantité de code testé, ou des efforts mis en oeuvre par votre team qualité, un de vos utilisateurs tenteras quelque chose d'inattendu, utiliseras un navigateur exotique, sera bridé par une configuration étrange ou n'importe quoi d'autre qui provoqueras des erreurs sur votre application.Or la collecte de ces erreurs est cruciale pour améliorer l'expérience utilisateur.
Nous savons parfaitement récupérer les logs d'exécution sur nos serveurs ils sont chez nous après tout, enregistrer une date, un message d'erreur, une stacktrace et pourquoi pas quelques informations permettant de définir le contexte de la levé d'erreur n'est pas si compliqué.
Mais quand l'erreur se produit sur le navigateur d'un client comment faire ?
Le principe
La solution est relativement simple, il s'agit d'intercepter l'erreur et d'envoyer un message enrichis avec des informations permettant de contextualiser celle-ci, à un webservice.L'implémentation que je vous propose convient pour AngularJS.
La gestion des erreurs dans AngularJS
Toute Exception levée dans le scope d'exécution d'AngularJS fini invariablement traitée dans le service exceptionHandler.Le fonctionnement de celui-ci est par défaut de mettre a contribution le service $log et de demander a celui-ci de le traiter comme un message d'erreur $log.error() ce qui a pour effet de générer une erreur dans la console de votre navigateur.
Implémentation
Nous allons créer un module AngularJS qu'on déclarera au bootstraping de l'application et qui contiendra un décorateur du service $log qui nous permettra de surcharger une partie de la méthode error de celui-ci.Le service $provide nous permet a l'aide de sa méthode decorator d'intercepter l'instanciation du service $log et de modifier ses fonctionnalités.
Il ne nous reste plus qu'as écrire un service permettant d'envoyer les messages a un webservice quelconque.
Ce service pourrait ressembler à ceci :
J'utilise _.memoize pour éviter de faire de multiples requêtes concernant la même erreur depuis un seul client. C'est particulièrement utile pour éviter de surcharger d'appel Ajax un mobile ou dans le cas d'une erreur se déclenchant dans une loop.
JQuery est utilisé a la place de $http pour effectuer des requetes XMLHttprequest car $http utilise exceptionHandler qui utilise lui même $log.