【问题标题】:Serilog not logging as expected when using TextWriter使用 TextWriter 时 Serilog 未按预期记录
【发布时间】:2019-03-18 03:53:49
【问题描述】:

我试图弄清楚如何让 Serilog 记录类名和方法/行号,就像我在 C++ 中使用 log4cxx 时看到的那样。

我尽力从我正在处理的真实代码中提取所有相关部分,并提出一个最小的示例。

我也一直在左右搜索 Serilog,但我没有找到好的文档。我想这是因为基础 serilog 之上有很多库,每个库都需要有自己的文档来告诉我如何做事。

我可以在 https://github.com/serilog/serilog/wiki/Configuration-Basics 看到有关配置的基础知识,但这似乎使用了来自单独的 Serilog 库和自定义格式化程序的 TextWriter 接收器,这两者我都不太了解。

我还可以找到使用简单配置和丰富调用来记录类和方法名称的堆栈溢出示例。

C# ASP.NET Core Serilog add class name and method to log

我无法让它记录它们。如何在仍然使用自定义格式化程序和 TextWriter 的同时记录类和方法名称或行号?

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Serilog;
using Serilog.Events;
using Serilog.Formatting;

namespace SerilogDemo {

    // Someone else made this, I just changed the name to protect the innocent
    public class SomeonesLogTextFormatter : ITextFormatter
    {
        public void Format(LogEvent logEvent, TextWriter output)
        {
            output.Write(logEvent.Level);
            output.Write(": ");
            logEvent.MessageTemplate.Render(logEvent.Properties, output);
            output.WriteLine();

            if (logEvent.Exception != null)
            {
                output.WriteLine(logEvent.Exception);
            }
        }
    }

    public class SomeClass
    {
        private Serilog.ILogger _log = Serilog.Log.ForContext<SomeClass>();

        public SomeClass()
        {
            _log.Debug("SomeClass has been instantiated");
        }

        public void Foo()
        {
            _log.Debug("Foo has been called");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .Enrich.FromLogContext()
                .WriteTo.TextWriter(textWriter: Console.Out, formatter: new SomeonesLogTextFormatter())
                .CreateLogger();

            var poop = new SomeClass();
            poop.Foo();
        }
    }
}

【问题讨论】:

    标签: c# serilog


    【解决方案1】:

    将更多信息添加到日志消息的 Serilog 方法是手动或使用为您执行此操作的 Enricher 将属性添加到 LogContext。阅读有关Serilog Enrichment 的更多信息。

    默认情况下,Serilog 不会捕获该信息,如果您为每条消息都捕获该信息,这可能会非常昂贵,但方法是使用 C#'s Caller Information feature,例如 CallerMemberNameCallerFilePath、@987654327 @。

    Here is an example,也抄在下面:

    public static class SerilogWithCallerAttributes
    {
        public static void Main()
        {
            Serilog.Log.Logger = new LoggerConfiguration()
                .WriteTo.ColoredConsole()
                .CreateLogger();
    
            GoDoSomething();
        }
    
        public static void GoDoSomething()
        {
            int score = 12;
    
            Log.Information("Player scored: {Score}", CallerInfo.Create(), score);
        }
    }
    
    public static class Log
    {
        public static void Information(string messageTemplate, CallerInfo callerInfo, params object[] propertyValues)
        {
            Serilog.Log.Logger
                .ForHere(callerInfo.CallerFilePath, callerInfo.CallerMemberName, callerInfo.CallerLineNumber)
                .Information(messageTemplate, propertyValues);
        }
    }
    
    public static class LoggerExtensions
    {
        public static ILogger ForHere(
            this ILogger logger,
            [CallerFilePath] string callerFilePath = null,
            [CallerMemberName] string callerMemberName = null,
            [CallerLineNumber] int callerLineNumber = 0)
        {
            return logger
                .ForContext("SourceFile", callerFilePath)
                .ForContext("SourceMember", callerMemberName)
                .ForContext("SourceLine", callerLineNumber);
        }
    }
    
    public class CallerInfo
    {
        public string CallerFilePath { get; private set; }
    
        public string CallerMemberName { get; private set; }
    
        public int CallerLineNumber { get; private set; }
    
        private CallerInfo(string callerFilePath, string callerMemberName, int callerLineNumber)
        {
            this.CallerFilePath = callerFilePath;
            this.CallerMemberName = callerMemberName;
            this.CallerLineNumber = callerLineNumber;
        }
    
        public static CallerInfo Create(
            [CallerFilePath] string callerFilePath = null,
            [CallerMemberName] string callerMemberName = null,
            [CallerLineNumber] int callerLineNumber = 0)
        {
            return new CallerInfo(callerFilePath, callerMemberName, callerLineNumber);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多