c# 实现一个简单的异常日志记录(异常迭代+分片+定时清理)+AOP Rougamo全局注入
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 块中进行,确保线程安全。如果发生异常,内部异常会被捕获但不会记录,避免日志记录本身抛出的异常导致程序崩溃。
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Shapes;namespace DataParser.Helpers;public class LogHelper
{private static readonly object objException = new object();private static readonly string logDirectory = "./Exceptions";private static string curfileName = $"{DateTime.Now:yyyy_MM_dd}.log";private static readonly int maxLogFileAgeDays = 1;private static readonly long maxFileSizeBytes = 3*1024;private static readonly Encoding encoding =Encoding.UTF8;static int cnt= 0;public static void WriteExceptionLog(Exception ex){try{lock (objException){if (!Directory.Exists(logDirectory)){Directory.CreateDirectory(logDirectory);}var files = Directory.GetFiles(logDirectory, "*.log").Select(x=>System.IO.Path.GetFileName(x)).Where(x => x.Contains($"{DateTime.Now:yyyy_MM_dd}"));if(files.Count()>0){var tmp = files.OrderBy(x => x.Length);curfileName = tmp.Last();if (curfileName.Contains("_P")){Match match = Regex.Match(curfileName, @"_P(\d+)");if (match.Success) {string str = match.Groups[1].Value;int.TryParse(str, out cnt);}}}else{curfileName = $"{DateTime.Now:yyyy_MM_dd}.log";}string fileName = System.IO.Path.Combine(logDirectory, curfileName);string logEntry = GetLogEntry(ex);if (File.Exists(fileName) && (new FileInfo(fileName).Length > maxFileSizeBytes)){cnt++;fileName = System.IO.Path.Combine(logDirectory, $"{DateTime.Now:yyyy_MM_dd}_P{cnt}.log");}else if(!fileName.Contains("_P")){cnt = 0;}File.AppendAllText(fileName, logEntry, encoding);CleanupOldLogFiles();}}catch (Exception innerEx){}}private static string GetLogEntry(Exception ex, int depth = 0){string indent = new string(' ', depth * 4);string logEntry =$"{indent}【异常时间】{DateTime.Now}{Environment.NewLine}" +$"{indent}【异常信息】{ex.Message}{Environment.NewLine}" +$"{indent}【异常对象】{ex.Source}{Environment.NewLine}" +$"{indent}【调用堆栈】{Environment.NewLine} {ex.StackTrace?.Trim() ?? "N/A"}{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}";if (ex.InnerException != null){logEntry += GetLogEntry(ex.InnerException, depth + 1);}return logEntry;}private static void CleanupOldLogFiles(){var files = Directory.GetFiles(logDirectory, "*.log").Select(f => new FileInfo(f)).Where(f => (DateTime.Now - f.LastWriteTime).TotalDays > maxLogFileAgeDays);foreach (var file in files){File.Delete(file.FullName);}}
}
Rougamo 实现AOP
导包Rougamo.Fody
using DataParser.Helpers;
using Rougamo;
using Rougamo.Context;
namespace DataParser
{public class ExceptionLogAttribute : MoAttribute{public override void OnException(MethodContext context){LogHelper.WriteExceptionLog(context.Exception);context.HandledException(this, null);}}
}
public partial class MainViewModel:IRougamo<ExceptionLogAttribute>{}
MainViewModel
类实现了接口 IRougamo<ExceptionLogAttribute>
。这意味着在这个类中,所有被 ExceptionLogAttribute
特性标记的方法或类,都会在抛出异常时自动调用 ExceptionLogAttribute
的 OnException
方法
相关文章:
c# 实现一个简单的异常日志记录(异常迭代+分片+定时清理)+AOP Rougamo全局注入
1. 日志目录和文件管理 日志目录:日志文件存储在 ./Exceptions 目录下。日志文件命名:日志文件的命名格式为 yyyy_MM_dd.log,表示当天的日期。如果当天的日志文件大小超过 maxFileSizeBytes(3KB),则会创建…...

webrtc学习----前端推流拉流,局域网socket版,一对多
提示:局域网socket版,一对多 文章目录 [TOC](文章目录) 前言一、教程二、webrtc工作流程三、推流端四、拉流五、socket服务六、效果七、备注总结 前言 WebRTC(Web Real-Time Communication)是一种实时通讯技术,允许网…...

美国加州房价数据分析01
1.项目简介 本数据分析项目目的是分析美国加州房价数据,预测房价中值。 环境要求: ancondajupyter notebookpython3.10.10 虚拟环境: pandas 2.1.1 numpy 1.26.1 matplotlib 3.8.0 scikit-learn1.3.1 2. 导入并探索数据集 通用的数据分析…...

用Python开启人工智能之旅(四)深度学习的框架和使用方法
第四部分:深度学习的框架和使用方法 用Python开启人工智能之旅(一)Python简介与安装 用Python开启人工智能之旅(二)Python基础 用Python开启人工智能之旅(三)常用的机器学习算法与实现 用Pyt…...

两分钟解决:vscode卡在设置SSH主机,VS Code-正在本地初始化VSCode服务器
问题原因 remote-ssh还是有一些bug的,在跟新之后可能会一直加载初始化SSH主机解决方案 1.打开终端2.登录链接vscode的账号,到家目录下3.找到 .vscode-server文件,删掉这个文件4.重启 vscode 就没问题了...
信号仿真高级工程师面试题
信号仿真高级工程师面试题可能涵盖多个方面,旨在全面评估应聘者的专业知识、技能水平、实践经验和问题解决能力。以下是一些可能的面试题及其简要解析: 一、专业知识与技能 描述你对信号仿真的理解 考察点:对信号仿真基本概念、原理及应用的掌握程度。参考答案:信号仿真是…...
循环和迭代
从更高层次的思维角度来看迭代和循环的区别: 哲学层面: 迭代体现了"螺旋上升"的发展理念,每次迭代都在前一次的基础上有所提升和改进 循环体现了"周而复始"的概念,强调重复相同的过程 思维方式:…...
一个简单封装的的nodejs缓存对象
我们在日常编码中,经常会用到缓存,而一个有效的缓存管理,也是大家必不可少的工具。而nodejs没有内置专用的缓存对象,并且由于js的作用域链的原因,很多变量使用起来容易出错,如果用一个通用的缓存管理起来&a…...
【Rust自学】5.3. struct的方法(Method)
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 5.3.1. 什么是方法(Method) 方法和函数类似,也是用fn关键字进行声明,方法也有名称,也有参数ÿ…...
ChatGPT之父:奥尔特曼
奥尔特曼 阿尔特曼一般指萨姆奥尔特曼,他是OpenAI的联合创始人兼首席执行官,被称为“ChatGPT之父”.以下是其具体介绍: 个人经历 1985年4月22日出生于美国芝加哥,8岁学会编程,9岁拥有电脑,对信息技术和互联网产生兴趣.高中就读于约翰巴勒斯中学,后进入斯坦福大学主修计…...

如何在谷歌浏览器中设置桌面快捷方式
在日常使用电脑时,反复在浏览器中输入经常访问的网址不仅耗时,而且降低了工作效率。为了解决这一问题,我们可以通过在主屏幕上创建谷歌浏览器的快捷方式来简化操作。本文将详细介绍如何在Windows和Mac系统中实现这一功能。 一、步骤概述 1. …...
systemverilog中的priority if
1 基本概念 在 SystemVerilog 中,priority - if是一种条件判断结构。它和普通的if - else语句类似,但在条件评估和错误检查方面有自己的特点,主要用于按顺序评估多个条件,并且对不符合预期的情况进行报错。报错如下两点 当所有条件…...

图像处理-Ch2-空间域的图像增强
Ch2 空间域的图像增强 文章目录 Ch2 空间域的图像增强Background灰度变换函数(Gray-level Transformation)对数变换(Logarithmic)幂律变换(Power-Law)分段线性变换函数(Piecewise-Linear)对比度拉伸(Contrast-Stretching)灰度级分层(Gray-level Slicing) 直方图处理(Histogram …...
css 编写注意-1-命名约定
编写按照可维护性、性能和可读性规则: 1.代码组织与结构 层次清晰:使用模块化的结构,将样式分块组织。命名规范:采用统一的命名规则(如 BEM、SMACSS)以增强可读性。 /* BEM …...
虚幻引擎反射机制
在虚幻引擎中,反射系统是一种强大的机制,它允许开发者和引擎本身在运行时获取并操作类、对象、属性和方法的元信息。这个系统是基于UObject(Unreal Engine中所有支持反射的对象的基类)构建的,为游戏开发提供了极大的灵…...
Knife4j Swagger
1. 依赖 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version></dependency>2. 配置 第二步配置完成就可以访问:http://localhost…...

Xcode 16 编译弹窗问题、编译通过无法,编译通过打包等问题汇总
问题1:打包的过程中不断提示 :codesign 想要访问你的钥匙串中的密钥“develop 或者distribution 证书” 解决:打开钥匙串,点击证书---显示简介---信任----改为始终信任 (记住 :不能只修改钥匙的显示简介的…...
卷积神经网络入门指南:从原理到实践
目录 1 CNN的发展历史 2 CNN的基本原理 3 CNN核心组件 3.1 卷积操作基础 3.2 卷积层详解 3.3 高级卷积操作 3.3.1 分组卷积(Group Convolution) 3.3.2 深度可分离卷积(Depthwise Separable Convolution): 3.3 池…...

eNSP安装教程(内含安装包)
通过网盘分享的文件:eNSP模拟器.zip 链接: https://pan.baidu.com/s/1wPmAr4MV8YBq3U5i3hbhzQ 提取码: tefj --来自百度网盘超级会员v1的分享 !!!!解压后有四个文件,先安装Box,第二个安装cap&a…...

VBA技术资料MF244:利用VBA在图表工作表中创建堆积条形图
我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...

算术操作符与类型转换:从基础到精通
目录 前言:从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符:、-、*、/、% 赋值操作符:和复合赋值 单⽬操作符:、--、、- 前言:从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...