我正在使用NLog进行日志记录,我使用包装器来调用日志方法,我的问题是:如果我尝试打印有关调用站点的信息(${callsite}
),它会打印包装器方法而不是导致记录器记录的原始方法。
有没有办法获得调用包装器方法的原始方法?
答案 0 :(得分:20)
请参阅我对这个问题的回答:
Problem matching specific NLog logger name
我已经从这个答案复制了示例代码(对于缩写的NLog包装器)以节省一些麻烦:
class NLogLogger : ILogger
{
private NLog.Logger logger;
//The Type that is passed in is ultimately the type of the current object that
//Ninject is creating. In the case of my example, it is Class1 and Class1 is
//dependent on ILogger.
public NLogLogger(Type t)
{
logger = NLog.LogManager.GetLogger(t.FullName);
}
//Trace, Warn, Error, Fatal eliminated for brevity
public bool IsInfoEnabled
{
get { return logger.IsInfoEnabled; }
}
public bool IsDebugEnabled
{
get { return logger.IsDebugEnabled; }
}
public void Info(string format, params object [] args)
{
if (logger.IsInfoEnabled)
{
Write(LogLevel.Info, format, args);
}
}
public void Debug(string format, params object [] args)
{
if (logger.IsDebugEnabled)
{
Write(LogLevel.Debug, format, args);
}
}
private void Write(LogLevel level, string format, params object [] args)
{
LogEventInfo le = new LogEventInfo(level, logger.Name, null, format, args);
logger.Log(typeof(NLogLogger), le);
}
}
请注意,此答案是在NInject的上下文中给出的。即使您没有使用NInject,相同的原则也适用于包装NLog。关键是与NLog沟通包装器的类型。
这是关于如何正确编写NLog包装器(即维护呼叫站点信息)的示例。关键在于Write方法。注意它是如何使用NLog的Log方法的。另请注意,它将包装类的类型作为第一个参数传递。 NLog使用类型信息向上导航调用堆栈。只要它看到一个方法,其DeclaringType是传入类型(即包装器的类型),它就知道堆栈的下一帧是调用方法。
另请参阅此链接(到NLog的源代码库)以获取另外两个“扩展”Logger的示例。一个通过包装,一个通过继承:
https://github.com/jkowalski/NLog/tree/master/examples/ExtendingLoggers
我不是100%肯定,但我认为你不能简单地包装NLog并将Info,Debug,Warn等方法委托给NLog,如下所示:
class MyNLogWrapper
{
private readonly Logger logger = LogManager.GetCurrentClassLogger();
public void Info(string msg)
{
logger.Info(msg);
}
}
你需要一种方法告诉NLog包装器的类型,我认为你只能通过Logger.Log方法调用NLog(重载)来实现。
如果这不够用,请发布您的包装以获得更多帮助。
答案 1 :(得分:0)
您也可以将它添加到NLogLogger类中,并在Write方法的第一行调用它。
protected void GetCurrentClassLogger()
{
//This should take you back to the previous frame and context of the Log call
StackTrace trace = new StackTrace();
if (trace.FrameCount > 1)
{
logger = LogManager.GetLogger(trace.GetFrame(1).GetMethod().ReflectedType.FullName);
}
else //This would go back to the stated problem
{
logger = LogManager.GetCurrentClassLogger();
}
}
private void Write(LogLevel level, string format, params object[] args)
{
//added code
GetCurrentClassLogger();
LogEventInfo le = new LogEventInfo(level, logger.Name, null, format, args);
logger.Log(typeof(NLogLogger), le);
}
答案 2 :(得分:0)
专家 经过几天的艰苦努力和搜索。最后,我只使用一个简单的类构建了Nlog Wrapper,它可以保留$ {callsite}并在创建Nlog Wrapper实例时获取正确的记录器名称。我将把代码放在简单的注释之后。如您所见,我使用Stacktrace获取正确的记录器名称。使用write和writewithex注册logevnet,以便保留callsite。如果您有任何疑问,请告诉我。
public class NlogWrapper
{
private readonly NLog.Logger _logger; //NLog logger
/// <summary>
/// This is the construtor, which get the correct logger name when instance created
/// </summary>
public NlogWrapper()
{
StackTrace trace = new StackTrace();
if (trace.FrameCount > 1)
{
_logger = LogManager.GetLogger(trace.GetFrame(1).GetMethod().ReflectedType.FullName);
}
else //This would go back to the stated problem
{
_logger = LogManager.GetCurrentClassLogger();
}
}
/// <summary>
/// These two method are used to retain the ${callsite} for all the Nlog method
/// </summary>
/// <param name="level">LogLevel.</param>
/// <param name="format">Passed message.</param>
/// <param name="ex">Exception.</param>
private void Write(LogLevel level, string format, params object[] args)
{
LogEventInfo le = new LogEventInfo(level, _logger.Name, null, format, args);
_logger.Log(typeof(NlogWrapper), le);
}
private void WriteWithEx(LogLevel level, string format,Exception ex, params object[] args)
{
LogEventInfo le = new LogEventInfo(level, _logger.Name, null, format, args);
le.Exception = ex;
_logger.Log(typeof(NlogWrapper), le);
}
#region Methods
/// <summary>
/// This method writes the Debug information to trace file
/// </summary>
/// <param name="message">The message.</param>
public void Debug(String message)
{
if (!_logger.IsDebugEnabled) return;
Write(LogLevel.Debug, message);
}
public void Debug(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Debug, message, exception);
}
/// <summary>
/// This method writes the Information to trace file
/// </summary>
/// <param name="message">The message.</param>
public void Info(String message)
{
if (!_logger.IsInfoEnabled) return;
Write(LogLevel.Info, message);
}
public void Info(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Info, message, exception);
}
/// <summary>
/// This method writes the Warning information to trace file
/// </summary>
/// <param name="message">The message.</param>
public void Warn(String message)
{
if (!_logger.IsWarnEnabled) return;
Write(LogLevel.Warn, message);
}
public void Warn(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Warn, message, exception);
}
/// <summary>
/// This method writes the Error Information to trace file
/// </summary>
/// <param name="error">The error.</param>
/// <param name="exception">The exception.</param>
// public static void Error( string message)
// {
// if (!_logger.IsErrorEnabled) return;
// _logger.Error(message);
//}
public void Error(String message)
{
if (!_logger.IsWarnEnabled) return;
//_logger.Warn(message);
Write(LogLevel.Error, message);
}
public void Error(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Error, message, exception);
}
/// <summary>
/// This method writes the Fatal exception information to trace target
/// </summary>
/// <param name="message">The message.</param>
public void Fatal(String message)
{
if (!_logger.IsFatalEnabled) return;
Write(LogLevel.Fatal, message);
}
public void Fatal(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Fatal, message, exception);
}
/// <summary>
/// This method writes the trace information to trace target
/// </summary>
/// <param name="message">The message.</param>
///
public void Trace(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Trace, message, exception);
}
public void Trace(String message)
{
if (!_logger.IsTraceEnabled) return;
Write(LogLevel.Trace, message);
}
#endregion
}