I can coded a simple logging class in C#, my main aim for this is to make it easily usable, fast at logging and saving, and to handle pretty much everything that errors. Overall I am just looking for advice if this is a good logging setup, and how I can improve the code inside it.
I didn't want to manually save each error when it occurs to a outside file as I feel it will take up too much time between logs and if multiple errors are being logged it could cause an issue where the file is already in use. Could anyone share their views on this?
Thanks.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sirius.Core.Logging
{
internal class LogManager : IDisposable
{
private bool _isDisposing;
private readonly List<string> _logsToSave;
private readonly string _errorLogsFile;
public LogManager()
{
_isDisposing = false;
_logsToSave = new List<string>();
_errorLogsFile = "/logs/error_logs.txt";
}
public void Information(string log)
{
Log(LogType.Information, log);
}
public void Debug(string log)
{
Log(LogType.Debug, log);
}
public void Error(string log, Exception exception = null)
{
if (exception != null)
{
HandleException(exception);
}
Log(LogType.Error, log);
}
public void Warn(string log)
{
Log(LogType.Warning, log);
}
private static void Log(LogType logType, string log)
{
var oldConsoleColor = Console.ForegroundColor;
SetColor(logType);
Console.WriteLine(DateTime.Now.ToString("yyyyMMddHHmmss") + " [" + logType.ToString() + "] " + log);
Console.ForegroundColor = oldConsoleColor;
}
private void HandleException(Exception exception)
{
_logsToSave.Add("Error occurred at " + DateTime.Now.ToString("yyyyMMddHHmmss"));
_logsToSave.Add(exception.Message);
_logsToSave.Add(exception.StackTrace);
_logsToSave.Add(string.Empty);
}
private static void SetColor(LogType logType)
{
switch (logType)
{
default:
case LogType.Information:
Console.ForegroundColor = ConsoleColor.White;
break;
case LogType.Debug:
Console.ForegroundColor = ConsoleColor.Cyan;
break;
case LogType.Error:
Console.ForegroundColor = ConsoleColor.Red;
break;
case LogType.Warning:
Console.ForegroundColor = ConsoleColor.Yellow;
break;
}
}
// Not sure if its a good idea saving on application close as delay
// Maybe add a command while program is active to save logs while running?
private void SaveLogs()
{
if (IsFileLocked(new FileInfo(_errorLogsFile))) // Check if file is in use or any other IO related issues.
{
return;
}
var stringBuilder = new StringBuilder();
foreach (var errorLog in _logsToSave)
{
stringBuilder.AppendLine(errorLog);
}
File.WriteAllText(_errorLogsFile, stringBuilder.ToString());
}
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
return true;
}
finally
{
stream?.Close();
}
return false;
}
public void Dispose()
{
if (_isDisposing)
{
return;
}
_isDisposing = true;
SaveLogs();
}
}
}