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 …...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版
1.题目描述 2.思路 当前的元素可以重复使用。 (1)确定回溯算法函数的参数和返回值(一般是void类型) (2)因为是用递归实现的,所以我们要确定终止条件 (3)单层搜索逻辑 二…...
如何把工业通信协议转换成http websocket
1.现状 工业通信协议多数工作在边缘设备上,比如:PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发,当设备上用的是modbus从站时,采集设备数据需要开发modbus主站;当设备上用的是西门子PN协议时…...
