Skip to content

Instantly share code, notes, and snippets.

@davidvesely
Created May 20, 2022 08:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidvesely/9220b1cadaf3b6d3a7e41aab8cc8392c to your computer and use it in GitHub Desktop.
Save davidvesely/9220b1cadaf3b6d3a7e41aab8cc8392c to your computer and use it in GitHub Desktop.
Flawless Logger
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Blablabla
{
public static class Logger
{
// Enable to turn on the logger in %temp% folder
private const bool LogEnabled = true;
// Enable to turn on the log cleanup (delete the old log files) when the relevant applications initialize the logger
private const bool LogCleanup = true;
public static void Log(string messageTemplate, params object[] parameters)
=> Log(string.Format(messageTemplate, parameters));
public static void Log(string message)
{
if (LogEnabled)
{
Writer.Append($"{DateTime.Now.ToLongTimeString()} - #{Thread.CurrentThread.ManagedThreadId} - {message}");
}
}
public static void Stop()
{
Writer.Cancel();
MultiThreadFileWriter.Instance = null;
}
private static MultiThreadFileWriter Writer
{
get => MultiThreadFileWriter.Instance;
}
private class MultiThreadFileWriter
{
private const string Prefix = "test";
private const int DelayInMs = 500;
private readonly ConcurrentQueue<string> textToWrite = new();
private readonly CancellationTokenSource cancellationSource = new();
private MultiThreadFileWriter()
{
Task.Factory.StartNew(WriteToFile, TaskCreationOptions.LongRunning);
}
private static MultiThreadFileWriter writer;
internal static MultiThreadFileWriter Instance
{
get => writer ??= new MultiThreadFileWriter();
set => writer = value;
}
internal void Append(string line)
=> textToWrite.Enqueue(line);
private async Task WriteToFile()
{
// Initialization
var path = Path.Combine(Path.GetTempPath(), $"{Prefix}-{Process.GetCurrentProcess().ProcessName}.log");
// Clean up old log file
if (LogCleanup && File.Exists(path))
{
File.Delete(path);
}
while (true)
{
if (cancellationSource.Token.IsCancellationRequested)
{
return;
}
using var w = File.AppendText(path);
while (textToWrite.TryDequeue(out string textLine))
{
await w.WriteLineAsync(textLine);
}
await w.FlushAsync();
// Avoid eating up the CPU by waiting for next iteration
await Task.Delay(DelayInMs, cancellationSource.Token);
}
}
internal void Cancel()
{
cancellationSource.CancelAfter(DelayInMs+1);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment