C#如何设计一个好用的日志库?

阅读目录

  • 〇、前言

  • 一、日志的简单记录

  • 二、通过开源库 HslCommunication 记录不同级别的日志

  • 三、通过开源库 NLog 实现通过配置文件配置日志选项

    • 1. 配置文件

    • 2. 测试代码

    • 3. 日志记录类

  • 四、日志查看器 TextAnalysisTool.NET

    • 1. 下载应用程序包

    • 2. 分析的日志文件


〇、前言

相信你在实际工作期间经常遇到或听到这样的说法:

“我现在加一下日志,等会儿你再操作下。”

“只有在程序出问题以后才会知道打一个好的日志有多么重要。”

可见日志的记录是日常开发的必备技能。

记录日志的必要性:

当业务比较复杂时,在关键代码附件添加合适的日志是非常重要的,这样可以出现异常后,有章可循,较快速的在不停服的情况下,定位问题并解决。特别是在项目组中,人员较多,若没有统一的日志记录规范,查找系统问题原因就更加费时费力。

记录日志的三种实现:

  1. 当业务比较简单,性能要求不高,只是单纯的记录程序的运行是否正常。此时就可以参考本文第一种实现,仅一种级别的文本记录。

  2. 当业务复杂较复杂,对性能有一定要求时,可以根据实际情况,参考本文的第二、第三种实现。

  3. 当业务非常复杂,必然运行的效率就要求比较高,如何即让程序稳定高效的运行,又能合理记录程序运行状态成为关键。高效的的日志操作可以参考本文的第三种实现。


一、日志的简单记录

如下,为简单的记录开发人员预输出的文本内容,其内容为自定义,输出的时间格式和固定标识需相同。

此方法的性能当然是最差的,针对同一个日志文件,需要独占访问,当同时出现多个记录需求时,会出现排队的情况,导致系统出现卡顿。当然,可以采用多目标文件的方式来提高性能表现,若业务较复杂,还是推荐使用后两种方式。

日志内容测试结果:

日志类内容:

回到顶部

二、通过开源库 HslCommunication 记录不同级别的日志

此方式记录日志,简单高效,可以实现不同级别日志的输出控制,日志选项的配置可以配置在程序的配置文件中,在程序启动时加载即可。

若想实现实时加载,这只能在每次写日志前初始化日志对象,这样估计就影响程序性能了。

日志内容测试结果:

三个相关日志类:

  • HslCommunicationOper:操作类;

  • LogNetCollection:扩展类(提供日志文件的大小、生成新文件频率的配置);

  • MessageDegree:消息级别枚举。

参考:C# 日志记录分级功能使用 按照日期,大小,或是单文件存储( cnblogs.com/dathlin/p/7 )


三、通过开源库 NLog 实现通过配置文件配置日志选项

NLog 是一个基于 .net 平台编写的日志记录类库,我们可以使用 NLog 在应用程序中添加极为完善的跟踪调试代码。

本文将通过日志框架 Nlog 和 ConcurrentQueue 队列,实现一个高性能的日志库。

首先,为什么相中了 Nlog ?

  • NLog 是适用于各个 .net 平台的灵活且免费的日志记录平台。通过 NLog, 可以轻松地写入多个目标(例如:数据库、文件、控制台等), 并可动态更改日志记录配置信息。

  • NLog 支持结构化和传统日志记录。

  • NLog 的特点: 高性能、易于使用、易于扩展和灵活配置。

ConcurrentQueue:表示线程安全的先进先出(FIFO)集合。所有公共成员和受保护成员 ConcurrentQueue<T> 都是线程安全的,可以从多个线程并发使用。


1. 配置文件

对于 ASP.NET 应用程序,存在嵌入程序配置文件和单独配置文件两种方式,程序在启动时,会在应用程序主目录下依次查找: web.config(*.exe.config、*.web.config)、web.nlog(*.exe.nlog)、NLog.config

个人推荐单独文件配置,便于修改和迭代使用。

第一种方式:单独配置文件

常用名称为 NLog.config。此时需要在根节点 nlog 加上智能感知(Intellisense)的属性配置,详见下文配置文件 XML 代码。

1/5 targets(必须有) - 定义日志目标/输出

  • name:是指的输出地方的一个名词(给 rules 调用的);

  • xsi:type:输出文件的类型,File 指的是文件,Console 控制台输出;

  • fileName:输出到目标文件的地址,使用的相对路径,可以自行配置输出的地点。

  • layout:在最简单的形式中,布局是带有嵌入标记的文本,这些嵌入标记样子例如:${xxxx};

  • archiveFileName:表示 滚动日志 存放路径;

  • archiveAboveSize:单次日志的存储大小 (单位是Byte) ,超过配置,会 archiveFileName 中创建新的日志文件;

  • maxArchiveFiles:最多保留日志文件的数量,超过后将最早的日志文件自动清除,若值 <=0 则不删除;

  • archiveNumbering:日志文件的编号顺序,Sequence(顺序,数字越大越近),Rolling(倒序,数字越小越近);另有 Date、DateAndSequence,详见官网

  • maxArchiveDays:日志文件保留的最长天数,若值 <=0 则不删除,当archiveNumbering 为 Rolling 时无效;

  • archiveEvery:指示在某个时间节点自动生成下一个日志文件,值示例:Year/Day/Minute/Sunday/Friday/None 等等;

  • concurrentWrites:支持多个并发一起写文件,提高文件写入性能;

  • keepFileOpen:为了提高文件写入性能,避免每次写入文件都开关文件;

  • autoFlush:为了提高日志写入性能,不必每次写入日志都直接写入到硬盘;

  • header/footer:给每个日志文件添加头/尾的固定内容;

其中, layout 属性的标记变量(${xxx})解析 可以参考以下代码:


点击展开 查看标记释义


2/5 rules(必须有) - 定义日志路由规则

rules 下只有一种节点 logger(可同时配置多个),其属性释义如下:

  • name:logger 名称,若为 * 则表示适用于所有日志,?:匹配单个字符;

  • minlevel:表示记录的最低日志级别,只有大于等于该日志级别才会被记录;

  • maxlevel:记录的最高级别;

  • level:单极记录,只记录一个级别日志;

  • levels:同时记录多个级别的日志,用逗号分隔;

  • writeTo:和 target 节点的 name 属性值匹配,一个 rules 对应一个 target;

  • enabled:通过值为 false 禁用规则,而不用删除;

  • ruleName:规则标识符,允许使用 Configuration.FindRuleByName 和进行规则查找 Configuration.RemoveRuleByName,在 NLog 4.6.4 中引入。

3/5 variables - 声明变量的值

variable 元素定义了 配置文件中需要用到的变量 ,一般用来 表示复杂或者重复的表达式 (例如文件名)。变量需要先定义后使用,否则配置文件将初始化失败。

  • name:变量名;

  • value:变量值。

定义变量之后,可以通过 ${my_name} 语法来使用。

4/5 extensions - 定义要加载的 NLog 扩展项 *.dll 文件

extensions 节点可以添加额外的 NLog 元包或自定义功能,assembly 属性指定的被包含程序集不带后缀 .dll 。示例如下:

NLog 4.0 之后,与 NLog.dll 同目录下名如 NLog*.dll 的程序集(如: NLog.CustomTarget.dll )会被自动加载。

5/5 includes - 指定当前配置文件包含多个子配置文件

通过 ${} 语法可以使用环境变量,下例展示包含一个名为当前机器名的配置文件。

NLog 4.4.2 之后可以使用通配符 * 指定多个文件。例如: <include file="nlog-*.config" />

示例配置:

参考:完善 .Net Core 项目 — NLog入门 (日志组件)( zhuanlan.zhihu.com/p/35 )

第二种方式:嵌入程序配置文件

NLog 配置信息可以嵌入在 .net 应用程序自身的配置文件中,例如 *.exe.config 或者 *.web.config 中,需要使用 configSections 节点配置,如下 XML 代码,再将其他配置填入 nlog 节点即可。

nlog 节点内的内容,参考前边‘第一种方式’。


2. 测试代码


3. 日志记录类

后续跟新内容:再次感谢评论区的大佬们,博主已经意识到实际上 Nlog 本身已经足够强大,本身就支持队列缓存,此部分就画蛇添足了,不建议使用!

以下代码对 NLog 进行了封装, 将日志记录先存在线程安全的队列里,以避免调用写入文件时 I/O 的耗时操作拖垮应用程序

队列有两个,一个是操作队列-concurrentQueue_operation,一个是助手队列-concurrentQueue_assistant,程序中的日志记录需求直接写入助手队列,避免影响程序频繁写入造成的系统等待。当操作队列中的记录处理完成后,再将助手队列的记录转至操作队列,继续进行比较耗时的写入操作。

当然这种方法在提高系统响应速度的同时,也存在一个弊端,就是在程序崩溃而异常退出时, 可能造成积压在队列中的日志记录未全部完成落地 ,导致日志内容丢失。所以使用时还请权衡利弊,慎重使用。

3. 日志记录类

后续跟新内容:再次感谢评论区的大佬们,博主已经意识到实际上 Nlog 本身已经足够强大,本身就支持队列缓存,此部分就画蛇添足了,不建议使用!

以下代码对 NLog 进行了封装, 将日志记录先存在线程安全的队列里,以避免调用写入文件时 I/O 的耗时操作拖垮应用程序

队列有两个,一个是操作队列-concurrentQueue_operation,一个是助手队列-concurrentQueue_assistant,程序中的日志记录需求直接写入助手队列,避免影响程序频繁写入造成的系统等待。当操作队列中的记录处理完成后,再将助手队列的记录转至操作队列,继续进行比较耗时的写入操作。

当然这种方法在提高系统响应速度的同时,也存在一个弊端,就是在程序崩溃而异常退出时, 可能造成积压在队列中的日志记录未全部完成落地 ,导致日志内容丢失。所以使用时还请权衡利弊,慎重使用。


此部分代码额外添加了 ConcurrentQueue 支持,效果不及 NLog async="true" 的异步方式,不建议参考


参考:C# 超高速高性能写日志 代码开源( cnblogs.com/emrys5/p/fl ) .net core 中的那些常用的日志框架(NLog篇)( cnblogs.com/2828sea/p/1 )


四、日志查看器 TextAnalysisTool.NET

作为一名研发人员,高效率的日志分析是必须的,当然好的工具也是前提条件。

要想高效分析日志,有几个问题需要解决:

  • 快速定位,在海量日志信息中 快速定位 目标行;

  • 高亮显示,以不同颜色显示目标行,以便分类提高辨识度;

  • 只显示有用的行。

在日常开发使用最多的莫过于 NotePad++ 了,尽管其可以通过 “搜索-标记/标记所有-使用格式1/2/3/4/5”的操作来实现以上的前两点,但是操作较繁琐,当日志行数比较多时,也无法仅显示标记行,从而造成效率低下。

当然,对于普通的业务量不太高的日志记录,NotePad++ 足以满足使用。

下面介绍一个非常简单实用的开源日志查看工具 TextAnalysisTool.NET


1. 下载应用程序包

下载完成后,如下图打开最新版的应用程序:


2. 分析的日志文件

按照“File -> Open”选择要打开的日志文件。

双击任意行,便会跳出“Add Filter”窗口:(Text 默认为鼠标焦点行的内容)

可以通过修改 “Text Color”和“Background” 来指定查询结果的 文本和行底色 ,达到高亮显示目的。

其他选项: Description :描述; Excluding :排除,不包含; Case-sensitive :大小写敏感; Regular-expression :按照正则表达式查询。

如下图示例,查询三个语句,标志为不同的行底色效果:

若想 只显示查询目标所在的行 ,可以如下图鼠标操作,也可使用快捷键 Ctrl+H,取消时重复操作即可。

参考:使用TextAnalysisTool来快速提高你分析文本日志的效率( blog.csdn.net/bird67/ar )

作者: 橙子家

原文链接: cnblogs.com/czzj/p/JGP_


版权声明:本文来源于网友收集或网友供稿,仅供学习交流之用,如果有侵权,请转告小编或者留言,本公众号立即删除。



支持小薇



关注公众号:DotNet开发跳槽❀点分享点收藏点点赞点在看
发布于 2023-04-21 10:11 ・IP 属地北京