C# 超高速高性能写日志
原理
使用列队先缓存到内存,独立线程从列队中使用log4net写到磁盘上。
日志写入列队
public void EnqueueMessage(string message, FlashLogLevel level, Exception ex = null)
{if ((level == FlashLogLevel.Debug && _log.IsDebugEnabled)|| (level == FlashLogLevel.Error && _log.IsErrorEnabled)|| (level == FlashLogLevel.Fatal && _log.IsFatalEnabled)|| (level == FlashLogLevel.Info && _log.IsInfoEnabled)|| (level == FlashLogLevel.Warn && _log.IsWarnEnabled)){_que.Enqueue(new FlashLogMessage{Message = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss,fff") + "]\r\n" + message,Level = level,Exception = ex});// 通知线程往磁盘中写日志_mre.Set();}
}
队列写入日志
/// <summary>
/// 另一个线程记录日志,只在程序初始化时调用一次
/// </summary>
public void Register()
{Thread t = new Thread(new ThreadStart(WriteLog));t.IsBackground = false;t.Start();
}/// <summary>
/// 从队列中写日志至磁盘
/// </summary>
private void WriteLog()
{while (true){// 等待信号通知_mre.WaitOne();FlashLogMessage msg;// 判断是否有内容需要如磁盘 从列队中获取内容,并删除列队中的内容while (_que.Count > 0 && _que.TryDequeue(out msg)){// 判断日志等级,然后写日志switch (msg.Level){case FlashLogLevel.Debug:_log.Debug(msg.Message, msg.Exception);break;case FlashLogLevel.Info:_log.Info(msg.Message, msg.Exception);break;case FlashLogLevel.Error:_log.Error(msg.Message, msg.Exception);break;case FlashLogLevel.Warn:_log.Warn(msg.Message, msg.Exception);break;case FlashLogLevel.Fatal:_log.Fatal(msg.Message, msg.Exception);break;}}// 重新设置信号_mre.Reset(); Thread.Sleep(1);}
}
应用注意事项
需要在程序启动时注册,如asp.net 程序中在Global.asax中的Application_Start注册。
注册示例
public class MvcApplication : System.Web.HttpApplication
{protected void Application_Start(){AreaRegistration.RegisterAllAreas();FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);FlashLogger.Instance().Register();}
}
使用
调用FlashLogger的静态方法
FlashLogger.Debug("Debug");
FlashLogger.Debug("Debug", new Exception("testexception"));
FlashLogger.Info("Info");
FlashLogger.Fatal("Fatal");
FlashLogger.Error("Error");
FlashLogger.Warn("Warn", new Exception("testexception"));
参考链接
C# 超高速高性能写日志https://mp.weixin.qq.com/s?__biz=MzA4MTQyNDk4OA==&mid=2456958300&idx=2&sn=9c949a184d13e23f98e82417ac729421&chksm=895b198dcdf167e226da852887a430b409d74997d18ded44e20858db53fd841448fe11b93d96&mpshare=1&scene=1&srcid=1226pYPjHUCOMZmnq7FMGk86&sharer_shareinfo=ece2905c127436a9b5eae1003db433fd&sharer_shareinfo_first=0628f372cfaf61c028e18d6a8c508f50&exportkey=n_ChQIAhIQuA3e9zi0waukFDFCW1r%2ByhKfAgIE97dBBAEAAAAAAMFpCyDDdf4AAAAOpnltbLcz9gKNyK89dVj0uQI27swsOvYg368rEF3G9%2B72QxoOEAPAtRnBP0T8TmPbvTWYGbNG6ug7Za3ehBxruqhkk%2Bki%2BwUlj9NyGj7PzmMFO%2FJsij6UBGY3Vpgu3wKdrwe08W%2F0g4%2FAHVYW85it%2FEy104f1SNm0dtnV7sKSaTu8QbO%2FhqanrBe6n1u5q0B816ezwmh2m4RyMqxtUucoo0a2cOBvnIpfgO5pA%2F1KZ1naNd73ubHBMDQ2dU8E8SSQH2quniORgpyMqyOMK19GbsFh9Yh6xu1qsmX3iE5Ei%2F3G3JxxHvWaTR5uV5%2Fousn%2Fly4ctUTgA1mNvArHHHabEgtbFAVFrP5W&acctmode=0&pass_ticket=%2BHWz3yc2o8iZ6T2jkz0Pa27SKjP5Jc%2BuBoHv%2FE7tlB6avrF01Uh8JTBFsqDxKGA6&wx_header=0#rd
完整代码
using log4net;
using log4net.Config;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace Emrys.FlashLog
{public sealed class FlashLogger{/// <summary>/// 记录消息Queue/// </summary>private readonly ConcurrentQueue<FlashLogMessage> _que;/// <summary>/// 信号/// </summary>private readonly ManualResetEvent _mre;/// <summary>/// 日志/// </summary>private readonly ILog _log;/// <summary>/// 日志/// </summary>private static FlashLogger _flashLog = new FlashLogger();private FlashLogger(){var configFile = new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4net.config"));if (!configFile.Exists){throw new Exception("未配置log4net配置文件!");}// 设置日志配置文件路径XmlConfigurator.Configure(configFile);_que = new ConcurrentQueue<FlashLogMessage>();_mre = new ManualResetEvent(false);_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);}/// <summary>/// 实现单例/// </summary>/// <returns></returns>public static FlashLogger Instance(){return _flashLog;}/// <summary>/// 另一个线程记录日志,只在程序初始化时调用一次/// </summary>public void Register(){Thread t = new Thread(new ThreadStart(WriteLog));t.IsBackground = false;t.Start();}/// <summary>/// 从队列中写日志至磁盘/// </summary>private void WriteLog(){while (true){// 等待信号通知_mre.WaitOne();FlashLogMessage msg;// 判断是否有内容需要如磁盘 从列队中获取内容,并删除列队中的内容while (_que.Count > 0 && _que.TryDequeue(out msg)){// 判断日志等级,然后写日志switch (msg.Level){case FlashLogLevel.Debug:_log.Debug(msg.Message, msg.Exception);break;case FlashLogLevel.Info:_log.Info(msg.Message, msg.Exception);break;case FlashLogLevel.Error:_log.Error(msg.Message, msg.Exception);break;case FlashLogLevel.Warn:_log.Warn(msg.Message, msg.Exception);break;case FlashLogLevel.Fatal:_log.Fatal(msg.Message, msg.Exception);break;}}// 重新设置信号_mre.Reset();Thread.Sleep(1);}}/// <summary>/// 写日志/// </summary>/// <param name="message">日志文本</param>/// <param name="level">等级</param>/// <param name="ex">Exception</param>public void EnqueueMessage(string message, FlashLogLevel level, Exception ex = null){if ((level == FlashLogLevel.Debug && _log.IsDebugEnabled)|| (level == FlashLogLevel.Error && _log.IsErrorEnabled)|| (level == FlashLogLevel.Fatal && _log.IsFatalEnabled)|| (level == FlashLogLevel.Info && _log.IsInfoEnabled)|| (level == FlashLogLevel.Warn && _log.IsWarnEnabled)){_que.Enqueue(new FlashLogMessage{Message = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss,fff") + "]\r\n" + message,Level = level,Exception = ex});// 通知线程往磁盘中写日志_mre.Set();}}public static void Debug(string msg, Exception ex = null){Instance().EnqueueMessage(msg, FlashLogLevel.Debug, ex);}public static void Error(string msg, Exception ex = null){Instance().EnqueueMessage(msg, FlashLogLevel.Error, ex);}public static void Fatal(string msg, Exception ex = null){Instance().EnqueueMessage(msg, FlashLogLevel.Fatal, ex);}public static void Info(string msg, Exception ex = null){Instance().EnqueueMessage(msg, FlashLogLevel.Info, ex);}public static void Warn(string msg, Exception ex = null){Instance().EnqueueMessage(msg, FlashLogLevel.Warn, ex);}}/// <summary>/// 日志等级/// </summary>public enum FlashLogLevel{Debug,Info,Error,Warn,Fatal}/// <summary>/// 日志内容/// </summary>public class FlashLogMessage{public string Message { get; set; }public FlashLogLevel Level { get; set; }public Exception Exception { get; set; }}
}
特此记录
anlog
2024年12月27日
相关文章:

C# 超高速高性能写日志
原理 使用列队先缓存到内存,独立线程从列队中使用log4net写到磁盘上。 日志写入列队 public void EnqueueMessage(string message, FlashLogLevel level, Exception ex null) {if ((level FlashLogLevel.Debug && _log.IsDebugEnabled)|| (level Flas…...

阿里云人工智能ACA(五)——深度学习基础
一、深度学习概述 1. 深度学习概念 1-1. 深度学习基本概念 深度学习是机器学习的一个分支基于人工神经网络(模仿人脑结构)通过多层网络自动学习特征能够处理复杂的模式识别问题 1-2. 深度学习的优点与缺点 优点 强大的特征学习能力可以处理复杂问题…...

入职体检尿潜血3+能通过吗,什么原因引起
在许多行业入职体检中,尿液检测是一个重要的组成部分。尿潜血(也称为尿中血红蛋白)是尿液常规检查中一种常见的指标,其结果可以反映出身体的健康状况。当检测结果为“尿潜血3”时,很多人会感到困惑,尤其是在…...
vue最新源码探索分析
我在github上fork了最新版本vue3.5版本的源码并做了大幅删除,保留最核心的代码,有兴趣的可以看看,欢迎大家提出PR 仓库地址 https://github.com/greatanimalion/core 本项目vue版本3.5.13 为了方便查看与分析,减少心智负担 已…...
Kivy App开发之打包apk
Kivy项目可以为windows,max os,安卓,IOS等平台创建运行python的程序包。本文介绍如何将程序打包成apk并在安卓系统上安卓运行。 打包apk的方法主要有三种 使用Kivy Launcher,添加项目文件夹(必须包含main.py文件和android.txt文件),启动Kivy Launcher后就会运行,要生成a…...

【Java 数据结构】LinkedList 类 和 模拟实现链表
🔥博客主页🔥:【 坊钰_CSDN博客 】 欢迎各位点赞👍评论✍收藏⭐ 目录 1. 什么是 LinkedList ? 2 LinkedList 的使用 2.1 LinkedList 的构造 2.2 LinkedList 的常用方法 2.3 LinkedList 的遍历 3. 单链表的模拟实现…...

VS2022 中的 /MT /MTd /MD /MDd 选项
我们有时编译时,需要配置这个 运行库,指定C/C++运行时库的链接方式。 如下图 那么这些选项的含义是什么? /MT:静态链接多线程库 /MT选项代表“Multi-threaded Static”,即多线程静态库。选择此选项时,编译器会从运行时库中选择多线程静态连接库来解释程序中的代码,…...

产品初探Devops!以及AI如何赋能Devops?
DevOps源自Development(开发)和Operations(运维)的组合,是一种新的软件工程理念,旨在打破传统软件工程方法中“开发->测试->运维”的割裂模式,强调端到端高效一致的交付流程,实…...

两种不同的LuaBehaviour生命周期绑定
在学习xLua时,发现xLua和LoxodonFramework的LuaBehaviour稍微有些不同,其中一个点是在调用DoString方法时的区别 1. xLua的版本中 直接使用Lua脚本环境进行绑定,这时候的Lua脚本调用生命周期函数是这样的 直接在Lua脚本中写函数就行 2. Lo…...
Effective C++ 条款31:将文件间的编译依存关系降至最低
文章目录 条款31:将文件间的编译依存关系降至最低最小化编译依赖关系的最佳实践通过减少编译依赖的好处总结 条款31:将文件间的编译依存关系降至最低 为了减少编译依赖关系,应该将接口与实现分离,并尽量减少头文件之间的依赖。这…...

python数据分析之爬虫基础:scrapy详解
一、爬虫工程化 在之前的爬虫学习中基本已经掌握了爬虫这门技术的大多数技术点,但是我们现在写的代码还很流程化,很难进行商用,想要爬虫达到商用级别,必须要对我们现在编写的爬虫进行大刀阔斧式的重组,以达到工程化的…...

openwrt 负载均衡方法 openwrt负载均衡本地源接口
openwrt 负载均衡方法 openwrt负载均衡本地源接口_mob6454cc647bdb的技术博客_51CTO博客 本人注重原理分析,要求对其原理掌握,否则按教程操作,你怕是什么都学不会,仔细看,认真记比较好。 首先确认一下基本细节 1、路由…...
Linux高级--3.3.2.6高并发编程之“内存屏障”“CPU屏障”“编译屏障”
一、内存屏障 在 Linux C 语言编程 中,内存屏障(Memory Barrier) 是一种用于控制内存访问顺序的技术。它主要用于多处理器系统中,确保某些操作按预期顺序执行,避免 CPU 和编译器对内存访问进行优化,从而影…...

【含开题报告+文档+PPT+源码】基于SpringBoot的智能安全与急救知识科普系统设计与实现
开题报告 在全球范围内,安全与急救知识的普及已成为提升公众安全素养、减少意外伤害发生率、提高突发事件应对能力的重要举措。尤其是在当今社会,人们面临的生活、工作环境日益复杂,交通事故、火灾、溺水、突发疾病等各种意外事件的发生概率…...

EMQX5.X版本性能配置调优参数
EMQX 主配置文件为 emqx.conf,根据安装方式其所在位置有所不同: 安装方式配置文件所在位置DEB 或 RPM 包安装/etc/emqx/emqx.confDocker 容器/opt/emqx/etc/emqx.conf解压缩包安装./etc/emqx.conf EMQ X 消息服务器默认占用的 TCP 端口包括: 端口 说明…...

电脑配置maven-3.6.1版本
不要使用太高的版本。 apache-maven-3.6.1-bin.zip 下载这个的maven压缩包 使用3.6.1版本。 解压缩放在本地软甲目录下面: 配置系统环境变量 在系统环境下面配置MAVEN_HOME 点击path 新增一条 在cmd中输入 mvn -v 检查maven的版本 配置阿里云镜像和本地的仓库 …...

水电站视频智能监控系统方案设计与技术应用方案
一、背景需求 水电站作为国家重要的能源基地,其安全运行对于保障能源供应和社会稳定具有重要意义。然而,传统的人工监控方式存在着诸多问题,如人力成本高、监控范围有限、反应不及时等。因此,水电站急需引进一种先进的视频智能监控…...
React 组件通信完整指南 以及 自定义事件发布订阅系统
React 组件通信完整指南 1. 父子组件通信 1.1 父组件向子组件传递数据 // 父组件 function ParentComponent() {const [data, setData] useState(Hello from parent);return <ChildComponent message{data} />; }// 子组件 function ChildComponent({ message }) {re…...

华为 AI Agent:企业内部管理的智能变革引擎(11/30)
一、华为 AI Agent 引领企业管理新潮流 在当今数字化飞速发展的时代,企业内部管理的高效性与智能化成为了决定企业竞争力的关键因素。华为,作为全球领先的科技巨头,其 AI Agent 技术在企业内部管理中的应用正掀起一场全新的变革浪潮。 AI Ag…...
【Pandas】pandas Series empty
Pandas2.2 Series Attributes 方法描述Series.index每个数据点的标签或索引Series.array对象底层的数据数组Series.values以NumPy数组的形式访问Series中的数据值Series.dtype用于获取 Pandas Series 中数据的类型(dtype)Series.shape用于获取 Pandas …...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...