1

I am experimenting with Windsor Logging Facility as a wrapper to NLog. Everything seems to be working fine except the callsite info is emitting the wrapper class and method names instead of the actual caller information. From a basic search this sounded like an obvious thing, but I could not find a solution to this. Any thoughts?

I added the facility to the container:

   container.AddFacility<LoggingFacility>(f => f.UseNLog());

In my class I have the public property and I'm instantiating the class using the container.

    private ILogger logger = NullLogger.Instance;
    public ILogger Logger
    {
        get
        {
            return logger;
        }
        set
        {
            logger = value;
        }
    }

And my NLog.config is configured to emit the callsite info:

      ${callsite: className=true: fileName=true: includeSourcePath=true: methodName=true}
user1178376
  • 928
  • 2
  • 10
  • 24

1 Answers1

1

It looks to me like the Castle NLogLogger wrapper that wraps the NLog Logger object is not implemented such the call site information is retained. See this link into the Castle repository for the implementation of the wrapper.

For completeness, here is an abbreviated example of the Castle implementation:

public class NLogLogger : ILogger
{
  public NLogLogger(Logger logger, NLogFactory factory)
  {
    Logger = logger;
    Factory = factory;
  }

  internal NLogLogger() {}

  public bool IsDebugEnabled
  {
    get { return Logger.IsDebugEnabled; }
  }
  public void Debug(string message)
  {
    Logger.Debug(message);
  }
}

The key problem is that the "Debug" method (all the rest of the logging methods) uses the corresponding methods on the NLog Logger object. The logging methods on the NLog Logger use the calling function/method as the call site (that is not 100% correct, but it is effectively what happens in this case). So, in the case of this wrapper, the call site will be the Castle NLog wrapper implementation. One correct way to write the wrapper such that call site is preserved is the use the Log method on the NLog Logger, passing the Type of the wrapper as the first parameter. NLog will go up the stack until the Type of the MethodInfo is the same as the Type passed into the Log method. The next method up the stack will be the call site.

In order to retain the call site information correctly, the Debug method should look something like this:

public void Debug(string message)
{
  LogEventInfo logEvent = new LogEventInfo(LogLevel.Debug, Logger.Name, message);
  Logger.Log(typeof(NLogLogger), logEvent);
}

See these links to answers that I have posted in the past about correctly wrapping NLog's Logger such that call site information is retained:

How to retain callsite information when wrapping NLog

Nlog Callsite is wrong when wrapper is used

See also this link to NLog's source repository for some examples of how to extend NLog's Logger.

Community
  • 1
  • 1
wageoghe
  • 27,390
  • 13
  • 88
  • 116
  • Thanks, I just cloned the Core solution, made changes as you said above and it worked like a charm. Note that you just need to build Castle.Services.Logging.NLogIntegration.dll and copy overwrite existing assembly from the NuGet package (Castle.Core NLog Integration 3.0). – Tien Do Mar 30 '12 at 10:57
  • @Tiendq did you pull request it? – Krzysztof Kozmic Jun 30 '12 at 05:53
  • @KrzysztofKoźmic Sorry, I'm not sure I understood "pull request it". I just got a readonly copy and modified necessary file and rebuilt it for my project. – Tien Do Jul 02 '12 at 03:37
  • @Tiendq I meant this: https://help.github.com/articles/using-pull-requests But I guess what you did will have to suffice. Some tests would help too :) – Krzysztof Kozmic Jul 06 '12 at 22:06