AppLogger.cs 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using System;
  2. using System.Globalization;
  3. using System.Text;
  4. namespace TeamAAS
  5. {
  6. /// <summary>
  7. /// 统一的进程内日志入口(底层经 NLog 写文件,见 TeamAAS.Logging.NLogHub)。
  8. /// 日志写入 CommonPattern 解析出的公共日志文件(如 Logs/年/年-月-日.log),与插件 1/2 级日志共用;
  9. /// 单文件大小归档与保留天数自动删除均由 NLog 原生完成(配置见 PluginLogConfig)。
  10. /// 写日志失败不会反向影响业务流程,只会回退到 Debug 输出,避免异常处理路径再次抛出异常。
  11. /// </summary>
  12. public static class AppLogger
  13. {
  14. /// <summary>是否启用文件日志。</summary>
  15. public static bool Enabled { get; set; } = true;
  16. /// <summary>低于该级别的日志不会写入文件。</summary>
  17. public static LogLevel MinimumLevel { get; set; } = LogLevel.Info;
  18. public static void Info(string message, string source = null) => Write(LogLevel.Info, message, null, source);
  19. public static void Warning(string message, string source = null) => Write(LogLevel.Warning, message, null, source);
  20. public static void Error(string message, string source = null) => Write(LogLevel.Error, message, null, source);
  21. public static void Error(string message, Exception exception, string source = null) => Write(LogLevel.Error, message, exception, source);
  22. /// <summary>
  23. /// 写入一条日志。该方法刻意不向调用方抛出异常,适合在 catch/finally 中使用。
  24. /// </summary>
  25. public static void Write(LogLevel level, string message, Exception exception = null, string source = null)
  26. {
  27. if (!Enabled || level < MinimumLevel)
  28. return;
  29. var now = DateTime.Now;
  30. var safeMessage = message ?? string.Empty;
  31. var builder = new StringBuilder();
  32. builder.Append(now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture));
  33. builder.Append(" [").Append(level.ToString().ToUpperInvariant()).Append("]");
  34. builder.Append(" [T").Append(Environment.CurrentManagedThreadId).Append("]");
  35. if (!string.IsNullOrWhiteSpace(source))
  36. builder.Append(" [").Append(source.Trim()).Append("]");
  37. builder.Append(' ').Append(safeMessage.Replace(Environment.NewLine, " | "));
  38. if (exception != null)
  39. {
  40. builder.Append(" | ").Append(exception.GetType().FullName);
  41. builder.Append(": ").Append(exception.Message);
  42. if (!string.IsNullOrWhiteSpace(exception.StackTrace))
  43. builder.AppendLine().Append(exception.StackTrace);
  44. }
  45. var line = builder.ToString();
  46. try
  47. {
  48. TeamAAS.Logging.NLogHub.Apply();
  49. TeamAAS.Logging.NLogHub.Common.Log(MapLevel(level), line);
  50. }
  51. catch (Exception loggingException)
  52. {
  53. System.Diagnostics.Debug.WriteLine("[TeamAAS logging failure] " + loggingException.Message);
  54. System.Diagnostics.Debug.WriteLine(line);
  55. }
  56. // 联动实时日志控件:公共日志条目(已受 Enabled/MinimumLevel 过滤),恒显示
  57. TeamAAS.Logging.LogStream.Publish(new TeamAAS.Logging.LogEntry(
  58. now, TeamAAS.Logging.LogSource.Common, level,
  59. sourceTag: source,
  60. message: exception == null ? safeMessage : safeMessage + " | " + exception.Message));
  61. }
  62. private static NLog.LogLevel MapLevel(LogLevel level)
  63. {
  64. switch (level)
  65. {
  66. case LogLevel.Warning: return NLog.LogLevel.Warn;
  67. case LogLevel.Error: return NLog.LogLevel.Error;
  68. default: return NLog.LogLevel.Info;
  69. }
  70. }
  71. }
  72. /// <summary>
  73. /// 日志类别(精简为三档),数值越大代表严重程度越高。
  74. /// </summary>
  75. public enum LogLevel
  76. {
  77. Info = 0,
  78. Warning = 1,
  79. Error = 2
  80. }
  81. }