Download and view my resume (PDF)

Tuesday, February 16, 2010

C# LogManager class

Here is a simple but very useful C# class for managing logging or system outputs such as debug statements, trace printouts, errors, and so on. This class is a simple implementation for simple needs and will handle writing to a file in the temp directory of the current user (which may be the system temp directory, depending on your configuration). This class locks the block of code which writes to the file, so that multiple instances of LogManager will not run over one another.

LogManager will print only messages with a message level at least as high as the log level. The possible log levels are ALL, TRACE, DEBUG, INFORM, WARN, ERROR, FATAL, and NONE. If the log level is set to WARN, then LogManager will print messages with message levels of FATAL, ERROR, and WARN; but will not print messages with message levels of INFORM, DEBUG, or TRACE. Log levels of ALL or NONE will result in printing all messages, or no messages.

private LogManager log = new LogManager(LogManager.INFORM);
log.Error("This message *is* printed because INFORM is higher than ERROR");
log.Trace("This message is *not* printed because INFORM is lower than TRACE");


using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Runtime.CompilerServices;


///
/// LogManager is a simple output manager for C# applications.
///

public class LogManager
{
// Log levels
public static int ALL = int.MaxValue;
public static int TRACE = 32;
public static int DEBUG = 16;
public static int INFORM = 8;
public static int WARN = 4;
public static int ERROR = 2;
public static int FATAL = 1;
public static int NONE = int.MinValue;

public static int DEFAULT_LOG_LEVEL = DEBUG;
public static string DEFAULT_LOGFILE = "MyLog.txt";

// this member is used to lock certain blocks of code which must be synchronized
// across all instances of LogManager
private static object classLock = new object();

private int logLevel = DEBUG;

///
/// Creates a LogManager with LogLevel=DEFAULT_LOG_LEVEL.
///

public LogManager()
{
this.logLevel = DEFAULT_LOG_LEVEL;
}

///
/// Creates a LogManager with LogLevel=logLevel.
///

///
public LogManager(int logLevel)
{
this.logLevel = logLevel;
}

///
/// Sets or gets the output level for this LogManager. Messages will be printed
/// only if the LogLevel is greater than or equal to the message level.
///

public int LogLevel
{
get
{
return this.logLevel;
}

set
{
this.logLevel = value;
}
}

///
/// Logs msg if LogLevel is greater than or equal to TRACE.
///

/// The message to print.
public void Trace(string msg)
{
if (LogLevel >= TRACE)
{
Print(msg);
}
}

///
/// Logs msg if LogLevel is greater than or equal to DEBUG.
///

/// The message to print.
public void Debug(string msg)
{
if (LogLevel >= DEBUG)
{
Print(msg);
}
}

///
/// Logs msg if LogLevel is greater than or equal to INFORM.
///

/// The message to print.
public void Inform(string msg)
{
if (LogLevel >= INFORM)
{
Print(msg);
}
}

///
/// Logs msg if LogLevel is greater than or equal to WARN.
///

/// The message to print.
public void Warn(string msg)
{
if (LogLevel >= WARN)
{
Print(msg);
}
}

///
/// Logs msg if LogLevel is greater than or equal to ERROR.
///

/// The message to print.
public void Error(string msg)
{
if (LogLevel >= ERROR)
{
Print(msg);
}
}

///
/// Logs msg if LogLevel is greater than or equal to FATAL.
///

/// The message to print.
public void Fatal(string msg)
{
if (LogLevel >= FATAL)
{
Print(msg);
}
}

///
/// Outputs msg to the configured log file and to System.Diagnostics.Debug.
///

/// The message to print.
private void Print(string msg)
{
// The file-writing portion of this method must be locked so that two threads do not attempt
// to write to the file at the same time -- that would cause a resource-sharing exception. That
// problem was immediately evident during testing when a large minority of the tiles would fail
// to load.
lock (classLock)
{
System.IO.StreamWriter sw = System.IO.File.AppendText(GetTempPath() + DEFAULT_LOGFILE);
try
{
string logLine = System.String.Format("{0:G}: {1}", System.DateTime.Now, msg);
sw.WriteLine(logLine);
System.Diagnostics.Debug.WriteLine(logLine);
}
finally
{
sw.Close();
}
}
}

private string GetTempPath()
{
string path = System.Environment.GetEnvironmentVariable("TEMP");
if (!path.EndsWith("\\")) path += "\\";
return path;
}
}

No comments:

Post a Comment