title: Flexible Logging interface design in C#
body: <p>I want to write my own Logging classes (in C#) which implement a standard interface, which I can call from any part of the code. </p>
  
  <p>My idea is to have multiple Log classes implement the Logger interface, each for its specific log destination, for example, a FileLogger will implement logging to a file, a TextBox logger will implement logging into a Multi Line TextBox in a Form, a DBLogger will implement logging to a database table, etc.</p>
  
  <p>Further, each logger class can have a nested logger or chained logger classes, so that a single call to Log() method from the application code can log the message in multiple destinations; example log to a file and a textbox on Form in a single call.</p>
  
  <p>The difficulty I am facing is this:</p>
  
  <p>Usually I log to a running log file (which will contain all log messages required for debugging), a review log file (which will contain only log messages to be reviewed by the user, or which require user action), a Multi Line textbox on screen (which will replicate all log messages to give a progress indication to the user), and another Multi Line textbox (which will log only messages required for user to review).</p>
  
  <p>When I call logger.Log(message), some messages may not apply to a particular log destination. For example, some message may be intended to be logged only in a running log file or progress textbox, but not in the user review textbox, and vice versa.</p>
  
  <p>Since the loggers will be chained so that a single function call can log into all required destinations, how can a particular logger identify that the log message is not intended for it and hence ignore the log message?</p>
  
  <p>My sample log interface is:</p>
  
  <pre><code>public interface Logger
  {
      public void Log(string msg);
      public void Log(string msgType, string msg);
      public void InitLogSession();
      public void EndLogSession();
      public void AddLogger(Logger chainedLogger);
      public void RemoveLogger(Logger chainedLogger);
  }
  
  public class FileLogger : Logger
  {
        //implement methods
  }
  
  public class TextBoxLogger : Logger
  {
        //implement methods
  }
  
  public class DBLogger : Logger
  {
        //implement methods
  }
  </code></pre>
  
  <p>EDIT 1:</p>
  
  <p>To be more precise, there could be 4 loggers: 2 file loggers and 2 textbox loggers. A particular message is suppose meant for 1 of the textbox loggers, and 1 of the file loggers; how should my design handle this?</p>
  
  <p>EDIT 2:
  Please do not suggest existing logging frameworks. I just want to write it on my own !</p>
  
  <p>EDIT 3:
  Ok. I have a design. Please give your feedback and probably fill the gaps. </p>
  
  <p>The revised interface:</p>
  
  <pre><code>public interface Logger
  {
      public void Log(string msg);
      public void Log(string msgType, string msg);
      public void Log(int loggerIds, string msg);
      public void Log(int loggerIds, string msgType, string msg);
      public void InitLogSession();
      public void EndLogSession();
      public int getLoggerId();
  }
  
  public enum LoggerType
  {
      File,
      TextBox
  };
  
  public class LoggerFactory
  {
      public Logger getLogger(LoggerType loggerType)
      {
  
      }
  }
  </code></pre>
  
  <p>The LoggerFactory class will be the sole way to instantiate a logger. This class will assign a unique id to each instance of a logger. This unique id will be a power of 2. Example, 1st logger will get id 1, 2nd will get id 2, 3rd will get 4, and 4th will get 8, and so on.</p>
  
  <p>The returned logger object can be typecast to specific class, and further values like filePath, textbox, etc. can be set by the caller, or else I can have multiple methods in LoggerFactory: one for each type of logger, which will accept specific parameters.</p>
  
  <p>So, suppose we have 4 loggers with ids 1,2,4,8.
  A particular message which has to be processed by the 1st and 3rd logger (i.e. logger ids 1 and 4) has to be logged using the function:</p>
  
  <pre><code>    public void Log(int loggerIds, string msg);
  </code></pre>
  
  <p>The value to be passed to loggerIds should be "0101". Each logger will check whether its logger id bit is ON. If yes, only then it will log the message.</p>
  
  <p>Now in the function signatures, I have mentioned int type, but which is the specific optimised type for performing bit manipuations and comparisons?</p>
  
  <p>In this approach, there can probably be a limit on the max no. of loggers, but that is fine with me. Please give your feedback.</p>
  
  <p>Note: Currently I am still on .NET 2.0. If possible, suggest solution within .NET 2.0, else fine, I can move to higher versions.</p>
  
  <p>CONS of this design: Each class which needs to log, needs to know about all the available loggers instantiated by the application, and accordingly set up the bit pattern. Any ideas how to have a loosely coupled design?</p>