Skip to content

Instantly share code, notes, and snippets.

/logger.cs Secret

Created May 11, 2017 14:32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WriteToFileMultiThreaded;
namespace WriteToFileMultiThreaded
{
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
/// <summary>
/// A Logging class implementing the Singleton pattern and an internal Queue to be flushed perdiodically
/// </summary>
public class LogWriter
{
private static LogWriter instance;
private static Queue<Log> logQueue;
private static string logDir = "";
private static string logFile = "WorkflowLog.txt";
private static int maxLogAge = int.Parse("5184000");
private static int queueSize = int.Parse("20");
private static DateTime LastFlushed = DateTime.Now;
/// <summary>
/// Private constructor to prevent instance creation
/// </summary>
private LogWriter() { }
/// <summary>
/// An LogWriter instance that exposes a single instance
/// </summary>
public static LogWriter Instance
{
get
{
// If the instance is null then create one and init the Queue
if (instance == null)
{
instance = new LogWriter();
logQueue = new Queue<Log>();
}
return instance;
}
}
/// <summary>
/// The single instance method that writes to the log file
/// </summary>
/// <param name="message">The message to write to the log</param>
public void WriteToLog(string message)
{
// Lock the queue while writing to prevent contention for the log file
lock (logQueue)
{
// Create the entry and push to the Queue
Log logEntry = new Log(message);
logQueue.Enqueue(logEntry);
// If we have reached the Queue Size then flush the Queue
if (logQueue.Count >= queueSize || DoPeriodicFlush())
{
FlushLog();
}
}
}
private bool DoPeriodicFlush()
{
TimeSpan logAge = DateTime.Now - LastFlushed;
if (logAge.TotalSeconds >= maxLogAge)
{
LastFlushed = DateTime.Now;
return true;
}
else
{
return false;
}
}
/// <summary>
/// Flushes the Queue to the physical log file
/// </summary>
private void FlushLog()
{
while (logQueue.Count > 0)
{
Log entry = logQueue.Dequeue();
string logPath = logDir + entry.LogDate + "_" + logFile;
// This could be optimised to prevent opening and closing the file for each write
using (FileStream fs = File.Open(logPath, FileMode.Append, FileAccess.Write))
{
using (StreamWriter log = new StreamWriter(fs))
{
log.WriteLine(string.Format("{0}\t{1}", entry.LogTime, entry.Message));
}
}
}
}
}
/// <summary>
/// A Log class to store the message and the Date and Time the log entry was created
/// </summary>
public class Log
{
public string Message { get; set; }
public string LogTime { get; set; }
public string LogDate { get; set; }
public Log(string message)
{
Message = message;
LogDate = DateTime.Now.ToString("yyyy-MM-dd");
LogTime = DateTime.Now.ToString("hh:mm:ss.fff tt");
}
}
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 20; i++)
{
string threadName = "Thread " + Convert.ToString(i + 1);
Thread t = new Thread(() => ThreadData(threadName));
t.Start();
}
}
static void ThreadData(string threadName)
{
LogWriter writer = LogWriter.Instance;
for (int i = 0; i < 1000; i++)
{
writer.WriteToLog(threadName + " Writing" + Environment.NewLine);
//System.IO.File.AppendAllText("test.txt", "Thread One Writing Line " + i + Environment.NewLine);
}
}
static void ThreadTwo()
{
LogWriter writer = LogWriter.Instance;
for (int i = 0; i < 1000; i++)
{
writer.WriteToLog("Thread Two Writing Line " + i + Environment.NewLine);
//System.IO.File.AppendAllText("test.txt", "Thread Two Writing Line " + i);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment