1

目前我有 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 的不同类中调用函数?

谢谢

4

1 回答 1

3

如果您主要对使用 NLog 包装器感兴趣,但仍然能够维护呼叫站点信息,请在此处查看我对先前问题的回答:

使用 wrapper 时 Nlog Callsite 错误

简而言之,您可以使用 NLog Log 方法并传递包装器的类型。然后,如果您使用 NLog callsite LayoutRenderer,NLog 将能够找出 callsite 信息,而无需您自己弄清楚。

因此,您的 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)的情况下,您正在做一些额外的工作。如果由于当前的日志记录级别设置,该语句实际上不会被记录,那么您仍在格式化字符串并且您正在进行两次相对昂贵的调用来获取调用点信息。

于 2013-05-06T14:07:04.847 回答