tags:

views:

310

answers:

5

Hi guys,

I'm rolling my own logger class, and want to represent the heirarchy of logs as the app moves through different phases:

log start
    loading
        loaded 400 values
    processing
         couldn't process var "x"

etc.

In C++ (yes I know), I'd use little classlets that pushed themselves on the log stack when created, and popped off when they left the scope. You could then leave functions at any point and still have consistent logging.

Obviously in C# any variable has to be new'd, so it wouldn't be deleted until the next garbage collection cycle, and if you immediately create a new classlet, you could have an out-of-sync logger.

How would people try to solve this problem in C#? I want the logger syntax to be as unobtrusive to the current function as possible, and still support functions with multiple exit points.

The only solution I can think of off the top of my head involves closeHeirarchy() calls every return statement - and you know I'm going to miss one somewhere.


Edit: I should make it clear I'm interested mainly in how you would replicate the "classlet" behaviour in c#. Is there a mechanism that provides identical behaviour?

+2  A: 

Perhaps you can have a look at this link as a starting point: http://msdn.microsoft.com/en-us/library/system.diagnostics.correlationmanager.aspx.

Fabrizio C.
+1  A: 

System.Diagnostics.Trace is worth a look. It supports things like indentation level, for example. The log4net project is also worth checking out.

Joel Coehoorn
+3  A: 

OffTopic: If you want "the logger syntax to be as unobtrusive " to the client code as possible, you might want to have a look at Aspect Oriented Programming once your logger is finished. But maybe you should take a short less painful route and use any of the great loggers available (log4Net, NLog, System.Trace or even Spring.Commonlogging).

tobsen
A: 

I had the same question, but regarding reporting progress to users. You may find the answers helpful in "making clean code while reporting progress to a user" helpful.

Gavin Miller
+3  A: 

You can get the behavior you are asking about if you use the using statement with an IDisposable-class.

Do something like this:

public class LogContext: IDisposable
{
  private readonly Logger _logger;
  private readonly string _context;

  public LogContext(Logger logger, string context){
    _logger = logger;
    _context = context;
    _logger.EnterContext(_context);
  }

  public void Dispose(){
    _logger.LeaveContext(_context);
  }
}

//...

public void Load(){
  using(new LogContext(logger, "Loading")){
    // perform load
  }
}
Rasmus Faber
That's great, thanks. The extra indentiation level is a pain, but acceptable.
tenpn