c# 实现一个简朴的非常日志记录(非常迭代+分片+定时清理)+AOP Rougamo全 ...

打印 上一主题 下一主题

主题 791|帖子 791|积分 2383

1. 日志目录和文件管理



  • 日志目录:日志文件存储在 ./Exceptions 目录下。
  • 日志文件定名:日志文件的定名格式为 yyyy_MM_dd.log,表现当天的日期。假如当天的日志文件大小超过 maxFileSizeBytes(3KB),则会创建新的日志文件,文件名格式为 yyyy_MM_dd_P{cnt}.log,此中 cnt 是日志文件的编号。
  • 日志文件编码:日志文件使用 UTF-8 编码。
2. 非常日志记录



  • WriteExceptionLog(Exception ex) 方法:
    该方法用于记录非常信息。首先检查日志目录是否存在,假如不存在则创建。
    获取当前日期的日志文件列表,并选择最新的日志文件(按文件名顺序)。
    假如日志文件存在且大小超过 maxFileSizeBytes,则创建一个新的日志文件,文件名中包罗 _P{cnt},此中 cnt 是文件的编号。
    将非常信息追加到日志文件中,使用 GetLogEntry(ex) 方法天生非常信息的日志条目。
    末了调用 CleanupOldLogFiles() 方法清理超过 maxLogFileAgeDays(1天)的旧日志文件。
3. 日志条目天生



  • GetLogEntry(Exception ex, int depth = 0) 方法:
    – 该方法递归地天生非常信息的日志条目。
    – 每层非常信息使用 depth 参数控制缩进,便于阅读。
    – 日志条目包括非常时间、非常信息、非常对象和调用堆栈。
    – 假如非常有嵌套的内部非常(InnerException),则递归调用 GetLogEntry 方法天生内部非常的日志条目。
4. 旧日志文件清理



  • CleanupOldLogFiles() 方法:
    – 该方法用于清理超过 maxLogFileAgeDays(1天)的旧日志文件。
    –获取日志目录中全部 .log 文件,检查文件的末了修改时间,假如超过 maxLogFileAgeDays,则删除该文件。
5. 非常处置处罚



  • 非常处置处罚:在 WriteExceptionLog(Exception ex) 方法中,全部的利用都在 lock 块中举行,确保线程安全。假如发生非常,内部非常会被捕捉但不会记录,制止日志记录自己抛出的非常导致步伐瓦解。
  1. using System.IO;
  2. using System.Text;
  3. using System.Text.RegularExpressions;
  4. using System.Windows;
  5. using System.Windows.Shapes;
  6. namespace DataParser.Helpers;
  7. public class LogHelper
  8. {
  9.     private static readonly object objException = new object();
  10.     private static readonly string logDirectory = "./Exceptions";
  11.     private static string curfileName = $"{DateTime.Now:yyyy_MM_dd}.log";
  12.     private static readonly int maxLogFileAgeDays = 1;
  13.     private static readonly long maxFileSizeBytes = 3*1024;
  14.     private static readonly Encoding encoding =Encoding.UTF8;
  15.     static int cnt= 0;
  16.     public static void WriteExceptionLog(Exception ex)
  17.     {
  18.         try
  19.         {
  20.             lock (objException)
  21.             {
  22.                 if (!Directory.Exists(logDirectory))
  23.                 {
  24.                     Directory.CreateDirectory(logDirectory);
  25.                 }
  26.                 var files = Directory.GetFiles(logDirectory, "*.log")
  27.                     .Select(x=>System.IO.Path.GetFileName(x))
  28.                     .Where(x => x.Contains($"{DateTime.Now:yyyy_MM_dd}"));
  29.                 if(files.Count()>0)
  30.                 {
  31.                     var tmp = files.OrderBy(x => x.Length);
  32.                     curfileName = tmp.Last();
  33.                     if (curfileName.Contains("_P"))
  34.                     {
  35.                         Match match = Regex.Match(curfileName, @"_P(\d+)");
  36.                         if (match.Success)
  37.                         {
  38.                             string str = match.Groups[1].Value;
  39.                             int.TryParse(str, out cnt);
  40.                         }
  41.                     }
  42.                 }
  43.                 else
  44.                 {
  45.                     curfileName = $"{DateTime.Now:yyyy_MM_dd}.log";
  46.                 }
  47.                 string fileName = System.IO.Path.Combine(logDirectory, curfileName);
  48.                 string logEntry = GetLogEntry(ex);
  49.                 if (File.Exists(fileName) && (new FileInfo(fileName).Length > maxFileSizeBytes))
  50.                 {
  51.                     cnt++;
  52.                     fileName = System.IO.Path.Combine(logDirectory, $"{DateTime.Now:yyyy_MM_dd}_P{cnt}.log");
  53.                 }
  54.                 else if(!fileName.Contains("_P"))
  55.                 {
  56.                     cnt = 0;
  57.                 }
  58.                 File.AppendAllText(fileName, logEntry, encoding);
  59.                 CleanupOldLogFiles();
  60.             }
  61.         }
  62.         catch (Exception innerEx)
  63.         {
  64.         }
  65.     }
  66.     private static string GetLogEntry(Exception ex, int depth = 0)
  67.     {
  68.         string indent = new string(' ', depth * 4);
  69.         string logEntry =
  70.             $"{indent}【异常时间】{DateTime.Now}{Environment.NewLine}" +
  71.             $"{indent}【异常信息】{ex.Message}{Environment.NewLine}" +
  72.             $"{indent}【异常对象】{ex.Source}{Environment.NewLine}" +
  73.             $"{indent}【调用堆栈】{Environment.NewLine}   {ex.StackTrace?.Trim() ?? "N/A"}{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}";
  74.         if (ex.InnerException != null)
  75.         {
  76.             logEntry += GetLogEntry(ex.InnerException, depth + 1);
  77.         }
  78.         return logEntry;
  79.     }
  80.     private static void CleanupOldLogFiles()
  81.     {
  82.         var files = Directory.GetFiles(logDirectory, "*.log")
  83.                 .Select(f => new FileInfo(f))
  84.                 .Where(f => (DateTime.Now - f.LastWriteTime).TotalDays > maxLogFileAgeDays);
  85.         foreach (var file in files)
  86.         {
  87.             File.Delete(file.FullName);
  88.         }
  89.     }
  90. }
复制代码
Rougamo 实现AOP

导包Rougamo.Fody
  1. using DataParser.Helpers;
  2. using Rougamo;
  3. using Rougamo.Context;
  4. namespace DataParser
  5. {
  6.     public class ExceptionLogAttribute : MoAttribute
  7.     {
  8.         public override void OnException(MethodContext context)
  9.         {
  10.             LogHelper.WriteExceptionLog(context.Exception);
  11.             context.HandledException(this, null);
  12.         }
  13.     }
  14. }
复制代码
  1.     public partial class MainViewModel:IRougamo<ExceptionLogAttribute>
  2.     {}
复制代码
MainViewModel 类实现了接口 IRougamo<ExceptionLogAttribute>。这意味着在这个类中,全部被 ExceptionLogAttribute 特性标记的方法或类,都会在抛出非常时自动调用 ExceptionLogAttribute 的 OnException 方法

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

泉缘泉

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表