Search code examples
c#.netscopeilogger

Implicit scopes for ILogger


I am using ConsoleLoggerProvider from Microsoft.Extensions.Logging (MEL) to write logs in .NET 6 console application.

I want my logs to include "class" and "method" records for each log entry, to know "from where" in my code the log message was written.

The only current way to do it without using third-party logging solutions like Serilog, is to use a built-in feature of "log scopes" in MEL.

So I end up writing code like:

public class MyClass {

    ILogger _logger;

    .... //Contructor, etc.

    public void MyMethod() 
    {
        using (_logger.BeginScope($"{nameof(MyClass)} => {nameof(MyMethod)}"))
            {
                ...//actual logic is here
            }
     }
}
    

I observe a concept of "ExternalScopeProviders" in the MS documentation but it's completely undocumented and example-free. Is there are more "implicit" way of having the code-structure scopes set automatically? Or are we (as .NET 6/C# users) are bound to explicit use of using (_logger.BeginScope) in our code to achieve this?


Solution

  • The more modern approach would be to use a function that auto-generates method names and location. You can create an extension method for this:

    public void Log(this ILogger logger, LogLevel logLevel, string message, [CallerMemberName]string memberName = null, [CallerFilePath]string filePath = null, [CallerLineNumber]int line = 0)
    {
       logger.Log(logLevel, $"In function {memberName} ({filePath}:{line}): {message}");
    }
    

    (and similarly for other functions of the ILogger interface)

    The compiler automatically inserts the member name (without class/namespace) in memberName, the source file in filePath and the line number in line if you do not manually fill them in at the call site. Unfortunately, there's no easy way to get the class name of the calling function this way, but it is normally identical to the file name, so this is not so big of a problem.