NamedPipeLogger.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. using System.Diagnostics;
  2. using System.Diagnostics.CodeAnalysis;
  3. using System.Text;
  4. using H.Pipes;
  5. using InABox.Core;
  6. namespace InABox.Logging
  7. {
  8. public abstract class LoggerBase
  9. {
  10. public LogType[] LogTypes = { LogType.Information, LogType.Query, LogType.Update, LogType.Error, LogType.Important };
  11. protected abstract void DoSend(string message);
  12. public virtual void Send(LogType logType, string user, string message)
  13. {
  14. if (!LogTypes.Any(x => x == logType))
  15. return;
  16. var type = logType switch
  17. {
  18. LogType.Information => "INFO",
  19. LogType.Query => "READ",
  20. LogType.Update => "UPDATE",
  21. LogType.Error => "ERROR",
  22. LogType.Important => "IMPTNT",
  23. _ => "ERROR"
  24. };
  25. var msg = string.Format("{0:HH:mm:ss.fff} {1} {2} {3}",
  26. DateTime.Now,
  27. type?.PadRight(6),
  28. (user ?? "").PadRight(12),
  29. message
  30. );
  31. DoSend(msg);
  32. }
  33. public virtual void Stop() { }
  34. }
  35. public class EventLogger : LoggerBase
  36. {
  37. public Action<string>? OnLog;
  38. public EventLogger(Action<string>? onLog = null)
  39. {
  40. OnLog = onLog;
  41. }
  42. protected override void DoSend(string message)
  43. {
  44. OnLog?.Invoke(message);
  45. }
  46. }
  47. public class ConsoleLogger : LoggerBase
  48. {
  49. public ConsoleLogger()
  50. {
  51. LogTypes = new LogType[] { LogType.Information, LogType.Error };
  52. }
  53. protected override void DoSend(string message)
  54. {
  55. Console.WriteLine(message);
  56. }
  57. }
  58. public class LogFileLogger : LoggerBase
  59. {
  60. private static readonly object logfileLock = new();
  61. private string TmpFolder;
  62. private string _folder;
  63. public string Folder
  64. {
  65. get => _folder;
  66. [MemberNotNull(nameof(_folder), nameof(TmpFolder))]
  67. set
  68. {
  69. _folder = value;
  70. TmpFolder = Path.Combine(Folder, "Temp");
  71. if (Directory.Exists(TmpFolder))
  72. {
  73. Directory.CreateDirectory(TmpFolder);
  74. var files = Directory.GetFiles(TmpFolder);
  75. foreach (var file in files)
  76. File.Delete(file);
  77. }
  78. }
  79. }
  80. public LogFileLogger(string folder)
  81. {
  82. Folder = folder;
  83. }
  84. public override void Send(LogType logtype, string user, string message)
  85. {
  86. if (logtype == LogType.Update)
  87. UpdateJournal(message);
  88. else
  89. base.Send(logtype, user, message);
  90. }
  91. protected override void DoSend(string message)
  92. {
  93. if (!string.IsNullOrEmpty(Folder))
  94. {
  95. UpdateLogFile(message);
  96. }
  97. }
  98. private void UpdateLogFile(string msg)
  99. {
  100. if (!Directory.Exists(Folder)) Directory.CreateDirectory(Folder);
  101. var filename = Path.Combine(Folder, string.Format("{0:yyyy-MM-dd}.log", DateTime.Today));
  102. try
  103. {
  104. lock (logfileLock)
  105. {
  106. using (var sw = new StreamWriter(filename, true, Encoding.UTF8, 65536))
  107. {
  108. sw.WriteLine(msg);
  109. sw.Close();
  110. }
  111. }
  112. }
  113. catch (Exception e)
  114. {
  115. Console.WriteLine("*** Failed to Update Log: " + e.Message);
  116. Console.WriteLine("*** Message: " + msg);
  117. }
  118. }
  119. private void UpdateJournal(string sql)
  120. {
  121. var filename = Path.Combine(Folder, string.Format("{0:yyyy-MM-dd}.sql", DateTime.Today));
  122. try
  123. {
  124. lock (logfileLock)
  125. {
  126. using (var sw = new StreamWriter(filename, true, Encoding.UTF8, 65536))
  127. {
  128. sw.WriteLine(sql);
  129. sw.Close();
  130. }
  131. }
  132. }
  133. catch (Exception e)
  134. {
  135. Console.WriteLine("*** Failed to Update SQL Journal: " + e.Message);
  136. Console.WriteLine("*** Message: " + sql);
  137. }
  138. }
  139. }
  140. public class NamedPipeLogger : LoggerBase
  141. {
  142. private PipeServer<string> _pipe;
  143. private string _name = "";
  144. public NamedPipeLogger(string name = "")
  145. {
  146. _name = string.IsNullOrWhiteSpace(name) ? Process.GetCurrentProcess().ProcessName : name;
  147. _pipe = new PipeServer<string>(_name);
  148. _pipe.ClientConnected += _pipe_ClientConnected;
  149. _pipe.StartAsync();
  150. }
  151. private void _pipe_ClientConnected(object? sender, H.Pipes.Args.ConnectionEventArgs<string> e)
  152. {
  153. _pipe.WriteAsync("Connected to " + _name);
  154. }
  155. public override void Stop()
  156. {
  157. _pipe.StopAsync().Wait();
  158. }
  159. protected override void DoSend(string message)
  160. {
  161. if (_pipe != null)
  162. _pipe.WriteAsync(message);
  163. }
  164. }
  165. public static class MainLogger
  166. {
  167. private static List<LoggerBase> Loggers = new();
  168. public static void AddLogger(LoggerBase logger)
  169. {
  170. Loggers.Add(logger);
  171. }
  172. public static void RemoveLogger(LoggerBase logger)
  173. {
  174. Loggers.Remove(logger);
  175. }
  176. public static void Send(LogType logType, string user, string message, params object[] parameters)
  177. {
  178. foreach(var logger in Loggers)
  179. {
  180. try
  181. {
  182. if (parameters?.Any() == true)
  183. logger.Send(logType, user, String.Format(message, parameters));
  184. else
  185. logger.Send(logType, user, message);
  186. }
  187. catch (Exception e)
  188. {
  189. Logger.Send(LogType.Error, "LOGERROR",
  190. $"Exception in Logger.Send ({e.Message}) Message=[{message}] ParameterCount={parameters?.Length ?? -1}");
  191. }
  192. }
  193. }
  194. public static void Stop()
  195. {
  196. foreach (var logger in Loggers)
  197. {
  198. logger.Stop();
  199. }
  200. }
  201. }
  202. }