Serilog - Output/Enrich All Messages with MethodName from which log entry was Called

后端 未结 5 1737
面向向阳花
面向向阳花 2020-12-02 16:24

Is there anyway to enrich all Serilog output with the Method Name.

For Instance consider If I have the following;

Public Class MyClassName

  Privat         


        
相关标签:
5条回答
  • 2020-12-02 16:29

    In outputTemplate for the Serilog , configure for logs to write Properties. Method name will be written as part of ActionName column.

    ActionName can also be configured individually (instead of all properties) in outputTemplate.

    Configuring Properties/ActionName will write the method name in Namespace.ClassName.MethodName format.

    0 讨论(0)
  • 2020-12-02 16:35

    The version on C# could be simplified. Just use AutofacSerilogIntegration:

    var path = Server.MapPath("~/");
    
            var outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext} {Message} {NewLine}{Exception}";
            Log.Logger = new LoggerConfiguration()
                        .MinimumLevel.Debug()
                        .WriteTo.File($"{path}/log/serilog-.log", LogEventLevel.Debug, outputTemplate, rollingInterval: RollingInterval.Day)
                        .CreateLogger();
    
            var builder = new ContainerBuilder();
            builder.RegisterLogger();  // from AutofacSerilogIntegration
            builder.RegisterControllers(typeof(MvcApplication).Assembly);
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    
    0 讨论(0)
  • 2020-12-02 16:41

    in case you need a version in C#:

    public static class LoggerExtensions
    {
        public static ILogger Here(this ILogger logger,
            [CallerMemberName] string memberName = "",
            [CallerFilePath] string sourceFilePath = "",
            [CallerLineNumber] int sourceLineNumber = 0) {
            return logger
                .ForContext("MemberName", memberName)
                .ForContext("FilePath", sourceFilePath)
                .ForContext("LineNumber", sourceLineNumber);
        }
    }
    

    use like this:

    // at the beginning of the class
    private static Serilog.ILogger Log => Serilog.Log.ForContext<MyClass>();
    
    // in the method
    Log.Here().Information("Hello, world!");
    

    Remember to add those properties in the message template. You can use something like this:

    var outputTemplate = "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}in method {MemberName} at {FilePath}:{LineNumber}{NewLine}{Exception}{NewLine}";
    
    Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Warning()
                .Enrich.FromLogContext()
                .WriteTo.RollingFile("log/{Date}.log", outputTemplate, LogEventLevel.Warning)
                .WriteTo.Console(LogEventLevel.Warning, outputTemplate, theme: AnsiConsoleTheme.Literate)
                .CreateLogger();
    
    0 讨论(0)
  • 2020-12-02 16:43

    It's possible to do this with an enricher by reflecting over the call stack, but very expensive to do so, so Serilog doesn't offer it.

    Instead you can use something like:

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

    and implement the Here() method as an extension method on ILogger:

    <Extension>
    Public Sub Here(ByVal logger as ILogger,
        <CallerMemberName> Optional memberName As String = Nothing)
    
        Return logger.ForContext("MemberName", memberName)
    End Sub 
    
    0 讨论(0)
  • 2020-12-02 16:50

    Based on MovGP0's answer (for C#),

    I created a solution that doesn't require the Here()-Method in every line where you want to log, by simply adding a custom Log.cs-Class into the "root namespace" of a project.

    For more info see: https://gist.github.com/litetex/b88fe0531e5acea82df1189643fb1f79

    0 讨论(0)
提交回复
热议问题