I have one window service. At any given time this window service runs 5-10 threads and each thread do some logging on text file. Logging can be exception or some information related to task/job. I have to make sure all the log should be in sequence with date and time. This is so important. Log file should create every day. If date change it should create new file and add log in new file. I have create one class which does this. Actually its two classes.
I used static variables for file name, file path and others, because I don't want to read configuration or create/destroy object every time(in logging process). Do you see anything which may cause an issue, or how I can improve performance?
class LoggingWorker
{
class LogDetail
{
public string Data;
public DateTime LogDate;
public LogDetail(string _Data)
{
Data = _Data;
LogDate = DateTime.Now;
}
}
#region "Private variables"
private static Object thisLock = new Object();
static string LogFileName = "MyJobs.";
static bool isVerboseMode;
static string LogFilePath;
static Thread thLogging;
static StreamWriter ofileWrite;
static Queue<LogDetail> _LogsQ;
static bool runLogging;
#endregion
/// <summary>
///
/// </summary>
static LoggingWorker()
{
//Reading from Config file
isVerboseMode = AppSettings.GetSettingBool("Logging.Verbose");
LogFilePath = AppSettings.GetSetting("Logging.Path");
_LogsQ = new Queue<LogDetail>();
if (!Directory.Exists(LogFilePath))
{
Directory.CreateDirectory(LogFilePath);
}
CreateFile();
runLogging = true;
thLogging = new Thread(StartLogging);
thLogging.Start();
}
~LoggingWorker()
{
runLogging = false;
}
private static StringBuilder GetErrorTrace(ref Exception ex)
{
StackTrace objTrace = new StackTrace(ex, true);
StringBuilder strError = new StringBuilder("");
strError.Append("Source :: " + ex.Source);
strError.Append("\r\nError :: " + DateTime.Now.ToString());
strError.Append("\r\nError Description : " + ex.Message);
strError.Append("\r\nInner Exception : " + ex.InnerException + "\r\n\r\n");
StackFrame sf;
for (int i = objTrace.FrameCount - 1; i > -1; i--)
{
sf = objTrace.GetFrame(i);
if (sf.GetFileLineNumber() < 1)
continue;
strError.Append("Method Name : " + sf.GetMethod() + "\r\n");
strError.Append("File Name : " + sf.GetFileName() + "\r\n");
strError.Append("Line Number : " + sf.GetFileLineNumber() + "\r\n\r\n");
}
return strError;
}
protected static void AddInLogQ(string msg, Exception ex)
{
msg = msg + "\t" + GetErrorTrace(ref ex).ToString();
AddInLogQ(msg);
}
protected static void AddInLogQ(Exception ex)
{
AddInLogQ(GetErrorTrace(ref ex).ToString());
}
protected static void AddInLogQ(string Data)
{
try
{
lock (thisLock)
{
_LogsQ.Enqueue(new LogDetail(Data));
}
}
catch (Exception ex)
{
EventLog.WriteEntry("AddInLogQ Failed.", ex.Message + ex.StackTrace + "\nOrignal Message:" + Data, EventLogEntryType.Error);
}
}
protected static void StartLogging()
{
LogDetail oTmp;
string sFileName;
while (runLogging)
{
if (_LogsQ.Count > 0)
{
lock (thisLock)
{
oTmp = _LogsQ.Dequeue();
}
//When Date change create new file.
sFileName = LogFilePath + "\\" + LogFileName + DateTime.Today.ToString("yyyy_MM_dd") + ".log";
//File is not exist so create new file.
if (!File.Exists(sFileName))
{
FileStream fs = File.Create(sFileName);
fs.Close();
if (ofileWrite != null)
{
ofileWrite.Close();
}
ofileWrite = new StreamWriter(sFileName, true);
}
ofileWrite.WriteLine(oTmp.LogDate.ToString("hh:mm:ss:fff tt") + " \t" + oTmp.Data);
ofileWrite.Flush();
}
else
{
Thread.Sleep(500);
}
}
if (ofileWrite != null)
{
ofileWrite.Close();
}
}
protected static void CreateFile()
{
//When Date change create new file.
string sFileName = LogFilePath + "\\" + LogFileName + DateTime.Today.ToString("yyyy_MM_dd") + ".log";
//File is not exist so create new file.
if (!File.Exists(sFileName))
{
FileStream fs = File.Create(sFileName);
fs.Close();
if (ofileWrite != null)
{
ofileWrite.Close();
}
ofileWrite = new StreamWriter(sFileName, true);
}
}
protected static void _StopLogging()
{
runLogging = false;
}
}
// This is the class which I used to Add Log from different threads/Jobs.
internal class Logging : LoggingWorker
{
public static void StopLogging()
{
_StopLogging();
}
internal static void CreateLog(string msg, Exception ex)
{
AddInLogQ(msg, ex);
}
internal static void CreateLog(Exception ex)
{
AddInLogQ(ex);
}
internal static void CreateLog(string Data)
{
AddInLogQ(Data);
}
}