Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
261 views
in Technique[技术] by (71.8m points)

c# - Nlog Callsite is wrong when wrapper is used

I'm using NLog for logging, I use a wrapper to call log methods, my problem is: if I try to print information about the call site (${callsite}), it prints the wrapper method and not the original method that caused the logger to log.

Is there any way to get the original method that called the wrapper method instead?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

See my answer to this question:

Problem matching specific NLog logger name

I have copied the example code (for an abbreviated NLog wrapper) from that answer here to save some trouble:

  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);
    }
  }

Note that this answer was given in the context of NInject. The same principal applies to wrapping NLog even if you are not using NInject. The key is communicating to NLog the type of your wrapper.

This is on example of how to write an NLog wrapper correctly (i.e. to maintain call site info). The key is in the Write method. Notice how it uses NLog's Log method. Notice also that is passes the type of the wrapper class as the first parameter. NLog uses the type information to navigate up the call stack. As soon as it sees a method whose DeclaringType is the passed-in type (i.e. the type of the wrapper), it knows that the next frame up the stack is the calling method.

Also see this link (to NLog's source repository) for two more examples of "extending" Logger. One by wrapping, one by inheriting:

https://github.com/jkowalski/NLog/tree/master/examples/ExtendingLoggers

I am not 100% sure, but I think that you cannot simply wrap NLog and delegate the Info, Debug, Warn, etc method to NLog like this:

class MyNLogWrapper
{
  private readonly Logger logger = LogManager.GetCurrentClassLogger();

  public void Info(string msg)
  {
    logger.Info(msg);
  }
}

You need a way to tell NLog the type of your wrapper and I think that you can only do that by calling NLog via the Logger.Log method (overloaded).

If this is not useful enough, post your wrapper for more help.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...