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

Jer*_*oen 5 c# asp.net logging serilog asp.net-core

我最近将日志记录添加到了ASP.Net Core项目中。当前,日志以以下格式写入.txt文件:

{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {消息} {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.");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

编辑

我向.WriteTo.Rollingfile()方法添加了一个自定义outputTemplate,如下所示:

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

这导致将名称空间和类添加到日志中,现在仅缺少该方法

小智 10

如果您使用内置记录器工厂,则将 SeriLog 与 ASP.NET Core 结合使用会落后于完整的 .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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

从你的代码中调用它是这样的:

public PeopleController(ILogger<PeopleController> logger)
{
    _logger.LogAppError("Ctor");
}
Run Code Online (Sandbox Code Playgroud)

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

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

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


Jer*_*oen 7

我通过结合Jordan的答案和这个答案解决了这个问题。

我通过丰富化来添加logcontext来更改Logger配置,并在outputTemplate中添加了属性“ method”:

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();
Run Code Online (Sandbox Code Playgroud)

Enrich.FromLogContext允许使用LogContext.PushProperty()方法将属性推送到outputTemplate。在这种情况下,请使用'method'属性(请注意outputTemplate中的{Method})。

异步方法示例:

using (LogContext.PushProperty("Method", new LogAsyncMethods().GetActualAsyncMethodName()))
{
    _log.LogInformation("Log message.");
}
Run Code Online (Sandbox Code Playgroud)

GetActualAsyncMethodName()的编写方式如下:

public static string GetActualAsyncMethodName([CallerMemberName]string name = null) => name;
Run Code Online (Sandbox Code Playgroud)

这对于异步方法很好。

现在,对于非异步方法,它可以正常工作:

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

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

命名空间.ClassName.MethodName

  • 请记住,在运行时通过反射获取当前方法会很昂贵;这里讨论了一种可能能够适应您的情况的有效替代方法:/sf/ask/2062960441/ -是HTH! (7认同)