本文将使用一个Nuget的一个组件库来实现一个简单强大的日志记录功能,包采用线程安全实现,所有的记录在后台完成,即使您在前台调用100万次方法,耗时也不过1000ms(具体时间依照电脑性能决定),支持日志等级,并提供了一个控件用于分析所有的日志消息。

在visual studio 中的Nuget管理器中可以下载安装,也可以直接在Nuget控制台输入下面的指令安装:

  1. Install-Package HslCommunication

Nuget安装教程:http://www.cnblogs.com/dathlin/p/7705014.html

联系作者及加群方式(激活码在群里发放):http://www.hslcommunication.cn/Cooperation

本组件提供了一个日志功能,实现了常用的3中日志模式:

  • 单日志文件模式,日志始终都向该文件写入,需要程序中自行清除或手动编写代码清空,不然文件会很大。
  • 根据文件大小存储的多文件模式,一个日志文件写入达到某个数值时,创建新文件写入。
  • 根据时间日期的多文件模式,每条日志将根据写入的时间日志来判断文件名,比如创建按每天存储的日志。

我也曾使用过.net中大名鼎鼎的log4net日志组件,一般使用起来确实方便,但是我在诸如实现上述的需求的时候就特别麻烦,而且log4net功能众多,大多数功能并不是我所需要的,我就需要一个实现txt日志的存储方式,简单高效,多种模式即可。于是就自行开发了一个简单高效的日志组件,并集成到了该通信库中,本日志组件还提供了一个分析控件及窗口,可以对一个长长的日志文件进行分析统计(只对本组件生成的日志有效),快速定位需要查找的日志信息,支持使用正则表达式来筛选,本日志组件也提供了分级存储。

Demo程序下载 HslCommunicationDemo.zip

使用之前先要进行命名控件的引用,如下:

  1. using HslCommunication.LogNet;

  

实例化

首先先实例化一个对象,如果您用于整个application的日志存储,可以定义成静态对象。或者直接定义在form窗口的下面也可以。此处先实例化单文件存储的机制

  1. private ILogNet logNet = new LogNetSingle("D:\\123.txt");

  

我们通常的做法是日志文件存储在exe程序目录下的Logs文件夹中,无论在服务器端还是客户端都是非常适用的,所以

  1. private ILogNet logNet = new LogNetSingle(Application.StartupPath + "\\Logs\\123.txt");

  

写日志

接下来你就可以在窗口的其他地方进行写入日志了,本组件提供了5个等级的日志写入功能,名称参考了常规的日志等级,有 DEBUG , INFO, WARN , ERROR , FATAL ,根据需要进行存储,还提供了对exception异常的方法支持和自定义的描述化文本写入,该文本不属于日志范畴,在日志分析中会被忽略,如下代码演示几种不同的写入(写入的方式采用统一的接口实现,对于三种日志模式都是适用的):

  1. private void userButton1_Click(object sender, EventArgs e)
  2. {
  3. // 一般日志写入
  4. logNet.WriteDebug("调试信息");
  5. logNet.WriteInfo("一般信息");
  6. logNet.WriteWarn("警告信息");
  7. logNet.WriteError("错误信息");
  8. logNet.WriteFatal("致命信息");
  9. logNet.WriteException(null, new IndexOutOfRangeException());
  10.  
  11. // 带有关键字的写入,关键字建议为方法名或是类名,方便分析的时候归类搜索
  12. logNet.WriteDebug("userButton1_Click", "调试信息");
  13. logNet.WriteInfo("TestForm", "一般信息");
  14. logNet.WriteWarn("随便什么", "警告信息");
  15. logNet.WriteError("userButton1_Click", "错误信息");
  16. logNet.WriteFatal("userButton1_Click", "致命信息");
  17. logNet.WriteException("userButton1_Click", new IndexOutOfRangeException());
  18. }

写入异常时会被自动赋予 FATAL 等级。写入效果如下:

下面再说明写入描述文本的时候发生的事情:

  1. logNet.WriteDescrition("这是一条描述文本");

 

描述性文本的前面会再新增一行作为明显的区分。描述性文本不列入到日志分析工具中,会被自动被过滤。

 

设置等级

为什么要实现日志分级呢?有两个巨大的好处。第一个好处是方便在日志追述的时候进行筛选,比如我需要查看日志中致命错误的时候就尤为重要,可以进行快速的筛选。第二个好处就是用于开发的时候调试使用,有时候我们为了快速的找到程序问题的时候,会对程序运行中各种数据状态,系统状态进行输出,然后分析日志得出结论。当你已经写了很多很多的

  1. logNet.WriteDebug("调试信息");

代码后,准备发布使用的时候不想输出这种仅用于调试的时候的日志,总不可能取消所有的调试日志吧?效率太低,万一以后需要恢复输出就麻烦了,所以本日志组件支持写入日志的时候的等级设置,如果我们把日志的等级设置为INFO级别,那么所有的DEBUG级别的日志都不会存储,所以我们在发布软件的时候,只要设置等级就行。

下面再来说明下如何设置日志存储等级。使用方法:

  1. logNet.SetMessageDegree(HslMessageDegree.DEBUG);//所有等级存储
  2. logNet.SetMessageDegree(HslMessageDegree.INFO);//除DEBUG外,都存储
  3. logNet.SetMessageDegree(HslMessageDegree.WARN);//除DEBUG和INFO外,都存储
  4. logNet.SetMessageDegree(HslMessageDegree.ERROR);//只存储ERROR和FATAL
  5. logNet.SetMessageDegree(HslMessageDegree.FATAL);//只存储FATAL
  6. logNet.SetMessageDegree(HslMessageDegree.None);//不存储任何等级

选择上面的一行代码执行就行。

自定义事件

组件默认存储所有的等级,如果需要设置,在实例化后即可设置等级。日志组件支持一个事件,在所有的日志进行存储前(被日志等级过滤掉的不会触发)会报告事件,可以用于其他操作或是控制台的显示等等,注意: 如果在事件关联方法中直接访问UI线程,会异常

这个事件有个非常大的好处,可以统一输出显示你的程序中所有地方的日志,方便统一的控制和处理。

  1. logNet.BeforeSaveToFile += LogNet_BeforeSaveToFile;
  1. private void LogNet_BeforeSaveToFile(object sender, HslEventArgs e)
  2. {
  3. // 如果需要UI显示,就要取消注释下方的代码
  4.  
  5. //if(InvokeRequired)
  6. //{
  7. // Invoke(new Action(() =>{
  8. // LogNet_BeforeSaveToFile(sender, e);
  9. // }));
  10. // return;
  11. //}
  12.  
  13. string degree = e.HslMessage.Degree.ToString();//获取等级
  14. DateTime time = e.HslMessage.Time;//获取时间
  15. string text = e.HslMessage.Text;//日志文本
  16. int threadId = e.HslMessage.ThreadId;//记录日志的线程id
  17. }

  

这个事件在2019年2月10日 16:36:41上新增了一个额外的功能,就是允许你手动取消当前日志的存储

  1. private void LogNet_BeforeSaveToFile( object sender, HslEventArgs e )
  2. {
  3. e.HslMessage.Cancel = checkBox1.Checked;
  4. }

假设这样设置后,所有的日志都不存储到文件中去。

  1. private void LogNet_BeforeSaveToFile( object sender, HslEventArgs e )
  2. {
  3. if (e.HslMessage.Degree != HslMessageDegree.INFO)
  4. {
  5. e.HslMessage.Cancel = checkBox1.Checked;
  6. }
  7. }

如果这么写,就是只存储INFO等级的日志信息。

过滤指定的关键字日志存储

有些日志数据可能我们想要触发BeforeSaveToFile事件,但是不能存储到日志文件里,那么可以直接按照如下的配置进行设置,会过滤掉存储到文件中,如下就是过滤掉关键字的信息

  1. logNet.FiltrateKeyword( "123" );

按文件大小存储的实例化

若要按照文件大小进行存储,例如日志存储2M后,自动生成新的文件,然后存满2M后生成新文件,如此重复,则需要指定文件的 存储路径大小 ,这种方式存储的文件名称不可控制,自动定义为 Logs_20170903170604.txt 的格式,会以当前时间自动命名,如下举例了实例化一个2M大小的对象:

  1. ILogNet logNet = new LogNetFileSize(Application.StartupPath + "\\customer1", 2 * 1024 * 1024);

  

只要定义了对象,就可以按照上述写入日志的代码来写了。

按时间日期存储的实例化

也是一种多文件的存储机制,和按照大小的存储非常类似,此处可以配置按照每小时生成新的文件,每天新的文件,每月新的文件,每季度新的文件,每年新的文件,生成的文件名称也是固定的,需要指定 路径存储模式

  1. ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2",GenerateMode.ByEveryHour);//按每小时
  2. ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2", GenerateMode.ByEveryDay);//按每天
  3. ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2", GenerateMode.ByEveryMonth);//按每月
  4. ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2", GenerateMode.ByEverySeason);//按每季度
  5. ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2", GenerateMode.ByEveryYear);//按每年

  

单文件模式

单文件的模式在上述已经作为演示说明过了,但是单文件模式提供了两个额外的方法:

  • 获取该文件日志中所有的内容
  • 清空该文件的所有数据

具体的代码如下所示:

  1. LogNetSingle logNetSingle = logNet as LogNetSingle;
  2. if (logNetSingle != null)
  3. {
  4. string logData = logNetSingle.GetAllSavedLog();//获取所有的日志信息
  5. logNetSingle.ClearLog();//清除所有的日志信息
  6. }

  

日志查看器

如果只提供了一个日志的写入而没有分析工具,那么本组件就是没什么竞争力的,本日志组件提供了一个大杀器,日志分析控件!您可以集成到您自己的系统中,该控件只需要接受一个 日志源字符串 (就是日志文件的所有字符串数据,服务器读取文件发送给远程客户端就可以现实远程查看日志分析!棒不棒!)原先的 ClientServerProject 项目中已经带有了2个日志查看器,一个服务器端使用了本组件提供的标准form窗口,客户端使用了日志分析控件实现远程查看功能,具体代码可以参照 ClientServerProject 项目的代码。

功能概述

  • 对日志文件中的所有等级日志进行分析,每种等级多少个
  • 可以同时根据日志等级和时间区段来筛选日志,比如查看某一时间段的 DEBUG 等级日志
  • 可以进行可视化分析,查看日志数据的时间分布情况
  • 在可视化的界面,如果某个区间段的某日数量特别高,鼠标移动上去后还可以自动跳转

此处直接演示一个组件标准的日志查看窗口,这个窗口也可以在wpf项目中显示:

  1. private void userButton13_Click(object sender, EventArgs e)
  2. {
  3. // 日志查看器
  4. using (HslCommunication.LogNet.FormLogNetView form = new HslCommunication.LogNet.FormLogNetView())
  5. {
  6. form.ShowDialog();
  7. }
  8. }

效果上图

查看日志信息

上图中点击了 信息 按钮后,显示的图形发生了变化,只显示了 信息 等级日志

光标移动到某一区间后,下方会有该区间的日志数量和时间范围,双击后的操作就您自己去发现了。^_^

控件的方式,新建一个窗口,将组件的控件给拖进去,如果这个组件在工具箱不显示,那么需要将dll文件拖到工具箱。

至于显示信息代码:

  1. private void FormLogNetTest_Load(object sender, EventArgs e)
  2. {
  3. // 该source可以是本地读取的文件,也可以是网络发送过来的数据
  4. string source = Encoding.UTF8.GetString(System.IO.File.ReadAllBytes("123.txt")); // 传入路径
  5. logNetAnalysisControl1.SetLogNetSource(source);
  6. }

C# 日志记录分级功能使用 按照日期,大小,或是单文件存储的更多相关文章

  1. python内置函数print输出到文件,实现日志记录的功能

    # bulid time 2018-6-22 import os import time def log(*args, **kwargs): # *kargs 为了通用 可不传 rule = &quo ...

  2. 基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)

    前言: 本章介绍自己写的基于java.util.logging的轻量级日志记录库(baseLog). 该版本的日志记录库犹如其名,baseLog,是个实现日志记录基本功能的小库,适合小型项目使用,方便 ...

  3. mysql数据库安全性配置——日志记录

    一:开启数据库日志记录 (1)在查看数据库是否开启日志记录,默认是OFF,即关闭状态.(可在数据库中执行该查询语句,也可在服务器端执行) show variables like 'log_bin'; ...

  4. 【干货】.NET开发通用组件发布(四) 日志记录组件

    组件介绍和合作开发 http://www.cnblogs.com/MrHuo/p/MrHuoControls.html 日志记录组件功能介绍 通过基类Logger,实现了文本记录日志和数据库记录日志两 ...

  5. asp.net Web项目中使用Log4Net进行错误日志记录

      使用log4net可以很方便地为应用添加日志功能.应用Log4net,开发者可以很精确地控制日志信息的输出,减少了多余信息,提高了日志记录性能.同时,通过外部配置文件,用户可以不用重新编译程序就能 ...

  6. 使用 ssm 实现登录日志记录

    使用 ssm 实现登录日志记录 学习总结 一.基础准备 1. 实现效果 2. 数据表 2.1 登陆日志信息表 2.3 员工表 二.代码实现 1. SysLogLogin 实体类 2. LogAspec ...

  7. Hibernate使用Log4j日志记录(使用xml文件)

    日志记录使程序员能够将日志详细信息永久写入文件. Log4j和Logback框架可以在hibernate框架中使用来支持日志记录. 使用log4j执行日志记录有两种方法: 通过log4j.xml文件( ...

  8. 如何自行给指定的SAP OData服务添加自定义日志记录功能

    有的时候,SAP标准的OData实现或者相关的工具没有提供我们想记录的日志功能,此时可以利用SAP系统强大的扩展特性,进行自定义日志功能的二次开发. 以SAP CRM Fiori应用"My ...

  9. IOS异常日志记录与展现功能

    在平常的APP开发过程中经常碰到程序遇到异常闪退的问题,通过日志可以把相关的详细错误信息进行记录,本实例要记录不管在哪个页面出错都要进行记录,这边使用到的日志记录插件CocoaLumberjack,以 ...

随机推荐

  1. ACM总结——2017区域赛网络赛总结

    从省赛回来至今4周,每周周末都在打网络赛,每次都是划水,总结下自己弱弱的ACM吧!划水水~~ 首先是新疆赛区,基本上都是图论相关的东西,全靠队友,自己翻水水,实力躺了5道. 然后是沈阳赛区,终于有点贡 ...

  2. 模块 import 与from

    什么是模块:就是一系列功能的集合体 模块的来源 :1内置模块   2 第三方模块   3 自定义模块 模块的格式: 1 使用python编写的.py文件 2 已被编译为共享库或DLL的C或C++扩展 ...

  3. 关于oracle result_cache

    结果集缓存 和聚合物化视图类似,报表系统和数据仓库系统是最适合结果集缓存的,这些系统通常具有大量复杂的SQL,其中不少子查询包含聚合函数,如果能够尽可能重用这些已经计算过的聚合结果集,将极大的提升系统 ...

  4. CEF 跨域访问iframe

    转载:https://www.cnblogs.com/wxxweb/p/3738696.html 在CefBrowserSettings也就是_cef_browser_settings_t结构体中,有 ...

  5. github笔记

    git config --global user.name"liuhongli1"liuhongli@liuhongli:~/github/test$ git config --g ...

  6. Spring错误——Spring xml注释——org.xml.sax.SAXParseException; lineNumber: 24; columnNumber: 10; cvc-complex-type.2.3: 元素 'beans' 必须不含字符 [子级], 因为该类型的内容类型为“仅元素”。

    背景:配置spring xml,注释xml中文件元素 错误: Caused by: org.xml.sax.SAXParseException; lineNumber: 24; columnNumbe ...

  7. 7.24-Codeforces Round #494 (Div. 3)

    链接:http://codeforces.com/contest/1003 A. Polycarp's Pockets 题型:模拟 题意:把初始集合拆分,要求相同的数不在同一个集合中,求出需要的集合个 ...

  8. Apache web服务器(LAMP架构)

    Apache web服务器(LAMP架构) apache介绍 1).世界上使用率最高的网站服务器,最高时可达70%:官方网站:apache.org 2).http 超文本协议 HTML 超文本标记语言 ...

  9. Bellman-Ford算法模板题

    POJ 3259 虫洞(Bellman-Ford判断有无负环的问题) 描述: 在探索他的许多农场时,Farmer John发现了许多令人惊叹的虫洞.虫洞是非常奇特的,因为它是一条单向路径,在您进入虫洞 ...

  10. 学习笔记69—金蝶财务软件安装教程(KIS12.3,win10)

    ****************************************************** 如有谬误,请联系指正.转载请注明出处. 联系方式: e-mail: heyi9069@gm ...