using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
namespace RageCoop.Core
{
public enum LogLevel
{
Trace = 0,
Debug = 1,
Info = 2,
Warning = 3,
Error = 4
}
///
///
public class Logger : MarshalByRefObject, IDisposable
{
public delegate void FlushDelegate(LogLine line, string fomatted);
private readonly ConcurrentQueue _queuedLines = new ConcurrentQueue();
public readonly string DateTimeFormat = "HH:mm:ss";
private readonly Thread LoggerThread;
///
/// Whether to use UTC time for timestamping the log
///
public readonly bool UseUtc = false;
public bool FlushImmediately = false;
public int FlushInterval = 1000;
///
/// 0:Trace, 1:Debug, 2:Info, 3:Warning, 4:Error
///
public int LogLevel = 0;
///
/// Name of this logger
///
public string Name = "Logger";
private bool Stopping;
public List Writers = new List { new StreamWriter(Console.OpenStandardOutput()) };
internal Logger()
{
Name = Process.GetCurrentProcess().Id.ToString();
if (!FlushImmediately)
{
LoggerThread = new Thread(() =>
{
while (!Stopping)
{
Flush();
Thread.Sleep(1000);
}
Flush();
});
LoggerThread.Start();
}
}
///
/// Stop backdround thread and flush all pending messages.
///
public void Dispose()
{
Stopping = true;
LoggerThread?.Join();
}
public event FlushDelegate OnFlush;
///
///
///
public void Info(string message)
{
Enqueue(2, message);
}
///
///
///
public void Warning(string message)
{
Enqueue(3, message);
}
///
///
///
public void Error(string message)
{
Enqueue(4, message);
}
///
///
///
///
public void Error(string message, Exception error)
{
Enqueue(4, $"{message}:\n {error}");
}
///
///
///
public void Error(Exception ex)
{
Enqueue(4, ex.ToString());
}
///
///
///
public void Debug(string message)
{
Enqueue(1, message);
}
///
///
///
public void Trace(string message)
{
Enqueue(0, message);
}
public void Enqueue(int level, string message)
{
if (level < LogLevel) return;
_queuedLines.Enqueue(new LogLine
{
Message = message,
TimeStamp = UseUtc ? DateTime.UtcNow : DateTime.Now,
LogLevel = (LogLevel)level
});
if (FlushImmediately) Flush();
}
private string Format(LogLine line)
{
return string.Format("[{0}][{2}] [{3}] {1}", line.TimeStamp.ToString(DateTimeFormat), line.Message, Name,
line.LogLevel.ToString());
}
///
///
public void Flush()
{
lock (_queuedLines)
{
try
{
while (_queuedLines.TryDequeue(out var line))
{
var formatted = Format(line);
Writers.ForEach(x =>
{
x.WriteLine(formatted);
x.Flush();
});
OnFlush?.Invoke(line, formatted);
}
}
catch
{
}
}
}
public class LogLine
{
public LogLevel LogLevel;
public string Message;
public DateTime TimeStamp;
internal LogLine()
{
}
}
}
}