Microsoft.Extensions.正在记录自定义实现,如何获取调用方方法名称



我在.NET 6中,实现了(Microsoft.Extensions.Logging的(自定义ILogger<TService>

通常,当我实现记录器时,我也会获得具有[CallerMemberName]属性的调用方方法名称,例如:

public void LogInformation(string message, [CallerMemberName] string callerName = null)

我真的不明白如何用ILogger<TService>接口获得相同的[CallerMemberName]。我查了EventId,但它没有那个信息。

// Dummy class, don't try this at home!
internal class CustomLogger<TService> : ILogger<TService>
{
public IDisposable BeginScope<TState>(TState state)
=> default;
public bool IsEnabled(LogLevel logLevel)
=> true;
public void Log<TState>(
LogLevel logLevel,
EventId eventId,
TState state,
Exception exception,
Func<TState, Exception, string> formatter)
{
// TODO How to get the caller name?
string callerName = "Log";
switch (logLevel)
{
case LogLevel.Trace:
case LogLevel.Debug:
case LogLevel.Information:
case LogLevel.Warning:
Console.WriteLine(callerName + ": " + formatter(state, exception));
break;
case LogLevel.Error:
case LogLevel.Critical:
Console.WriteLine(callerName + ": " + formatter(state, exception));
break;
}
}
}

在没有reflection或其他昂贵方法的情况下,是否有大量的方法可以获得它?


为什么我需要实现自定义ILogger<T>

  1. 我使用了两个我不控制的外部库和ILogger<T>实现(所以我不能强迫它们调用扩展方法(
  2. 我需要用自己的存储空间来存储日志,在这种情况下,没有任何提供商可以满足我的需求

为什么我需要添加CallerMemberName

  • 丰富我的日志。有了这些信息,它们的可读性和信息性要高得多

我真的希望我能编辑我自己的"评论";,这是一个转化为评论的答案,但是,它来了。从我分享的答案

public void Log()
{
var stackTrace = new System.Diagnostics.StackTrace(1); // skip one frame as this is the Log function frame
var name = stackTrace.GetFrame(0).GetMethod().Name;
}

或避免反射

using (_logger.BeginScope("name of method"))
{
// log the stuff
}

原始答案的学分

您可以向静态LoggerExtensions类添加/重载日志记录函数(扩展方法(,并在日志函数中检查格式化消息的开头,split。。

public static class LoggerExtensions
{
public static void LogCritical(this ILogger logger, string? message, [CallerMemberName] string callerMemberName = "")
{
logger.LogCritical("cmn_{message}_{caller}", message, callerMemberName);
}

public static void LogDebug(this ILogger logger, string? message, [CallerMemberName] string callerMemberName = "")
{
logger.LogDebug("cmn_{message}_{caller}", message, callerMemberName);
}

Log<TState>:中

string message = formatter(state, exception);
string caller = "";

if (message.StartsWith("cmn"))
string[] messageSplit = message.Split(new char[] {'_'});
message = messageSplit[1];
caller = messageSplit[2];
}

(不幸的是,您无法直接访问Log<TState>中的TState state,因为它是内部的,因此是拆分的解决方法(

最新更新