Extending the ILogger and LoggerBase

Mar 14, 2010 at 9:40 PM
  1. Would love to see the ILogger interface expanded to include a Func<string> delegate parameter (for the message), to defer a potentially long-running string operation - that may not be needed. This was outlined in http://www.beefycode.com/post/Extension-Methods-for-Deferred-Message-Formatting-in-Log4Net.aspx 
  2. Additionally, it would be great if also supported ILoggerFacade signature - to ease the migration from application blocks. I understand if this violates an isolation principal, I'm not sure how I feel about it myself.

<font size="2">




 <font size="2">




Log(string message<font size="2">, </font>Microsoft.Practices.Composite.Logging.Category category<font size="2">, </font>Microsoft.Practices.Composite.Logging.Priority

priority)<font size="2">

Member of





Either of these would make a great facade even better! Great job by the way - thanks! I would be happy to contribute for either effort in this regard.

Mar 19, 2010 at 3:19 PM


Thanks for the suggestion and kind words :-)

Adding delegate signatures is something we have talked about in the past, however, we wanted to keep the interface simple for the first release. I think a good approach for this might be to either expose either LoggerBase.IsLogLevelEnabled(LogLevel level), or the NLog / log4net style properties IsWarnEnabled, IsInfoEnabled, ... on the ILogger interface.

We can then add the delegate signatures via extension methods. This would keep the weight of ILogger down.

What do you think?

Regarding ILoggerFacade, I really don't know enough about the application block to know how this would work!

Regards, Colin E.

Aug 20, 2010 at 9:13 PM
Edited Aug 20, 2010 at 9:17 PM

I agree with providing the IsXXXEnabled functions for the ILogger interface.  It is certainly useful when some extra processing is required to generate some values to be logged, but that processing is required ONLY when logging.  The entire code block that performs the processing can be short-circuited by an upfront IsXXXEnabled.

void Matrix BuildTransform()
  Matrix m = DoSomeWorkToCalculateMatrix();

  logger.Info("Matrix = {0}", m);

  if (logger.IsInfoEnabled)
    IEnumerable<Point> pts = GetTestPoints();

    logger.Info("Points before transform");
    foreach (Point p in pts)
    logger.Info("Points after transform");
    foreach (Point p in pts.Transform(m))
  return m;

In this case, the purpose of the function is to compute a transformation matrix.  So, after computing it, I log the matrix.  I don't about you, but I would have a hard time telling if the matrix was really right or not.  But, I would have a pretty idea if it is right be comparing some before and after views of some known test points.  In the scheme of things, getting the test points and transforming them might be enough work that I just don't want to consider doing it unless I am logging, so I bracket the entire block with IsXXXEnabled.

I also agree that providing the delegate signatures via extension methods might be a good way to go.  The one question I would have about that is whether or not the call site information will still work correctly.  That is, will log4net and NLog be able to determine the calling method?  I know that there is an issue with this right now for log4net and that there was an issue with NLog, but a fix has been checked in.  If you essentially wrap the ILogger logging call in an extension method, does that break the call site preservation fix that has been made for NLog?  I haven't checked myself, but I have a feeling that the Type parameter that is being passed to NLog.Logger.LogEvent will cause NLog to go up the stack until the frame after the frame containing that Type.  That would be the stack frame of the extension method, not the "real" calling method.