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 …...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...
ThreadLocal 源码
ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物,因为每个访问一个线程局部变量的线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段,这些类希望将…...
