diff --git a/Logging/FileLogger.cs b/Logging/FileLogger.cs
new file mode 100644
index 0000000..da0284e
--- /dev/null
+++ b/Logging/FileLogger.cs
@@ -0,0 +1,19 @@
+using System.Text;
+using System.Text.Json.Serialization;
+
+namespace Logging;
+
+public class FileLogger : LoggerBase
+{
+ private string logFilePath { get; }
+
+ public FileLogger(string logFilePath, TextWriter? stdOut, Encoding? encoding = null) : base (stdOut, encoding)
+ {
+ this.logFilePath = logFilePath;
+ }
+
+ protected override void Write(LogMessage logMessage)
+ {
+ File.AppendAllText(logFilePath, logMessage.ToString());
+ }
+}
\ No newline at end of file
diff --git a/Logging/FormattedConsoleLogger.cs b/Logging/FormattedConsoleLogger.cs
new file mode 100644
index 0000000..a3c6467
--- /dev/null
+++ b/Logging/FormattedConsoleLogger.cs
@@ -0,0 +1,17 @@
+using System.Text;
+
+namespace Logging;
+
+public class FormattedConsoleLogger : LoggerBase
+{
+
+ public FormattedConsoleLogger(TextWriter? stdOut, Encoding? encoding = null) : base(stdOut, encoding)
+ {
+
+ }
+
+ protected override void Write(LogMessage message)
+ {
+ //Nothing to do yet
+ }
+}
\ No newline at end of file
diff --git a/Logging/Logger.cs b/Logging/Logger.cs
new file mode 100644
index 0000000..96e2ab3
--- /dev/null
+++ b/Logging/Logger.cs
@@ -0,0 +1,54 @@
+using System.Net.Mime;
+using System.Text;
+
+namespace Logging;
+
+public class Logger : TextWriter
+{
+ public override Encoding Encoding { get; }
+ public enum LoggerType
+ {
+ FileLogger,
+ ConsoleLogger,
+ MemoryLogger
+ }
+
+ private FileLogger? _fileLogger;
+ private FormattedConsoleLogger? _formattedConsoleLogger;
+ private MemoryLogger? _memoryLogger;
+ private TextWriter? stdOut;
+
+ public Logger(LoggerType[] enabledLoggers, TextWriter? stdOut, Encoding? encoding, string? logFilePath)
+ {
+ this.Encoding = encoding ?? Encoding.ASCII;
+ this.stdOut = stdOut ?? null;
+ if (enabledLoggers.Contains(LoggerType.FileLogger) && logFilePath is not null)
+ _fileLogger = new FileLogger(logFilePath, null, encoding);
+ else
+ {
+ _fileLogger = null;
+ throw new ArgumentException($"logFilePath can not be null for LoggerType {LoggerType.FileLogger}");
+ }
+ _formattedConsoleLogger = enabledLoggers.Contains(LoggerType.ConsoleLogger) ? new FormattedConsoleLogger(null, encoding) : null;
+ _memoryLogger = enabledLoggers.Contains(LoggerType.MemoryLogger) ? new MemoryLogger(null, encoding) : null;
+ }
+
+ public void WriteLine(object caller, string? value)
+ {
+ value = value is null ? Environment.NewLine : string.Concat(value, Environment.NewLine);
+
+ Write(caller, value);
+ }
+
+ public void Write(object caller, string? value)
+ {
+ if (value is null)
+ return;
+
+ _fileLogger?.Write(caller, value);
+ _memoryLogger?.Write(caller, value);
+ _formattedConsoleLogger?.Write(caller, value);
+
+ stdOut?.Write(value);
+ }
+}
\ No newline at end of file
diff --git a/Logging/LoggerBase.cs b/Logging/LoggerBase.cs
new file mode 100644
index 0000000..e800791
--- /dev/null
+++ b/Logging/LoggerBase.cs
@@ -0,0 +1,59 @@
+using System.Text;
+
+namespace Logging;
+
+public abstract class LoggerBase : TextWriter
+{
+ public override Encoding Encoding { get; }
+ private TextWriter? stdOut { get; }
+
+ public LoggerBase(TextWriter? stdOut, Encoding? encoding = null)
+ {
+ this.Encoding = encoding ?? Encoding.ASCII;
+ this.stdOut = stdOut;
+ }
+
+ public void WriteLine(object caller, string? value)
+ {
+ value = value is null ? Environment.NewLine : string.Join(value, Environment.NewLine);
+
+ LogMessage message = new LogMessage(DateTime.Now, caller, value);
+
+ Write(message);
+ }
+
+ public void Write(object caller, string? value)
+ {
+ if (value is null)
+ return;
+
+ LogMessage message = new LogMessage(DateTime.Now, caller, value);
+
+ stdOut?.Write(message.ToString());
+
+ Write(message);
+ }
+
+ protected abstract void Write(LogMessage message);
+
+ public class LogMessage
+ {
+ public DateTime logTime { get; }
+ public Type caller { get; }
+ public string value { get; }
+
+ public LogMessage(DateTime now, object caller, string value)
+ {
+ this.logTime = now;
+ this.caller = caller.GetType();
+ this.value = value;
+ }
+
+ public override string ToString()
+ {
+ string dateTimeString = $"{logTime.ToShortDateString()} {logTime.ToShortTimeString()}";
+ string callerString = caller.ToString();
+ return $"[{dateTimeString}] {callerString,-15} | {value}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Logging/Logging.csproj b/Logging/Logging.csproj
new file mode 100644
index 0000000..6836c68
--- /dev/null
+++ b/Logging/Logging.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
diff --git a/Logging/MemoryLogger.cs b/Logging/MemoryLogger.cs
new file mode 100644
index 0000000..bc22579
--- /dev/null
+++ b/Logging/MemoryLogger.cs
@@ -0,0 +1,42 @@
+using System.Text;
+
+namespace Logging;
+
+public class MemoryLogger : LoggerBase
+{
+ private SortedList logMessages = new();
+
+ public MemoryLogger(TextWriter? stdOut, Encoding? encoding = null) : base(stdOut, encoding)
+ {
+
+ }
+
+ protected override void Write(LogMessage value)
+ {
+ logMessages.Add(value.logTime, value);
+ }
+
+ public string[] GetLogMessage()
+ {
+ string[] ret = new string[logMessages.Count];
+ for (int logMessageIndex = 0; logMessageIndex < ret.Length; logMessageIndex++)
+ {
+ DateTime logTime = logMessages.GetValueAtIndex(logMessageIndex).logTime;
+ string dateTimeString = $"{logTime.ToShortDateString()} {logTime.ToShortTimeString()}";
+ string callerString = logMessages.GetValueAtIndex(logMessageIndex).caller.ToString();
+ string value = $"[{dateTimeString}] {callerString} | {logMessages.GetValueAtIndex(logMessageIndex).value}";
+ ret[logMessageIndex] = value;
+ }
+
+ return ret;
+ }
+
+ public string[] Tail(uint length)
+ {
+ string[] ret = new string[length];
+ for (int logMessageIndex = logMessages.Count - 1; logMessageIndex > logMessageIndex - length; logMessageIndex--)
+ ret[logMessageIndex] = logMessages.GetValueAtIndex(logMessageIndex).ToString();
+
+ return ret.Reverse().ToArray();
+ }
+}
\ No newline at end of file
diff --git a/Tranga.sln b/Tranga.sln
index 055c08f..f11d582 100644
--- a/Tranga.sln
+++ b/Tranga.sln
@@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tranga-CLI", "Tranga-CLI\Tr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tranga-API", "Tranga-API\Tranga-API.csproj", "{6284C936-4E90-486B-BC46-0AFAD85AD8EE}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logging", "Logging\Logging.csproj", "{415BE889-BB7D-426F-976F-8D977876A462}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -24,5 +26,9 @@ Global
{6284C936-4E90-486B-BC46-0AFAD85AD8EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6284C936-4E90-486B-BC46-0AFAD85AD8EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6284C936-4E90-486B-BC46-0AFAD85AD8EE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {415BE889-BB7D-426F-976F-8D977876A462}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {415BE889-BB7D-426F-976F-8D977876A462}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {415BE889-BB7D-426F-976F-8D977876A462}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {415BE889-BB7D-426F-976F-8D977876A462}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/Tranga/Tranga.csproj b/Tranga/Tranga.csproj
index 076e1ee..6ddc3bb 100644
--- a/Tranga/Tranga.csproj
+++ b/Tranga/Tranga.csproj
@@ -10,4 +10,8 @@
+
+
+
+