当前位置: 首页 > news >正文

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# 超高速高性能写日志icon-default.png?t=O83Ahttps://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# 超高速高性能写日志

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

阿里云人工智能ACA(五)——深度学习基础

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

入职体检尿潜血3+能通过吗,什么原因引起

在许多行业入职体检中&#xff0c;尿液检测是一个重要的组成部分。尿潜血&#xff08;也称为尿中血红蛋白&#xff09;是尿液常规检查中一种常见的指标&#xff0c;其结果可以反映出身体的健康状况。当检测结果为“尿潜血3”时&#xff0c;很多人会感到困惑&#xff0c;尤其是在…...

vue最新源码探索分析

我在github上fork了最新版本vue3.5版本的源码并做了大幅删除&#xff0c;保留最核心的代码&#xff0c;有兴趣的可以看看&#xff0c;欢迎大家提出PR 仓库地址 https://github.com/greatanimalion/core 本项目vue版本3.5.13 为了方便查看与分析&#xff0c;减少心智负担 已…...

Kivy App开发之打包apk

Kivy项目可以为windows,max os,安卓,IOS等平台创建运行python的程序包。本文介绍如何将程序打包成apk并在安卓系统上安卓运行。 打包apk的方法主要有三种 使用Kivy Launcher,添加项目文件夹(必须包含main.py文件和android.txt文件),启动Kivy Launcher后就会运行,要生成a…...

【Java 数据结构】LinkedList 类 和 模拟实现链表

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. 什么是 LinkedList &#xff1f; 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&#xff08;开发&#xff09;和Operations&#xff08;运维&#xff09;的组合&#xff0c;是一种新的软件工程理念&#xff0c;旨在打破传统软件工程方法中“开发->测试->运维”的割裂模式&#xff0c;强调端到端高效一致的交付流程&#xff0c;实…...

两种不同的LuaBehaviour生命周期绑定

在学习xLua时&#xff0c;发现xLua和LoxodonFramework的LuaBehaviour稍微有些不同&#xff0c;其中一个点是在调用DoString方法时的区别 1. xLua的版本中 直接使用Lua脚本环境进行绑定&#xff0c;这时候的Lua脚本调用生命周期函数是这样的 直接在Lua脚本中写函数就行 2. Lo…...

Effective C++ 条款31:将文件间的编译依存关系降至最低

文章目录 条款31&#xff1a;将文件间的编译依存关系降至最低最小化编译依赖关系的最佳实践通过减少编译依赖的好处总结 条款31&#xff1a;将文件间的编译依存关系降至最低 为了减少编译依赖关系&#xff0c;应该将接口与实现分离&#xff0c;并尽量减少头文件之间的依赖。这…...

python数据分析之爬虫基础:scrapy详解

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

openwrt 负载均衡方法 openwrt负载均衡本地源接口

openwrt 负载均衡方法 openwrt负载均衡本地源接口_mob6454cc647bdb的技术博客_51CTO博客 本人注重原理分析&#xff0c;要求对其原理掌握&#xff0c;否则按教程操作&#xff0c;你怕是什么都学不会&#xff0c;仔细看&#xff0c;认真记比较好。 首先确认一下基本细节 1、路由…...

Linux高级--3.3.2.6高并发编程之“内存屏障”“CPU屏障”“编译屏障”

一、内存屏障 在 Linux C 语言编程 中&#xff0c;内存屏障&#xff08;Memory Barrier&#xff09; 是一种用于控制内存访问顺序的技术。它主要用于多处理器系统中&#xff0c;确保某些操作按预期顺序执行&#xff0c;避免 CPU 和编译器对内存访问进行优化&#xff0c;从而影…...

【含开题报告+文档+PPT+源码】基于SpringBoot的智能安全与急救知识科普系统设计与实现

开题报告 在全球范围内&#xff0c;安全与急救知识的普及已成为提升公众安全素养、减少意外伤害发生率、提高突发事件应对能力的重要举措。尤其是在当今社会&#xff0c;人们面临的生活、工作环境日益复杂&#xff0c;交通事故、火灾、溺水、突发疾病等各种意外事件的发生概率…...

EMQX5.X版本性能配置调优参数

EMQX 主配置文件为 emqx.conf&#xff0c;根据安装方式其所在位置有所不同&#xff1a; 安装方式配置文件所在位置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版本。 解压缩放在本地软甲目录下面&#xff1a; 配置系统环境变量 在系统环境下面配置MAVEN_HOME 点击path 新增一条 在cmd中输入 mvn -v 检查maven的版本 配置阿里云镜像和本地的仓库 …...

水电站视频智能监控系统方案设计与技术应用方案

一、背景需求 水电站作为国家重要的能源基地&#xff0c;其安全运行对于保障能源供应和社会稳定具有重要意义。然而&#xff0c;传统的人工监控方式存在着诸多问题&#xff0c;如人力成本高、监控范围有限、反应不及时等。因此&#xff0c;水电站急需引进一种先进的视频智能监控…...

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 引领企业管理新潮流 在当今数字化飞速发展的时代&#xff0c;企业内部管理的高效性与智能化成为了决定企业竞争力的关键因素。华为&#xff0c;作为全球领先的科技巨头&#xff0c;其 AI Agent 技术在企业内部管理中的应用正掀起一场全新的变革浪潮。 AI Ag…...

【Pandas】pandas Series empty

Pandas2.2 Series Attributes 方法描述Series.index每个数据点的标签或索引Series.array对象底层的数据数组Series.values以NumPy数组的形式访问Series中的数据值Series.dtype用于获取 Pandas Series 中数据的类型&#xff08;dtype&#xff09;Series.shape用于获取 Pandas …...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…...

手动给中文分词和 直接用神经网络RNN做有什么区别

手动分词和基于神经网络&#xff08;如 RNN&#xff09;的自动分词在原理、实现方式和效果上有显著差异&#xff0c;以下是核心对比&#xff1a; 1. 实现原理对比 对比维度手动分词&#xff08;规则 / 词典驱动&#xff09;神经网络 RNN 分词&#xff08;数据驱动&#xff09…...

OpenGL-什么是软OpenGL/软渲染/软光栅?

‌软OpenGL&#xff08;Software OpenGL&#xff09;‌或者软渲染指完全通过CPU模拟实现的OpenGL渲染方式&#xff08;包括几何处理、光栅化、着色等&#xff09;&#xff0c;不依赖GPU硬件加速。这种模式通常性能较低&#xff0c;但兼容性极强&#xff0c;常用于不支持硬件加速…...