web-dev-qa-db-fra.com

C # ASP.NET Core Serilog ajouter un nom de classe et une méthode pour se connecter

J'ai récemment ajouté la journalisation à mon projet ASP.Net Core. Actuellement, le journal écrit dans un fichier .txt dans ce format:

{Horodatage: aaaa-MM-jj HH: mm: ss.fff zzz} [{Niveau}] {Message} {NewLine} {Exception}

Par exemple:

2017-11-30 13: 58: 22.229 +01: 00 [Information] Élément créé dans la base de données.

C'est très bien mais je voudrais avoir le nom de la classe qui enregistre et la méthode qui est exécutée dans ce fichier .txt. Par exemple, lorsque la classe A écrit quelque chose dans la base de données à l'aide de la méthode B et l'enregistre, j'aimerais voir quelque chose comme

ClassA.MethodB: élément créé dans la base de données

Toutes les classes qui se connectent ont leur Logger injecté dans leurs constructeurs comme

public class ClassA
{
    private readonly ILogger _log;

    public ClassA(ILogger<ClassA> log){
        _log = log;
    }

    public void AddItemToDb(Item item){
        //Add item
        //On success: 
        _log.LogInfo("Added item to db.");
    }
}

J'utilise actuellement Serilog et j'utilise la configuration LoggerConfiguration suivante:

var logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    .WriteTo.RollingFile(Configuration.GetValue<string>("LogFilePath") + "-{Date}.txt", LogEventLevel.Information)
    .CreateLogger();

Comment puis-je ajouter la classe et la méthode à mes journaux?

Modifier

J'ai ajouté un modèle de sortie personnalisé à la méthode .WriteTo.Rollingfile () comme ceci:

"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}) {Message}{NewLine}{Exception}")

Ce qui a abouti à l'espace de noms plus la classe à ajouter dans le journal, seule la méthode manque maintenant

9
Jeroen

J'ai résolu ce problème en utilisant une combinaison de Jordan's answer et this answer.

J'ai changé ma configuration de journal en ajoutant le logcontext via enrichissement et j'ai ajouté la propriété 'method' à mon modèle de sortie:

var logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    .Enrich.FromLogContext()
    .WriteTo.RollingFile(Configuration.GetValue<string>("LogFilePath") + "-{Date}.txt", LogEventLevel.Information, 
        outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{Method}) {Message}{NewLine}{Exception}")
    .CreateLogger();

Enrich.FromLogContext permet de pousser des propriétés vers le modèle de sortie en utilisant la méthode LogContext.PushProperty (). Dans ce cas, pour la propriété 'method' (notez la {Method} dans le modèle de sortie).

Exemple pour les méthodes asynchrones :

using (LogContext.PushProperty("Method", new LogAsyncMethods().GetActualAsyncMethodName()))
{
    _log.LogInformation("Log message.");
}

Où GetActualAsyncMethodName () est écrit comme ceci:

public static string GetActualAsyncMethodName([CallerMemberName]string name = null) => name;

Cela fonctionne très bien pour les méthodes asynchrones .

Maintenant, pour les méthodes non asynchrones , cela fonctionne bien:

using (LogContext.PushProperty("Method", System.Reflection.MethodBase.GetCurrentMethod().Name))
{
    _log.LogInformation("Changing of customer name succeeded");
}

Maintenant, le nom de la méthode est affiché dans la journalisation. Le SourceContext ajoute l'espace de noms + la classe et en ajoutant ". {Method}" il en résultera:

Namespace.ClassName.MethodName

8
Jeroen

Dans la configuration de votre enregistreur, vous devrez enrichir avec le LogContext :

var logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    .Enrich.FromLogContext()
    .WriteTo.RollingFile(
        Configuration.GetValue<string>("LogFilePath") + "-{Date}.txt", 
        LogEventLevel.Information)
    .CreateLogger();

Mais, pour être honnête, je ne me souviens pas s'il enregistre le nom de la méthode.

0
Jordan S. Jones

L'utilisation de SeriLog avec ASP.NET Core est un peu en retard sur le .NET F/W complet si vous utilisez la fabrique de consignateurs intégrée. Vous pouvez résoudre ce problème en écrivant une série de méthodes d'extension comme celle-ci:

    public static class LoggerExtensions
    {
        public static void LogAppError<T>(this ILogger<T> logger, EventId eventId, Exception exception, string message,
            [CallerMemberName] string memberName = "",
            [CallerFilePath] string sourceFilePath = "",
            [CallerLineNumber] int sourceLineNumber = 0)
        {
            using (var prop = LogContext.PushProperty("MemberName", memberName))
            {
                LogContext.PushProperty("FilePath", sourceFilePath);
                LogContext.PushProperty("LineNumber", sourceLineNumber);
                logger.LogError(eventId, exception, message);
            }
        }
}

L'appeler à partir de votre code comme ceci:

public PeopleController(ILogger<PeopleController> logger)
{
    _logger.LogAppError("Ctor");
}

Cela suppose que vous disposez d'un modèle de sortie similaire à celui-ci:

private static string outputTemplate =
    @"[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}Message:{Message}{NewLine}in method {MemberName} at {FilePath}:{LineNumber}{NewLine}{Exception}{NewLine}";

Lorsque vous appelez dans la méthode d'extension, la méthode, le fichier et le numéro de ligne sont récupérés par les attributs respectifs. Pousser une propriété sur LogContext renvoie un IDisposable qui supprimera cette propriété et toute propriété ajoutée après. Ainsi, en encapsulant l'appel dans l'instruction using, une fois que la méthode LogError est appelée sur l'enregistreur, les propriétés sont supprimées du contexte et ne pollueront aucun autre appel de journalisation.

0
Skimedic