using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text; using H.Formatters; using H.Pipes; using InABox.Core; namespace InABox.Logging { public abstract class LoggerBase { public LogType[] LogTypes = { LogType.Information, LogType.Query, LogType.Update, LogType.Error, LogType.Important }; protected abstract void DoSend(string message); public virtual void Send(LogType logType, string user, string message, Guid transaction) { if (!LogTypes.Any(x => x == logType)) return; var type = logType switch { LogType.Information => "INFO", LogType.Query => "READ", LogType.Update => "UPDATE", LogType.Error => "ERROR", LogType.Important => "IMPTNT", _ => "ERROR" }; var msg = string.Format("{0:HH:mm:ss.fff} {1} {2} {3} {4}", DateTime.Now, transaction, type?.PadRight(6), (user ?? "").PadRight(12), message ); DoSend(msg); } public virtual void Stop() { } } public class EventLogger : LoggerBase { public Action? OnLog; public EventLogger(Action? onLog = null) { OnLog = onLog; } protected override void DoSend(string message) { OnLog?.Invoke(message); } } public class ConsoleLogger : LoggerBase { public ConsoleLogger() { LogTypes = new LogType[] { LogType.Information, LogType.Error }; } protected override void DoSend(string message) { Console.WriteLine(message); } } public class LogFileLogger : LoggerBase { private static readonly object logfileLock = new(); private string TmpFolder; private string _folder; public string Folder { get => _folder; [MemberNotNull(nameof(_folder), nameof(TmpFolder))] set { _folder = value; TmpFolder = Path.Combine(Folder, "Temp"); if (Directory.Exists(TmpFolder)) { Directory.CreateDirectory(TmpFolder); var files = Directory.GetFiles(TmpFolder); foreach (var file in files) File.Delete(file); } } } public LogFileLogger(string folder) { Folder = folder; } public override void Send(LogType logtype, string user, string message, Guid transaction) { if (logtype == LogType.Update) UpdateJournal(message); else base.Send(logtype, user, message, transaction); } protected override void DoSend(string message) { if (!string.IsNullOrEmpty(Folder)) { UpdateLogFile(message); } } private void UpdateLogFile(string msg) { if (!Directory.Exists(Folder)) Directory.CreateDirectory(Folder); var filename = Path.Combine(Folder, string.Format("{0:yyyy-MM-dd}.log", DateTime.Today)); try { lock (logfileLock) { using (var sw = new StreamWriter(filename, true, Encoding.UTF8, 65536)) { sw.WriteLine(msg); sw.Close(); } } } catch (Exception e) { Console.WriteLine("*** Failed to Update Log: " + e.Message); Console.WriteLine("*** Message: " + msg); } } private void UpdateJournal(string sql) { var filename = Path.Combine(Folder, string.Format("{0:yyyy-MM-dd}.sql", DateTime.Today)); try { lock (logfileLock) { using (var sw = new StreamWriter(filename, true, Encoding.UTF8, 65536)) { sw.WriteLine(sql); sw.Close(); } } } catch (Exception e) { Console.WriteLine("*** Failed to Update SQL Journal: " + e.Message); Console.WriteLine("*** Message: " + sql); } } } public class NamedPipeLogger : LoggerBase { private PipeServer _pipe; private string _name = ""; public NamedPipeLogger(string name = "") { _name = string.IsNullOrWhiteSpace(name) ? Process.GetCurrentProcess().ProcessName : name; _pipe = new PipeServer(_name, formatter:new BinaryFormatter()); _pipe.ClientConnected += _pipe_ClientConnected; _pipe.StartAsync(); } private void _pipe_ClientConnected(object? sender, H.Pipes.Args.ConnectionEventArgs e) { _pipe.WriteAsync("Connected to " + _name); } public override void Stop() { _pipe.StopAsync().Wait(); } protected override void DoSend(string message) { if (_pipe != null) _pipe.WriteAsync(message); } } public static class MainLogger { private static List Loggers = new(); public static void AddLogger(LoggerBase logger) { Loggers.Add(logger); } public static void RemoveLogger(LoggerBase logger) { Loggers.Remove(logger); } public static void Send(LogType logType, string user, string message, Guid transaction) { foreach(var logger in Loggers) { try { logger.Send(logType, user, message, transaction); } catch (Exception e) { Logger.Send(LogType.Error, "LOGERROR", $"Exception in Logger.Send ({e.Message}) Message=[{message}]"); } } } public static void Stop() { foreach (var logger in Loggers) { logger.Stop(); } } } }