Regarder les logs

Si seulement j'avais reçu un mail lorsque l'erreur s'est produite, j'aurai pu intervenir plus rapidement...

C'est le genre de phrase que l'on pourrait se dire lorsque notre application plante et provoque une catastrophe chez un client. Souvent, intervenir dès que l'erreur est détectée aurait permis de diminuer l'impact du problème.

Aujourd'hui, c'est ce que nous allons essayer de voir avec yLogger, le composant qui permet de gérer les logs de votre application.

Vous avez bien protégé votre application, les erreurs sont correctement loguées, mais il y en a une qui vous fait peur et vous avez le code suivant :

QUAND EXCEPTION DANS
    executer_traitement_très_risqué()
FAIRE
    logger.ecrire_critique("Le traitement très risqué a explosé." + RC + ExceptionInfo(errMessage))
FIN

Mais voilà, les logs sont enregistrés sur la machine qui fait tourner le code. Lorsque l'erreur se produit, vous n'êtes pas derrière à vérifier ce qu'il se passe. Si seulement vous aviez reçu un mail !

Ça ne s'est pas encore produit ? Tant mieux ! Je vous propose de résoudre ce problème en mettant en place un enregistreur qui permet d'envoyer un mail lorsqu'une erreur critique est rencontrée.

La première chose à faire est de créer l'enregistreur. Pour cela, vous devez créer une nouvelle classe. Pour ma part, je l'appelle ici cEnregistreurVersMail.

cEnregistreurVersMail est une Classe
hérite de cEnregistreur

PRIVÉE
    __adresses_destinataires est un tableau de chaînes

    __serveur_adresse est une chaîne
    __serveur_port est une chaîne
    __serveur_nom_expéditeur est une chaîne
    __serveur_mdp_expéditeur est une chaîne

    __chemin_fichier_log est une chaîne
    __logger est un cLogger dynamique
FIN

On paramètre ensuite le constructeur. Dedans, on indique que l'on n'envoie un mail que dans le cas d'un message critique avec la constante _LOG_CRITIQUE_. On indique aussi le formateur par défaut, je prends le fichier texte.
Notez qu'en paramètre, je récupère un objet logger. Et oui, si je n'arrive pas à envoyer mon mail, j'ai envie d'enregistrer la raison. En le récupérant comme un paramètre, cela m'évite de mettre en place une dépendance avec le projet. Je peux déplacer ma classe dans chacun de mes projets.

PROCEDURE Constructeur(logger est un cLogger dynamique)
Constructeur cEnregistreur(_LOG_CRITIQUE_, mLogger.créer_formateur_texte())
:__logger = logger
    :__adresses_destinataires = ["[email protected]", "[email protected]"]

    :__serveur_adresse = "smtp.fai.com"
    :__serveur_port = 25
    :__serveur_nom = "utilisateur"
    :__serveur_mdp = "mon mot de passe"

    :__chemin_fichier_log = "x:\répertoire\fichier.log" // Changer le chemin du fichier log
FIN

Je dérive ensuite la méthode _enregistrer. C'est la base de la classe cEnregistreur. Chaque message de log passe par cette méthode. Afin d'éviter que le programme bloque les messages, j'utilise un thread pour envoyer le mail. J'aurais aussi pu utiliser une tâche parallèle. J'utilise DonneGUID pour être sûr d'avoir un nom de thread unique.

PROCEDURE _enregistrer(message_log est un stMessage)
ThreadExécute(DonneGUID(), threadNormal, :__envoyer_log_par_mail, message_log)

Et voilà la procédure qui permet d'envoyer le log par mail. J'initialise mes paramètres d'envoi et surtout, je n'oublie pas d'attacher le fichier de log. C'est lui qui me permettra de savoir ce qu'il s'est passé. Je protège l'envoi par un QUAND EXCEPTION.

PROCEDURE PRIVÉE __envoyer_log_par_mail(message_log est un stMessage)
QUAND EXCEPTION DANS
    // Ouverture d'une session SMTP sécurisée TLS
    session_mail est un EmailSessionSMTP
    session_mail..AdresseServeur = :__serveur_adresse
    session_mail..Option = emailOptionDéfaut

    // Le port TLS dépend du fournisseur, à bien vérifier !
    session_mail..Port = :__serveur_port

    session_mail..Nom = :__serveur_nom_expéditeur
    session_mail..MotDePasse = :__serveur_mdp_expéditeur

    // 10 secondes pour le time out
    EmailChangeTimeOut(10)

    SI EmailOuvreSession(session_mail) ALORS
        // Envoi d'un message
        email_log est un Email
        email_log.Expediteur = "[email protected]"
        email_log.Sujet = "Problème dans le projet Truc"
        email_log.Destinataire = :__adresses_destinataires
        email_log.Message = message_log.texte
        EmailChargeFichierAttaché(email_log, :__chemin_fichier_log)

        EmailEnvoieMessage(session_mail, email_log)
        EmailFermeSession(session_mail)
    SINON
        :__logger.ecrire_erreur("Impossible d'envoyer un mail." + RC + ErreurInfo())
    FIN
FAIRE
    :__logger.ecrire_erreur("Impossible d'envoyer un mail." + RC + ExceptionInfo())
FIN

Enfin, il ne me reste plus qu'à ajouter mon enregistreur à mon objet cLogger.

logger = créer_logger(_LOG_INFO_)
logger.ajouter_enregistreur(creer_enregistreur_vers_fichier_texte(_LOG_INFO_, mLogger.créer_formateur_texte(), "x:\répertoire\fichier.log"))
logger.ajouter_enregistreur(allouer un cEnregistreurVersMail(vl.logger))

Dès lors que j'appelle la méthode logger.ecrire_critique(), je recevrais un mail avec le fichier de log.

Et voilà ! Vous avez mis en place un système qui vous permet de recevoir un mail à chaque fois qu'une erreur critique survient. Bien entendu, vous pouvez conditionner l'envoi sur la présence d'un mot clé dans le message de log ou sur tout autre critère (en fonction de l'heure par exemple).

Si vous n'utilisez pas encore yLogger, sachez que je le vends à prix libre.

Sachez aussi que je peux vous proposer des séances d'accompagnement pour vous aider à mettre en place ce composant.

Si vous souhaitez le faire évoluer, n'hésitez pas à m'indiquer vos suggestions.

J'espère que cet article vous a plu et vous permettra d'utiliser tout le potentiel d' yLogger.

Je vous remercie.