Section courante

A propos

Section administrative du site

Connexion à elmah.io depuis Serilog

Connecter Serilog à elmah.io présente plusieurs avantages, surtout si vous cherchez à combiner une gestion avancée des journaux de bord avec des fonctionnalités de surveillance d'erreurs robustes. Voici quelques raisons pour lesquelles cette intégration peut être bénéfique :

Serilog est un excellent ajout à la communauté de journal de bord .NET, décrite comme «Une bibliothèque de journal de bord pratique pour l'ère NoSQL» sur leur page de projet. Serilog fonctionne comme d'autres cadres d'application de journal de bord tels que log4net et NLog mais offre une excellente API fluide et le concept de récepteurs (un peu comme les appenders dans log4net). Les récepteurs sont supérieurs aux appenders car ils menacent les erreurs en tant qu'objets plutôt que chaînes de caractères, ce qui convient parfaitement à Elmah.io étant lui-même construit sur NoSQL. Serilog est déjà livré avec un support natif pour Elmah.io (solution commerciale basée sur l'infonuagique), ceci facilitant l'intégration à n'importe quelle application utilisant Serilog.

L'ajout de ce type de journal de bord à vos applications Windows et console est tout aussi simple. Ajoutez le Serilog.Sinks.ElmahIopackage à partir de NuGet à votre projet :

Install-Package Serilog.Sinks.ElmahIo

Pour configurer Serilog, ajoutez le code C# suivant à la méthode Application_Start dans global.asax.cs :

  1. var log = new LoggerConfiguration().WriteTo.ElmahIo(new ElmahIoSinkOptions("API_KEY", new Guid("LOG_ID"))).CreateLogger();
  2. Log.Logger = log;     

Remplacez API_KEY par votre clef API et LOG_ID par l'identificateur du journal de bord auquel vous souhaitez envoyer les messages.

Tout d'abord, nous créons un nouveau LoggerConfiguration et lui disons d'écrire sur Elmah.io. L'objet de journal de bord peut être utilisé pour enregistrer les erreurs et vous devez l'enregistrer dans votre conteneur IoC. Dans ce cas, nous n'utilisons pas IoC, c'est pourquoi l'objet journal est défini comme propriété publique statique Logger, ce qui le rend accessible de partout.

Pour enregistrer les exceptions sur Elmah.io via Serilog, utilisez la classe Log fournie par Serilog :

  1. try {
  2.  // Faire des choses pouvant provoquer une exception
  3. } catch (Exception e) {
  4.  Log.Error(e, "Le message d'erreur actuel");
  5. }

La méthode Error indique à Serilog de consigner l'erreur dans les récepteurs configurés, qui dans notre cas se connecte à Elmah.io. Note : Appelez toujours Log.CloseAndFlush(); avant la fin de votre programme.

Journal de bord des propriétés personnalisées

Serilog prend en charge le journal de bord des propriétés personnalisées de trois manières : dans le cadre du message de journal, via des enrichisseurs et en utilisant LogContext. Les trois types de propriétés sont implémentés dans le récepteur Elmah.io dans le cadre du dictionnaire de données d'Elmah.io.

L'exemple suivant montre comment consigner les trois types de propriétés :

  1. var logger = new LoggerConfiguration()
  2.              .Enrich.WithProperty("ApplicationIdentifier", "MonApp")
  3.              .Enrich.FromLogContext()
  4.              .WriteTo.ElmahIo(new ElmahIoSinkOptions("API_KEY", new Guid("LOG_ID")))
  5.              .CreateLogger();
  6. using (LogContext.PushProperty("ThreadId", Thread.CurrentThread.ManagedThreadId)) {
  7.     logger.Error("Ceci est un message avec des propriétés {Type}", "custom");
  8. }

Sous l'onglet Data sur les détails du message enregistré, les propriétés ApplicationIdentifier, ThreadId et Type peuvent être trouvées.

Serilog.Sinks.ElmahIo fournit une gamme de noms de propriétés réservées, pouvant être utilisées pour remplir les données dans les champs corrects de l'interface utilisateur Elmah.io. Supposons que vous souhaitiez remplir le champ User en utilisant uniquement la journal de bord structurée :

  1. logger.Information("{Quote} de {User}", "Test du journal de bord", "Sylvain Maltais");

Cela remplira la valeur Sylvain Maltais dans le champ User et ajoutera deux paires clef/valeur (Quote et User) à l'onglet Data sur Elmah.io. Pour une référence de tous les noms de propriétés possibles, consultez les noms de propriétés sur CreateMessage.

Crochets de message

Serilog.Sinks.ElmahIo fournit des crochets de message similaires aux intégrations avec ASP.NET et ASP.NET Core.

Note : Les crochets de message nécessitent Serilog.Sinks.ElmahIo une version 3.3.0 ou une version plus récente.

Messages de journal de bord de décoration

Pour inclure des informations supplémentaires sur les messages du journal, vous pouvez utiliser l'événement OnMessage lors de l'initialisation de la cible Elmah.io :

  1. Log.Logger = new LoggerConfiguration().WriteTo.ElmahIo(new ElmahIoSinkOptions("API_KEY", new Guid("LOG_ID"))
  2.         {
  3.             OnMessage = msg =>
  4.             {
  5.                 msg.Version = "1.0.0";
  6.             }
  7.         })
  8.         .CreateLogger();     

L'exemple ci-dessus inclut un numéro de version sur toutes les erreurs. Étant donné que le récepteur elmah.io récupère également les enrichisseurs spécifiés avec Serilog, cet exemple pourrait être implémenté en enrichissant tous les messages de journal de bord avec un champ nommé version.

Inclure le code source

Vous pouvez utiliser l'action OnMessage pour inclure le code source pour enregistrer les messages. Cela nécessitera une trace de pile dans la propriété Detail contenant les noms de fichiers et les numéros de ligne.

Il existe plusieurs façons d'inclure du code source pour enregistrer les messages. En bref, vous devrez installer le paquet Elmah.Io.Client.Extensions.SourceCode de NuGet et appeler la méthode WithSourceCodeFromPdb dans l'action OnMessage :

  1. Log.Logger = new LoggerConfiguration().WriteTo.ElmahIo(new ElmahIoSinkOptions("API_KEY", new Guid("LOG_ID"))
  2.         {
  3.             OnMessage = msg =>
  4.             {
  5.                 msg.WithSourceCodeFromPdb();
  6.             }
  7.         })
  8.         .CreateLogger();

L'inclusion du code source dans les messages du journal est disponible dans le paquet Elmah.Io.Client version 4 et ultérieur.

Gérer les erreurs

Pour gérer les erreurs se produisant lors du traitement d'un message de journal de bord, vous pouvez utiliser l'événement OnError lors de l'initialisation du récepteur elmah.io :

  1. Log.Logger = new LoggerConfiguration().WriteTo.ElmahIo(new ElmahIoSinkOptions("API_KEY", new Guid("LOG_ID"))
  2.         {
  3.             OnError = (msg, ex) =>
  4.             {
  5.                 Console.Error.WriteLine(ex.Message);
  6.             }
  7.         })
  8.         .CreateLogger();

L'exemple implémente un rappel si la connexion à elmah.io échoue. La manière dont vous choisissez de mettre en oeuvre cela dépend entièrement de votre application et de votre pile technologique.

Filtrage des erreurs

Pour ignorer des messages spécifiques en fonction de leur contenu, vous pouvez utiliser l'événement OnFilter lors de l'initialisation du récepteur elmah.io :

  1. Log.Logger = new LoggerConfiguration().WriteTo.ElmahIo(new ElmahIoSinkOptions("API_KEY", new Guid("LOG_ID"))
  2.         {
  3.             OnFilter = msg =>
  4.             {
  5.                 return msg.Title.Contains("trace");
  6.             }
  7.         })
  8.         .CreateLogger();     

L'exemple ci-dessus ignore tout message de journal contenant le mot trace dans le titre.

ASP.NET Core

Le Serilog fournit un paquet pour ASP.NET Core, acheminant les messages de journal de bord depuis l'intérieur du cadre d'application via Serilog. Il est recommandé d'utiliser ce paquet avec le récepteur elmah.io, afin de capturer les avertissements et les erreurs se produisant dans ASP.NET Core.

Pour l'utiliser, installez les paquets suivants :

Install-Package Serilog.AspNetCore
Install-Package Serilog.Sinks.ElmahIo

Configurez Serilog en utilisant la méthode UseSerilog dans le fichier Program.cs :

  1. builder.Host.UseSerilog((ctx, lc) => lc.WriteTo.ElmahIo(new ElmahIoSinkOptions("API_KEY", new Guid("LOG_ID"))
  2.     {
  3.         MinimumLogEventLevel = LogEventLevel.Information,
  4.     }));
  5. }     

Désormais, tous les avertissements, erreurs et erreurs fatales se produisant dans ASP.NET Core sont enregistrés sur elmah.io.

Une demande courante consiste à inclure toutes les informations contextuelles HTTP que vous obtenez habituellement lorsque vous utilisez un paquet tel que Elmah.Io.AspNetCore. Ils ont développé un paquet NuGet spécialisé pour inclure les cookies, les variables de serveur,... lors de la connexion via Serilog à partir d'ASP.NET Core. Pour le configurer, installez le paquet Elmah.Io.AspNetCore.Serilog de NuGet :

Install-Package Elmah.Io.AspNetCore.Serilog

Ensuite, appelez la méthode UseElmahIoSerilog dans le fichier Program.cs :

  1. // ... Logiciel passerelle de gestion des exceptions
  2. app.UseElmahIoSerilog();
  3. // ... Utilisé Mvc ....

Le logiciel passerelle utilise la fonctionnalité LogContext de Serilog pour enrichir chaque message de journal de bord avec des propriétés supplémentaires. Pour activer le contexte de journal de bord, étendez votre configuration Serilog :

  1. builder.Host.UseSerilog((ctx, lc) => lc
  2.     .WriteTo.ElmahIo(/*...*/)
  3.     .Enrich.FromLogContext() // <-- ajouter cette ligne
  4. );     

Il y a un problème avec cette approche lorsqu'un point de terminaison lève une exception non interceptée. Microsoft.Extensions.Logging enregistre toutes les exceptions non interceptées en tant qu'erreurs, mais le message LogContextest déjà affiché lors de cette opération. L'approche recommandée consiste à ignorer ces erreurs dans le récepteur elmah.io et à installer le paquet Elmah.Io.AspNetCore pour enregistrer les erreurs non détectées dans elmah.io. Le message d'erreur spécifique peut être ignoré dans le récepteur en fournissant le filtre suivant lors de l'initialisation de Serilog :

  1. .WriteTo.ElmahIo(/*...*/)
  2. {
  3.     // ...
  4.     OnFilter = msg =>
  5.     {
  6.         return
  7.             msg != null
  8.             && msg.TitleTemplate != null
  9.             && msg.TitleTemplate.Equals(
  10.                 "Une exception non gérée s'est produite lors de l'exécution de la requête.",
  11.                 StringComparison.InvariantCultureIgnoreCase);
  12.     }
  13. })

ASP.NET

Les messages enregistrés via Serilog dans une application ASP.NET WebForms, MVC ou Web API peuvent être enrichis avec une gamme d'informations contextuelles HTTP à l'aide du paquet SerilogWeb.Classic de NuGet. Commencez par installer le paquet :

Install-Package SerilogWeb.Classic

Le paquet comprend la journal de bord automatique des requêtes et des réponses HTTP ainsi que certains enrichisseurs Serilog. Sauf si vous essayez de déboguer un problème spécifique avec votre site Web, nous vous recommandons de désactiver le journal de bord HTTP, car cela produira beaucoup de messages (en fonction du trafic sur votre site Web). Le journal de bord HTTP peut être désactivée en incluant le code suivant dans le fichier Global.asax.cs :

  1. protected void Application_Start()
  2. {
  3.     SerilogWebClassic.Configure(cfg => cfg
  4.         .Disable()
  5.     );
  6.  
  7.     // ...
  8. }

Pour enrichir les messages de journal avec des informations contextuelles HTTP, vous pouvez configurer un ou plusieurs enrichisseurs au même endroit que vous configurez le récepteur elmah.io :

  1. Log.Logger = new LoggerConfiguration()
  2.     .WriteTo.ElmahIo(new ElmahIoSinkOptions("API_KEY", new Guid("LOG_ID")))
  3.     .Enrich.WithHttpRequestClientHostIP()
  4.     .Enrich.WithHttpRequestRawUrl()
  5.     .Enrich.WithHttpRequestType()
  6.     .Enrich.WithHttpRequestUrl()
  7.     .Enrich.WithHttpRequestUserAgent()
  8.     .Enrich.WithUserName(anonymousUsername:null)
  9.     .CreateLogger();

Cela remplira automatiquement les champs sur elmah.io comme l'URL, la méthode, l'adresse IP du client et UserAgent.

Configuration à l'aide de appsettings.json

Bien que Serilog fournisse une API en C# fluide, certains préfèrent configurer Serilog à l'aide d'un appsettings.jsonfichier. Pour configurer le récepteur elmah.io de cette façon, vous devrez installer le paquet Serilog.Settings.Configuration de NuGet. Configurez ensuite elmah.io dans votre fichier appsettings.json :

  1. {
  2.     // ...
  3.     "Serilog":{
  4.         "Using":[
  5.             "Serilog.Sinks.ElmahIo"
  6.         ],
  7.         "MinimumLevel": "Warning",
  8.         "WriteTo":[
  9.             {
  10.                 "Name": "ElmahIo",
  11.                 "Args":{
  12.                     "apiKey": "API_KEY",
  13.                     "logId": "LOG_ID"
  14.                 }
  15.             }
  16.         ]
  17.     }
  18. }

Note : Assurez-vous de spécifier les paramètres apiKey et logId avec le premier caractère en minuscule.

Enfin, dites à Serilog de lire la configuration à partir du fichier appsettings.json :

  1. var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
  2. var logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();     

Détails des exceptions étendus avec Serilog.Exceptions

Plus vous disposez d'informations sur une erreur, plus il est facile de découvrir ce qui n'a pas fonctionné. Le paquet Serilog.Exceptions utilise la réflexion sur une exception enregistrée pour enregistrer des informations supplémentaires en fonction du type d'exception concret. Vous pouvez installer le paquet via NuGet :

Install-Package Serilog.Exceptions

Et configurez-le en code C# :

  1. var logger = new LoggerConfiguration()
  2.     .Enrich.WithExceptionDetails()
  3.     .WriteTo.ElmahIo(/*...*/)
  4.     .CreateLogger();     

Le récepteur elmah.io récupérera automatiquement les informations supplémentaires et les affichera dans la superposition des détails étendus du message. Pour accéder à cette vue, cliquez sur une erreur dans la vue de recherche. Cliquez ensuite sur le bouton dans le coin supérieur droit pour ouvrir les détails étendus du message. Les informations enregistrées par Serilog.Exceptions sont disponibles sous l'onglet Data.

Supprimer les données sensibles

La journalisation structurée avec Serilog est un excellent moyen d'entreposer de nombreuses informations contextuelles sur un message de journal. Dans certains cas, cela peut cependant entraîner l'entreposage de données sensibles dans votre journal. Il est recommandé de supprimer toutes les données sensibles de vos messages de journal avant de l'entreposer sur elmah.io et ailleurs. Pour implémenter cela, vous pouvez utiliser l'événement OnMessage comme déjà présenté précédemment dans le document :

  1. OnMessage = msg => {
  2.     foreach (var d in msg.Data) {
  3.         if (d.Key.Equals("motdepasse")) {
  4.             d.Value = "****";
  5.         }
  6.     }
  7. }

Une alternative au remplacement manuel des valeurs sensibles consiste à utiliser un paquet de déstructuration personnalisé pour Serilog. L'exemple suivant montre comment y parvenir à l'aide du paquet Destructurama.Attributed :

Install-Package Destructurama.Attributed

Configurer la déstructuration à partir des attributs :

  1. Log.Logger = new LoggerConfiguration()
  2.     .Destructure.UsingAttributes()
  3.     .WriteTo.ElmahIo(/*...*/)
  4.     .CreateLogger();     

Assurez-vous de décorer toutes les propriétés comprenant des données sensibles avec l'attribut NotLogged :

  1. public class LoginModel {
  2.     public string Username { get; set; }
  3.  
  4.     [NotLogged]
  5.     public string Password { get; set; }
  6. }

Définir une catégorie

elmah.io fournit un champ nommé Category pour mieux regrouper les messages du journal par nom de classe, espace de noms ou similaire. La catégorie (Category) est automatiquement cartographiée au SourceContext de Serilog lors de l'utilisation de Serilog.Sinks.ElmahIo. Pour vous assurer que la catégorie est correctement renseignée, soit utilisez la méthode Forcontext :

  1. Log.ForContext<Program>().Information("Ceci est un message d'information avec contexte");
  2. Log.ForContext("The context").Information("Ceci est un autre message d'information avec contexte");     

Ou définissez une propriété SourceContext ou Category en utilisant LogContext :

  1. using (LogContext.PushProperty("SourceContext", "Le contexte"))
  2.     Log.Information("Ceci est un message d'information avec contexte");
  3.  
  4. using (LogContext.PushProperty("Category", "Le contexte"))
  5.     Log.Information("Ceci est un message d'information avec contexte");     


Dernière mise à jour : Mercredi, le 28 août 2024