add proper logger, saves to file as well

This commit is contained in:
Master
2023-10-14 19:39:26 +02:00
parent a2e27effff
commit 239c4fca32
17 changed files with 402 additions and 140 deletions

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

18
AscNet.Logging/ILogger.cs Normal file
View File

@@ -0,0 +1,18 @@
namespace AscNet.Logging
{
public interface ILogger
{
void Debug(string message, string memberName = "");
void Error(string message, Exception ex = null, string memberName = "");
void Fatal(string message, Exception ex = null, string memberName = "");
void Info(string message, string memberName = "");
void Dispose();
void Warn(string message, Exception ex = null, string memberName = "");
}
}

View File

@@ -0,0 +1,13 @@
namespace AscNet.Logging
{
public enum LogLevel : byte
{
OFF = 0,
FATAL = 8,
ERROR = 16,
WARN = 32,
INFO = 64,
DEBUG = 128,
ALL = 255
}
}

201
AscNet.Logging/Logger.cs Normal file
View File

@@ -0,0 +1,201 @@
namespace AscNet.Logging
{
public class Logger : ILogger
{
#region Members
private readonly string _logFilePath = "log.log";
private readonly string _loggerName = "DefaultLogger";
private readonly LogLevel _logLevel = LogLevel.ALL;
private readonly LogLevel _fileLogLevel = LogLevel.ALL;
private bool _disposed;
private Type _loggerType;
#endregion
#region Instantiation
public Logger(string logFilePath)
{
_logFilePath = logFilePath;
}
public Logger(string logFilePath, LogLevel logLevel) : this(logFilePath) => _logLevel = logLevel;
public Logger(Type loggerType, string logFilePath, LogLevel logLevel) : this(logFilePath, logLevel)
{
_loggerType = loggerType;
_loggerName = loggerType.Namespace.RemoveBefore('.');
}
public Logger(Type loggerType, LogLevel logLevel, LogLevel fileLogLevel)
{
_logLevel = logLevel;
_fileLogLevel = fileLogLevel;
_loggerType = loggerType;
_loggerName = loggerType.Name;
}
public Logger(Type loggerType, string loggerName, LogLevel logLevel, LogLevel fileLogLevel)
{
_logLevel = logLevel;
_fileLogLevel = fileLogLevel;
_loggerType = loggerType;
_loggerName = loggerName;
}
#endregion
#region Methods
public void Debug(string message, string memberName = "")
{
if (!string.IsNullOrWhiteSpace(message))
{
Append(message, memberName, LogLevel.DEBUG);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Error(string message, Exception ex = null, string memberName = "")
{
if (!string.IsNullOrWhiteSpace(message))
{
if (ex == null)
{
Append(message, memberName, LogLevel.ERROR);
}
else
{
Append(message + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace, memberName,
LogLevel.ERROR);
}
}
}
public void Fatal(string message, Exception ex = null, string memberName = "")
{
if (!string.IsNullOrWhiteSpace(message))
{
if (ex == null)
{
Append(message, memberName, LogLevel.FATAL);
}
else
{
Append(message + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace, memberName,
LogLevel.FATAL);
}
}
}
public void Info(string message, string memberName = "")
{
if (!string.IsNullOrWhiteSpace(message))
{
Append(message, memberName, LogLevel.INFO);
}
}
public void Trace(string message, Exception ex)
{
// TODO
throw new NotImplementedException();
}
public void Warn(string message, Exception ex = null, string memberName = "")
{
if (!string.IsNullOrWhiteSpace(message))
{
if (ex == null)
{
Append(message, memberName, LogLevel.WARN);
}
else
{
Append(message + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace, memberName,
LogLevel.WARN);
}
}
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
ThreadSafeStreamWriter.Instance.Dispose();
}
_loggerType = null;
_disposed = true;
}
}
private void Append(string message, string memberName, LogLevel logLevel)
{
if (!string.IsNullOrWhiteSpace(memberName))
{
AppendToConsole($"[{memberName}][{_loggerName}]: {message}", logLevel);
AppendToFile($"[{memberName}][{_loggerName}]: {message}", logLevel);
}
else
{
AppendToConsole($"[{_loggerName}]: {message}", logLevel);
AppendToFile($"[{_loggerName}]: {message}", logLevel);
}
}
private void AppendToConsole(string message, LogLevel logLevel)
{
if (logLevel <= _logLevel)
{
switch (logLevel)
{
case LogLevel.DEBUG:
Console.ForegroundColor = ConsoleColor.Magenta;
break;
case LogLevel.INFO:
Console.ForegroundColor = ConsoleColor.Green;
break;
case LogLevel.WARN:
Console.ForegroundColor = ConsoleColor.Yellow;
break;
case LogLevel.ERROR:
Console.ForegroundColor = ConsoleColor.Red;
break;
case LogLevel.FATAL:
Console.ForegroundColor = ConsoleColor.DarkRed;
break;
default:
throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null);
}
Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}][{logLevel}]{message}");
Console.ResetColor();
}
}
private void AppendToFile(string message, LogLevel logLevel)
{
if (logLevel <= _fileLogLevel)
{
ThreadSafeStreamWriter.Instance.AppendLine($"[{DateTime.Now:dd.MM.yyyy HH:mm:ss.fff}][{_loggerType.Namespace}][{_loggerName}][{logLevel}]{message}");
}
}
#endregion
}
}

View File

@@ -0,0 +1,23 @@
using System.Runtime.CompilerServices;
namespace AscNet.Logging
{
public static class LoggerFactory
{
public static ILogger Logger { get; set; }
public static void Debug(string message, [CallerMemberName] string memberName = "") => Logger.Debug(message, memberName);
public static void Error(string message, Exception ex = null, [CallerMemberName] string memberName = "") => Logger.Error(message, ex, memberName);
public static void Fatal(string message, Exception ex = null, [CallerMemberName] string memberName = "") => Logger.Fatal(message, ex, memberName);
public static void Info(string message, [CallerMemberName] string memberName = "") => Logger.Info(message, memberName);
public static void Warn(string message, Exception ex = null, [CallerMemberName] string memberName = "") => Logger.Warn(message, ex, memberName);
public static void Dispose() => Logger.Dispose();
public static void InitializeLogger(ILogger log) => Logger = log;
}
}

View File

@@ -0,0 +1,16 @@
namespace AscNet.Logging
{
public static class LoggingExtensions
{
public static string RemoveBefore(this string value, char character)
{
int index = value.LastIndexOf(character);
if (index > 0)
{
value = value[(index + 1)..];
}
return value;
}
}
}

View File

@@ -0,0 +1,60 @@
namespace AscNet.Logging
{
public class ThreadSafeStreamWriter : IDisposable
{
private static ThreadSafeStreamWriter? _instance;
private static StreamWriter _writer;
private bool disposedValue;
// TODO: add support for configuring
private string _logFilePath = "log.log";
private object _lock = new object();
public ThreadSafeStreamWriter()
{
_writer = new StreamWriter(_logFilePath, true);
#if !RELEASE
_writer.AutoFlush = true;
#endif
}
public static ThreadSafeStreamWriter Instance
{
get
{
return _instance ??= new ThreadSafeStreamWriter();
}
}
public void AppendLine(string line)
{
lock (_lock)
{
_writer.WriteLine(line);
}
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_writer.Flush();
_writer.Close();
_writer.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}