C#ASP.NET Core Serilog添加类名和方法进行记录

问题描述 投票:4回答:3

我最近添加了日志记录到我的ASP.Net核心项目。目前,日志以这种格式写入.txt文件:

{时间戳:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message} {NewLine} {Exception}

例如:

2017-11-30 13:58:22.229 +01:00 [信息]在数据库中创建的项目。

这很好,但我想要记录的类的名称和正在执行此.txt文件的方法。例如,当A类使用方法B向数据库写入内容并记录此内容时,我希望看到类似的内容

ClassA.MethodB:在数据库中创建的项目

所有记录的类都将Logger注入到它们的构造函数中

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.");
    }
}

我目前正在使用Serilog并使用以下LoggerConfiguration:

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

如何将类和方法添加到日志中?

编辑

我将自定义的outputTemplate添加到.WriteTo.Rollingfile()方法中,如下所示:

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

这导致命名空间加上要在日志中添加的类,现在只缺少方法

c# asp.net logging asp.net-core serilog
3个回答
4
投票

我通过使用Jordan's答案和this答案的组合解决了这个问题。

我通过enrichment添加logcontext来改变我的Logger配置,并将属性'method'添加到我的outputTemplate:

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允许使用LogContext.PushProperty()方法将属性推送到outputTemplate。在本例中为'method'属性(注意outputTemplate中的{Method})。

异步方法的示例:

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

GetActualAsyncMethodName()的编写方式如下:

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

这适用于异步方法。

现在对于非异步方法,这很好用:

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

现在,方法名称正在记录中显示。 SourceContext添加了命名空间+类,通过添加“。{Method}”,它将导致:

Namespace.ClassName.MethodName


0
投票

在您的记录器配置中,您将需要enrich with the 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();

但是,说实话,我不记得它是否记录了方法名称。


0
投票

如果使用内置记录器工厂,则使用带有ASP.NET Core的SeriLog会落后于完整的.NET F / W.您可以通过编写一系列扩展方法来解决此问题:

    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);
            }
        }
}

从你这里调用代码如下:

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

这假设您有一个类似于此的输出模板:

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

当您调用扩展方法时,方法,文件和行号将由相应的属性选取。将属性推送到LogContext上会返回一个IDisposable,它将删除该属性以及之后添加的任何属性。因此,通过将调用包装在using语句中,一旦在记录器上调用LogError方法,就会从上下文中删除属性,并且不会污染任何其他日志记录调用。

© www.soinside.com 2019 - 2024. All rights reserved.