目前我有LogWrapper类,它初始化NLog并发送给它Info / Debug / Warning等。
所以其他类中的每个方法都从
开始LogWrapper.Informational(string.Format(" {0} starts {1}", MethodBase.GetCurrentMethod().DeclaringType.Name, MethodBase.GetCurrentMethod().Name));
在LogWrapper中时:
private static readonly Logger s_log = LogManager.GetCurrentClassLogger();
public static void Informational(string fmt, Exception exception)
{
s_log.Info("{0} {1}",fmt, exception.ToString());
}
问题是,由于调用类与访问日志包装器的日志不同,因此始终显示LogWrapper的namespace.methodname,因此会对MethodBase进行无用的调用。
有没有办法从实际访问NLog的不同类的类调用函数?
感谢
答案 0 :(得分:3)
如果您主要对使用NLog包装器感兴趣但仍能够维护呼叫站点信息,请参阅我之前对此问题的回答:
Nlog Callsite is wrong when wrapper is used
简而言之,您可以使用NLog Log方法并传递包装器的类型。然后,如果您使用NLog callsite LayoutRenderer,NLog将能够找出呼叫站点信息,而无需您自己解决。
因此,您的LogWrapper可能有这样的方法:
public static void Informational(string fmt, Exception exception)
{
LogEventInfo le = new LogEventInfo(LogLevel.Info, logger.Name, null, fmt, exception.ToString());
logger.Log(typeof(LogWrapper), le);
}
关键是将包装器的类型(typeof(LogWrapper)
)作为第一个参数传递给Logger.Log
。 NLog使用该值遍历调用堆栈,直到它将该类型视为当前MethodInfo的DeclaringType。 NLog将堆栈帧视为实际呼叫站点之前的最后一个堆栈帧,因此NLog在看到它后再上升一级。
你应该知道NLog也有一个Exception LayoutRenderer,所以你不必自己使用exception.ToString()。
虽然Daniel Hilgarth在他的评论中提到的问题有一些有趣的代码,但我认为你应该非常小心地添加一堆代码来确定NLog可以为你“免费”获取的信息。如果您只需要它用于记录目的,我建议让NLog为您解决。如果你需要其他目的,那么你可能别无选择,只能自己解决。
另外,我还建议不要使用这种风格进行日志记录调用:
LogWrapper.Informational(string.Format(" {0} starts {1}",
MethodBase.GetCurrentMethod().DeclaringType.Name, MethodBase.GetCurrentMethod().Name));
如果您的LogWrapper.Informational方法委托给NLog的Logger.Info,那么在没有打开日志记录或者日志记录级别小于Info(例如Warn,Error,Fatal)的情况下,您正在做一些额外的工作。 。如果由于当前的日志记录级别设置,该语句实际上不会被记录,您仍在格式化字符串,并且您正在进行两次相对昂贵的调用以获取调用点信息。