Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

vb.net

serilog

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

For Instance consider If I have the following;

Public Class MyClassName

  Private Function MyFunctionName() As Boolean
      Logger.Information("Hello World")
      Return True
  End Function

End Class

The desired output would be as follows;

2015-04-06 18:41:35.361 +10:00 [Information] [MyFunctionName] Hello World!

Actually the Fully Qualified Name would be good.

2015-04-06 18:41:35.361 +10:00 [Information] [MyClassName.MyFunctionName] Hello World!

It seems that "Enrichers" are only good for Static Information and won't work each time.

like image 278
Aaron Glover Avatar asked Apr 06 '15 12:04

Aaron Glover


3 Answers

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(); 
like image 131
MovGP0 Avatar answered Sep 23 '22 10:09

MovGP0


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  
like image 45
Nicholas Blumhardt Avatar answered Sep 23 '22 10:09

Nicholas Blumhardt


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

like image 45
litetex Avatar answered Sep 24 '22 10:09

litetex