Introduction
Une solution de journalisation efficace est cruciale pour le succès de toute application. Winston est une bibliothèque de journalisation polyvalente et une solution de journalisation populaire disponible pour les applications Node.js. Les fonctionnalités de Winston incluent la prise en charge de plusieurs options de stockage, des niveaux de journalisation, des requêtes de journalisation et un profileur intégré.
Dans ce tutoriel, vous utiliserez Winston pour journaliser une application Node/Express que vous créerez dans le cadre de ce processus. Vous verrez également comment combiner Winston avec Morgan, un autre middleware de journalisation de requêtes HTTP populaire pour Node.js, pour consolider les journaux de données de requêtes HTTP avec d’autres informations. Après avoir terminé ce tutoriel, votre serveur Ubuntu exécutera une petite application Node/Express, et Winston sera implémenté pour journaliser les erreurs et les messages dans un fichier et sur la console.
Prérequis
Pour suivre ce tutoriel, vous aurez besoin de :
-
Un serveur Ubuntu 20.04 avec un utilisateur non-root sudo, que vous pouvez configurer en suivant la configuration initiale du serveur.
-
Node.js installé à l’aide du PPA officiel (archive de paquets personnelle), comme expliqué dans Comment installer Node.js sur Ubuntu 20.04, Option 2.
Étape 1 — Création d’une application Node/Express de base
Winston est souvent utilisé pour enregistrer des événements provenant d’applications web construites avec Node.js. Dans cette étape, vous allez créer une application web Node.js simple en utilisant le framework Express. Vous utiliserez express-generator
, un outil en ligne de commande, pour démarrer rapidement une application web Node/Express.
Étant donné que vous avez installé le Gestionnaire de Paquets Node lors des prérequis, vous pouvez utiliser la commande npm
pour installer express-generator
:
Le drapeau -g
installe le package globalement, ce qui signifie qu’il peut être utilisé comme un outil en ligne de commande en dehors d’un projet/module Node existant.
Avec express-generator
installé, vous pouvez créer votre application en utilisant la commande express
, suivie du nom du répertoire que vous souhaitez utiliser pour le projet:
Pour ce tutoriel, le projet s’appellera myApp
.
Remarque : Il est également possible d’exécuter l’outil express-generator
directement sans l’installer globalement comme une commande système au préalable. Pour ce faire, exécutez cette commande:
La commande npx
est un exécuteur de commandes fourni avec le Gestionnaire de Packages Node qui facilite l’exécution d’outils en ligne de commande à partir du registre npm
.
Lors du premier lancement, il vous demandera si vous acceptez de télécharger le package:
Need to install the following packages:
express-generator
Ok to proceed? (y)
Répondez y
et appuyez sur ENTRÉE
. Maintenant, vous pouvez utiliser npx express-generator
à la place de express
.
Ensuite, installez Nodemon, qui rechargera automatiquement l’application chaque fois que vous apporterez des modifications. Une application Node.js doit être redémarrée chaque fois que des modifications sont apportées au code source pour que ces modifications prennent effet, donc Nodemon surveillera automatiquement les modifications et redémarrera l’application. Comme vous souhaitez pouvoir utiliser nodemon
comme un outil en ligne de commande, installez-le avec le drapeau -g
:
Pour terminer la configuration de l’application, déplacez-vous vers le répertoire de l’application et installez les dépendances comme suit:
Par défaut, les applications créées avec express-generator
s’exécutent sur le port 3000
, donc vous devez vous assurer que le pare-feu ne bloque pas ce port.
Pour ouvrir le port 3000
, exécutez la commande suivante :
Vous avez maintenant tout ce dont vous avez besoin pour démarrer votre application web. Pour ce faire, exécutez la commande suivante :
Cette commande lance l’application sur le port 3000
. Vous pouvez vérifier si elle fonctionne en pointant votre navigateur vers http://votre_adresse_ip_du_serveur:3000
. Vous devriez voir quelque chose comme ceci :
À ce stade, vous pouvez ouvrir une deuxième session SSH vers votre serveur pour le reste de ce tutoriel, en laissant l’application web que vous venez de démarrer s’exécuter dans la session d’origine. Pour le reste de cet article, la session SSH initiale exécutant actuellement l’application sera appelée Session A. Toutes les commandes dans la Session A apparaîtront sur un fond bleu foncé comme ceci :
Vous utiliserez la nouvelle session SSH pour exécuter des commandes et modifier des fichiers. Cette session sera appelée Session B. Toutes les commandes dans la Session B apparaîtront sur un fond bleu clair comme ceci :
Sauf indication contraire, vous exécuterez toutes les commandes restantes dans la Session B.
Dans cette étape, vous avez créé l’application de base. Ensuite, vous allez la personnaliser.
Étape 2 — Personnalisation des variables de journalisation
Bien que l’application par défaut créée par express-generator
soit un bon point de départ, vous devez personnaliser l’application afin qu’elle appelle le bon journalisateur au besoin.
express-generator
inclut le middleware de journalisation HTTP Morgan que vous utiliserez pour enregistrer des données sur toutes les requêtes HTTP. Étant donné que Morgan prend en charge les flux de sortie, il s’associe parfaitement avec la prise en charge des flux intégrée à Winston, vous permettant de consolider les journaux de données des requêtes HTTP avec tout ce que vous choisissez de journaliser avec Winston.
Le modèle de base de express-generator
utilise la variable logger
lors de la référence au package morgan
. Puisque vous utiliserez à la fois morgan
et winston
, qui sont tous deux des packages de journalisation, il peut être confus d’appeler l’un ou l’autre d’entre eux logger
. Pour spécifier la variable que vous souhaitez, vous pouvez modifier les déclarations de variable en éditant le fichier app.js
.
Pour ouvrir app.js
pour l’édition, utilisez nano
ou votre éditeur de texte préféré:
Recherchez la ligne suivante près du début du fichier:
Changez le nom de la variable de logger
à morgan
:
Cette mise à jour spécifie que la variable déclarée morgan
appellera la méthode require()
liée au journalisateur de requêtes Morgan.
Vous devez trouver où la variable logger
a été référencée ailleurs dans le fichier et la changer en morgan
. Vous devrez également changer le format de journal utilisé par le package morgan
en combined
, qui est le format de journal Apache standard et inclura des informations utiles dans les journaux, telles que l’adresse IP distante et l’en-tête de requête HTTP de l’utilisateur.
Pour ce faire, trouvez la ligne suivante :
Modifiez-la comme suit :
Ces modifications vous aideront à comprendre quel package de journalisation est référencé à tout moment après l’intégration de la configuration de Winston.
Une fois terminé, enregistrez et fermez le fichier.
Maintenant que votre application est configurée, vous pouvez commencer à travailler avec Winston.
Étape 3 — Installation et configuration de Winston
Dans cette étape, vous installerez et configurerez Winston. Vous explorerez également les options de configuration disponibles dans le cadre du package winston
et créerez un journal pour enregistrer des informations dans un fichier et sur la console.
Installez winston
avec la commande suivante :
Il est utile de conserver tous les fichiers de configuration de support ou d’utilité pour vos applications dans un répertoire spécial. Créez un dossier config
qui contiendra la configuration de winston
:
Ensuite, créez un dossier qui contiendra vos fichiers journaux :
Enfin, installez app-root-path
:
Le package app-root-path
est utile lors de la spécification des chemins dans Node.js. Bien que ce package ne soit pas directement lié à Winston, il est utile pour déterminer les chemins vers les fichiers dans Node.js. Vous l’utiliserez pour spécifier l’emplacement des fichiers journaux de Winston depuis la racine du projet et pour éviter une syntaxe de chemin relative moche.
Maintenant que la configuration de gestion des journaux est en place, vous pouvez définir vos paramètres. Créez et ouvrez ~/myApp/config/winston.js
pour l’édition :
Le fichier winston.js
contiendra votre configuration winston
.
Ensuite, ajoutez le code suivant pour requérir les packages app-root-path
et winston
:
Avec ces variables en place, vous pouvez définir les paramètres de configuration pour vos transports. Les transports sont un concept introduit par Winston qui fait référence aux mécanismes de stockage/sortie utilisés pour les journaux. Winston est livré avec quatre transports principaux intégrés : Console, File, HTTP et Stream.
Vous vous concentrerez sur les transports console et fichier pour ce tutoriel. Le transport console enregistrera les informations dans la console, et le transport fichier enregistrera les informations dans un fichier spécifié. Chaque définition de transport peut contenir des paramètres de configuration, tels que la taille du fichier, les niveaux de journalisation et le format du journal.
Voici un résumé rapide des paramètres que vous utiliserez pour chaque transport :
niveau
: niveau des messages à journaliser.nom_fichier
: le fichier à utiliser pour écrire les données de journal.gérerExceptions
: intercepter et journaliser les exceptions non gérées.tailleMax
: taille maximale du fichier journal, en octets, avant qu’un nouveau fichier ne soit créé.maxFichiers
: limiter le nombre de fichiers créés lorsque la taille du fichier journal est dépassée.format
: comment la sortie du journal sera formatée.
Niveaux de journalisation indiquent la priorité des messages et sont représentés par un entier. Winston utilise les niveaux de journalisation npm qui sont priorisés de 0 à 6 (le plus élevé au plus bas) :
- 0: erreur
- 1: avertissement
- 2: info
- 3: http
- 4: verbeux
- 5: débogage
- 6: bête
Lorsque vous spécifiez un niveau de journalisation pour un transport particulier, tout ce niveau ou plus élevé sera journalisé. Par exemple, en définissant un niveau de info
, tout ce qui est au niveau erreur
, avertissement
, ou info
sera journalisé.
Les niveaux de journalisation sont spécifiés lors de l’appel du journaliseur, ce qui signifie que vous pouvez exécuter la commande suivante pour enregistrer une erreur: journaliseur.erreur('message d'erreur de test')
.
Ajoutez encore dans le fichier de configuration, le code suivant pour définir les paramètres de configuration des transports fichier
et console
dans la configuration de winston
:
Ensuite, ajoutez le code suivant pour instancier un nouveau journaliste winston
avec des transports de fichier et de console en utilisant les propriétés définies dans la variable options
:
Par défaut, morgan
ne produit des sorties que dans la console, donc vous définirez une fonction de flux qui sera capable de récupérer la sortie générée par morgan
dans les fichiers journaux winston
. Vous utiliserez le niveau de journal info
pour récupérer la sortie par les deux transports (fichier et console). Ajoutez le code suivant au fichier de configuration :
Enfin, ajoutez le code ci-dessous pour exporter le journaliste afin qu’il puisse être utilisé dans d’autres parties de l’application :
Le fichier de configuration complet de winston
ressemblera désormais à ceci :
Enregistrez et fermez le fichier.
Vous avez maintenant configuré le journal, mais votre application n’en est toujours pas consciente, ni comment l’utiliser, vous devez donc l’intégrer avec l’application.
Étape 4 — Intégration de Winston avec l’application
Pour faire fonctionner votre journal avec l’application, vous devez informer express
. Vous avez vu à l’étape 2 que votre configuration express
est située dans app.js
, vous pouvez donc importer votre journal dans ce fichier.
Ouvrez le fichier pour l’édition:
Ajoutez une déclaration de variable winston
près du haut du fichier avec les autres déclarations require
:
Le premier endroit où vous utiliserez winston
est avec morgan
. Toujours dans app.js
, trouvez la ligne suivante :
Met à jour pour inclure l’option stream
:
Ici, vous définissez l’option stream
sur l’interface de flux que vous avez créée dans la configuration de winston
.
Enregistrez et fermez le fichier.
Dans cette étape, vous avez configuré votre application Express pour fonctionner avec Winston. Ensuite, vous examinerez les données de journal.
Étape 5 — Accès aux données de journal et enregistrement de messages de journal personnalisés
Maintenant que l’application est configurée, vous êtes prêt à voir des données de journal. Dans cette étape, vous examinerez les entrées de journal et mettrez à jour vos paramètres avec un exemple de message de journal personnalisé.
Si vous rechargez la page dans le navigateur Web, vous devriez voir quelque chose de similaire à la sortie suivante dans la console de la session SSH A :
Output[nodemon] restarting due to changes...
[nodemon] starting `node bin/www`
info: ::1 - - [25/Apr/2022:18:10:55 +0000] "GET / HTTP/1.1" 200 170 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
info: ::1 - - [25/Apr/2022:18:10:55 +0000] "GET /stylesheets/style.css HTTP/1.1" 304 - "http://localhost:3000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
Il y a deux entrées de journal ici : la première pour la demande de la page HTML ; la deuxième pour la feuille de style associée. Étant donné que chaque transport est configuré pour gérer les données de journal de niveau info
, vous devriez également voir des informations similaires dans le transport de fichier situé à ~/myApp/logs/app.log
.
Pour afficher le contenu du fichier journal, exécutez la commande suivante :
tail
va afficher les dernières parties du fichier dans votre terminal.
Vous devriez voir quelque chose de similaire à ce qui suit :
{"level":"info","message":"::1 - - [25/Apr/2022:18:10:55 +0000] \"GET / HTTP/1.1\" 304 - \"-\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36\"\n","timestamp":"2022-04-25T18:10:55.573Z"}
{"level":"info","message":"::1 - - [25/Apr/2022:18:10:55 +0000] \"GET /stylesheets/style.css HTTP/1.1\" 304 - \"http://localhost:3000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36\"\n","timestamp":"2022-04-25T18:10:55.588Z"}
La sortie dans le fichier transport sera écrite sous forme d’objet JSON puisque vous avez utilisé winston.format.json()
dans l’option format
pour la configuration du transport de fichier. Vous pouvez en apprendre plus sur JSON dans Une introduction à JSON.
Jusqu’à présent, votre enregistreur ne consigne que les requêtes HTTP et les données associées. Ces informations sont essentielles à avoir dans vos journaux.
À l’avenir, vous voudrez peut-être enregistrer des messages de journal personnalisés, tels que l’enregistrement des erreurs ou le profilage des performances des requêtes de base de données. Par exemple, vous appellerez le journal depuis la route de gestion des erreurs. Par défaut, le package express-generator
inclut déjà une route de gestion des erreurs 404
et 500
, donc vous travaillerez avec cela.
Ouvrez le fichier ~/monApp/app.js
:
Trouvez le bloc de code en bas du fichier qui ressemble à ceci :
Cette section est la route de gestion d’erreurs finale qui enverra finalement une réponse d’erreur au client. Étant donné que toutes les erreurs côté serveur passeront par cette route, c’est un bon endroit pour inclure le journal winston
.
Parce que vous traitez désormais avec des erreurs, vous voulez utiliser le niveau de journalisation error
. Les deux transports sont configurés pour journaliser les messages de niveau error
, donc vous devriez voir la sortie dans les journaux de la console et du fichier.
Vous pouvez inclure tout ce que vous voulez dans le journal, y compris des informations telles que :
err.status
: Le code de statut d’erreur HTTP. S’il n’est pas déjà présent, défaut à500
.err.message
: Détails de l’erreur.req.originalUrl
: L’URL qui a été demandée.req.path
: La partie chemin de l’URL de la demande.req.method
: Méthode HTTP de la demande (GET, POST, PUT, etc.).req.ip
: Adresse IP distante de la demande.
Mettez à jour la route de gestionnaire d’erreur pour inclure la journalisation winston
:
Enregistrez et fermez le fichier.
Pour tester ce processus, essayez d’accéder à une page qui n’existe pas dans votre projet. Accéder à une page inexistante provoquera une erreur 404. Dans votre navigateur web, essayez de charger l’URL suivante : http://votre_adresse_ip_du_serveur:3000/foo
. Grâce à la structure de base créée par express-generator
, l’application est configurée pour répondre à une telle erreur.
Votre navigateur affichera un message d’erreur comme ceci :
Lorsque vous regardez la console dans la session SSH A, il devrait y avoir une entrée de journal pour l’erreur. Grâce au format colorize
appliqué, il devrait être facile à repérer :
Output[nodemon] starting `node bin/www`
error: 404 - Not Found - /foo - GET - ::1
info: ::1 - - [25/Apr/2022:18:08:33 +0000] "GET /foo HTTP/1.1" 404 982 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
info: ::1 - - [25/Apr/2022:18:08:33 +0000] "GET /stylesheets/style.css HTTP/1.1" 304 - "http://localhost:3000/foo" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
Quant au journal de fichiers, en exécutant à nouveau la commande tail
, vous devriez voir les nouveaux enregistrements de journal :
Vous verrez un message comme le suivant :
{"level":"error","message":"404 - Not Found - /foo - GET - ::1","timestamp":"2022-04-25T18:08:33.508Z"}
Le message d’erreur comprend toutes les données que vous avez spécifiquement demandé à winston
de journaliser dans le gestionnaire d’erreurs. Ces informations incluront le statut d’erreur (404 – Non trouvé), l’URL demandée (localhost/foo
), la méthode de requête (GET
), l’adresse IP effectuant la requête, et l’horodatage de la demande.
Conclusion
Dans ce tutoriel, vous avez construit une application web Node.js simple et intégré une solution de journalisation Winston qui fonctionnera comme un outil efficace pour fournir un aperçu des performances de l’application.
Vous pouvez faire beaucoup plus pour créer des solutions de journalisation robustes pour vos applications, particulièrement lorsque vos besoins deviennent plus complexes. Pour en savoir plus sur les transports de Winston, consultez la Documentation des Transports de Winston. Pour créer vos propres transports, consultez Ajout de Transports Personnalisés. Pour créer un point de terminaison HTTP à utiliser avec le transport principal HTTP, consultez winstond
. Pour utiliser Winston comme un outil de profilage, consultez Profilage.