Serilog Logging with ClassName, Method Name

六月ゝ 毕业季﹏ 提交于 2021-02-07 14:34:22

问题


I am using serilog and SEQ in my project Angular,web api, EF. I am new to both.

1) How can I make sure every time I write error, information, debug it should contain ClassName.Method Name. I know I have to create Enrich but not sure how to get ClassName.Method Name

for example

Class Test
{
  public void testing(){
  // logger.Error("Error ....");}
}

Now,when I see the log it should display "29/09/2012 10:00:00, Test=>testing Error ....."

In, short DateTime, ClassName , MethodName and Message


回答1:


To get the method name automatically on every logging call, you'll have to use an enricher that reflects over the call stack (which is very expensive to do) to capture the method name.

Here is an example written by @nblumhardt: https://github.com/serilog/serilog/issues/1084#issuecomment-358117004

using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using Serilog;
using Serilog.Configuration;
using Serilog.Core;
using Serilog.Events;

namespace ConsoleApp24
{
    class CallerEnricher : ILogEventEnricher
    {
        public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
        {
            var skip = 3;
            while (true)
            {
                var stack = new StackFrame(skip);
                if (!stack.HasMethod())
                {
                    logEvent.AddPropertyIfAbsent(new LogEventProperty("Caller", new ScalarValue("<unknown method>")));
                    return;
                }

                var method = stack.GetMethod();
                if (method.DeclaringType.Assembly != typeof(Log).Assembly)
                {
                    var caller = $"{method.DeclaringType.FullName}.{method.Name}({string.Join(", ", method.GetParameters().Select(pi => pi.ParameterType.FullName))})";
                    logEvent.AddPropertyIfAbsent(new LogEventProperty("Caller", new ScalarValue(caller)));
                }

                skip++;
            }
        }
    }

    static class LoggerCallerEnrichmentConfiguration
    {
        public static LoggerConfiguration WithCaller(this LoggerEnrichmentConfiguration enrichmentConfiguration)
        {
            return enrichmentConfiguration.With<CallerEnricher>();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .Enrich.WithCaller()
                .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message} (at {Caller}){NewLine}{Exception}")
                .CreateLogger();

            Log.Information("Hello, world!");

            SayGoodbye();

            Log.CloseAndFlush();
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        static void SayGoodbye()
        {
            Log.Information("Goodbye!");
        }
    }
}

Another alternative (if you only want to capture the method name in specific/more important places), is to create an extension method that you can call, which will add the method name to the logging context... E.g.

Logger.Here().Information("Hello, world!");

You can see an example of how to implement this Here method on a different question here on StackOverflow: https://stackoverflow.com/a/46905798



来源:https://stackoverflow.com/questions/52473924/serilog-logging-with-classname-method-name

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!