您的位置首页  散文精选

怎么取消焦点(C#取消焦点)


阅读目录〇、前言一、日志的简单记录二、通过开源库 HslCommunication 记录不同级别的日志三、通过开源库 NLog 实现通过配置文件配置日志选项1. 配置文件2. 测试代码

怎么取消焦点(C#取消焦点)

 

阅读目录〇、前言一、日志的简单记录二、通过开源库 HslCommunication 记录不同级别的日志三、通过开源库 NLog 实现通过配置文件配置日志选项1. 配置文件2. 测试代码3. 日志记录类四、日志查看器 TextAnalysisTool.NET

1. 下载应用程序包2. 分析的日志文件〇、前言相信你在实际工作期间经常遇到或听到这样的说法:  “我现在加一下日志,等会儿你再操作下”  “只有在程序出问题以后才会知道打一个好的日志有多么重要”可见日志的记录是日常开发的必备技能。

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

记录日志的三种实现:当业务比较简单,性能要求不高,只是单纯的记录程序的运行是否正常此时就可以参考本文第一种实现,仅一种级别的文本记录当业务复杂较复杂,对性能有一定要求时,可以根据实际情况,参考本文的第二、第三种实现。

当业务非常复杂,必然运行的效率就要求比较高,如何即让程序稳定高效的运行,又能合理记录程序运行状态成为关键高效的的日志操作可以参考本文的第三种实现一、日志的简单记录如下,为简单的记录开发人员预输出的文本内容,其内容为自定义,输出的时间格式和固定标识需相同。

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

日志内容测试结果:publicstaticstring strlock = string.Empty;staticvoidMain(string[] args){lock(strlock) // 在同一个日志文件操作范围添加同一个锁,避免多线程操作时因抢占资源而报错

{WriteLogPublic.WriteLogFunStr("Program", "Main", "日志内容1");// 实际生成的路径:C:\Logs\Program\Main\202304\log07.log

// 记录的内容:2023-04-07 11-21-31 --- 日志内容1}}日志类内容:publicclassWriteLogPublic{////// 记录日志///

///项目名称///控制器名称///

日志内容publicstaticvoidWriteLogFunStr(string projectname, string controllername, string strlog){

string sfilepath = $"C:\\Logs\\{projectname}\\{controllername}\\{DateTime.Now.ToString("yyyyMM")}"; // 根据项目名称等创建文件夹

string sfilename = $"log{DateTime.Now.ToString("dd")}.log";sfilename = sfilepath + "\\" + sfilename;

// 文件的绝对路径// if (!Directory.Exists(sfilepath)) // 验证路径是否存在(此句可省略,因为 CreateDirectory 方法创建文件路径前会判断是否存在)

Directory.CreateDirectory(sfilepath); // 不存在则创建using (FileStream fs = new FileStream(sfilename, FileMode.OpenOrCreate, FileAccess.Write))

{using (var sw = new StreamWriter(fs)){sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + " --- "

+ strlog);}}}}回到顶部二、通过开源库 HslCommunication 记录不同级别的日志此方式记录日志,简单高效,可以实现不同级别日志的输出控制,日志选项的配置可以配置在程序的配置文件中,在程序启动时加载即可。

若想实现实时加载,这只能在每次写日志前初始化日志对象,这样估计就影响程序性能了日志内容测试结果:staticvoidMain(string[] args){// 先初始化配置 HslCommunicationOper。

HslCommunicationOper.HslComLogCollection("Test.ConsoleApp", "Main", 5, HslCommunication.LogNet.GenerateMode.ByEveryHour);

// HslCommunicationOper.HslComLog("Test.ConsoleApp", "Main"); // 单文件// HslCommunicationOper.HslComLogSize("Test.ConsoleApp", "MainSize", 5); // 增加日志单文件大小配置

// HslCommunicationOper.HslComLogByDate("Test.ConsoleApp", "MainDate", TimeType.Day); // 按照日期分文件保存HslCommunicationOper.SetMessageDegree(MessageDegree.WARN);

//日志级别// 记录日志HslCommunicationOper.logNet.WriteDebug("调试信息");HslCommunicationOper.logNet.WriteInfo("一般信息"

);HslCommunicationOper.logNet.WriteWarn("警告信息");HslCommunicationOper.logNet.WriteError("错误信息");HslCommunicationOper.logNet.WriteFatal(

"致命信息");HslCommunicationOper.logNet.WriteDebug("KeyWord调试信息", "调试信息");HslCommunicationOper.logNet.WriteInfo(

"KeyWord一般信息", "一般信息");HslCommunicationOper.logNet.WriteWarn("KeyWord警告信息", "警告信息");HslCommunicationOper.logNet.WriteError(

"KeyWord错误信息", "错误信息");HslCommunicationOper.logNet.WriteFatal("KeyWord致命信息", "致命信息");HslCommunicationOper.logNet.WriteException(

"KeyWord-WriteException", new IndexOutOfRangeException());HslCommunicationOper.logNet.WriteDebug("调试信息"

);HslCommunicationOper.logNet.WriteInfo("一般信息");HslCommunicationOper.logNet.WriteWarn("警告信息");HslCommunicationOper.logNet.WriteError(

"错误信息");HslCommunicationOper.logNet.WriteFatal("致命信息");}// 日志输出格式示例:[警告] 2023-04-0718:22:03.565 Thread:[

001] 警告信息[错误] 2023-04-0718:22:03.605 Thread:[001] 错误信息[致命] 2023-04-0718:22:03.605 Thread:[001] 致命信息[警告]

2023-04-0718:22:03.605 Thread:[001] KeyWord警告信息 : 警告信息[错误] 2023-04-0718:22:03.605 Thread:[001] KeyWord错误信息 : 错误信息

[致命] 2023-04-0718:22:03.605 Thread:[001] KeyWord致命信息 : 致命信息[致命] 2023-04-0718:22:03.676 Thread:[001] KeyWord-WriteException : 错误信息:Index was outside the bounds of the array.

错误源:错误堆栈:错误类型:System.IndexOutOfRangeException错误方法:/=================================================[ Exception ]================================================/

[警告] 2023-04-0718:22:03.676 Thread:[001] 警告信息[错误] 2023-04-0718:22:03.676 Thread:[001] 错误信息[致命] 2023-04

-0718:22:03.676 Thread:[001] 致命信息三个相关日志类:HslCommunicationOper:操作类;LogNetCollection:扩展类(提供日志文件的大小、生成新文件频率的配置);

MessageDegree:消息级别枚举publicstaticclassHslCommunicationOper{publicstatic ILogNet logNet = null;///。

/// 日志文件根目录///publicstaticstring rootpath = "C:\\Log";////// 单日志文件存储//////

///日志文件名publicstaticvoidHslComLog(string

projectname, string opername){logNet = new LogNetSingle($"{rootpath}\\{projectname}\\{opername}.txt"

);logNet.SetMessageDegree(HslMessageDegree.DEBUG); // 默认存储最低级别为 DEBUG}////// 限定日志文件大小///

//////日志上级文件夹名///

日志文件大小(单位:M) 1~20,默认 5publicstaticvoidHslComLogSize(string projectname, string opername, int logfilesize =

5){if (logfilesize 20)logfilesize = 5;logNet = new LogNetFileSize($"{rootpath}\\{projectname}\\{opername}"

, logfilesize * 1024 * 1024); // 单位M(5M):5 * 1024 * 1024logNet.SetMessageDegree(HslMessageDegree.DEBUG);

// 默认存储最低级别为 DEBUG}////// 按照日期存储/////////

日志上级文件夹名///传入枚举类型(TimeType),值范围:Minute、Hour、Day、Month、Season、Year

publicstaticvoidHslComLogByDate(string projectname, string opername, GenerateMode generateMode = GenerateMode.ByEveryDay)

{logNet = new LogNetDateTime($"{rootpath}\\{projectname}\\{opername}", generateMode); // 按每天logNet.SetMessageDegree(HslMessageDegree.DEBUG);

// 默认存储最低级别为 DEBUG}////// 按照文件或日期存储/////////

日志上级文件夹名///传入枚举类型 GenerateModepublicstaticvoidHslComLogCollection

(string projectname, string opername, int filesize, GenerateMode generateMode = GenerateMode.ByEveryDay)

{logNet = new LogNetCollection($"{rootpath}\\{projectname}\\{opername}", filesize * 1024 * 1024, generateMode);

logNet.SetMessageDegree(HslMessageDegree.DEBUG); // 默认存储最低级别为 DEBUG}////// 单独配置日志级别///

///默认 DEBUGpublicstaticvoidSetMessageDegree(MessageDegree messageDegree = MessageDegree.DEBUG)

{switch (messageDegree){case MessageDegree.DEBUG:logNet.SetMessageDegree(HslMessageDegree.DEBUG); // 所有等级存储

break;case MessageDegree.INFO:logNet.SetMessageDegree(HslMessageDegree.INFO); // 除 DEBUG 外,都存储break;case

MessageDegree.WARN:logNet.SetMessageDegree(HslMessageDegree.WARN); // 除 DEBUG 和 INFO 外,都存储break;case

MessageDegree.ERROR:logNet.SetMessageDegree(HslMessageDegree.ERROR); // 只存储 ERROR 和 FATALbreak;case MessageDegree.FATAL:

logNet.SetMessageDegree(HslMessageDegree.FATAL); // 只存储 FATALbreak;case MessageDegree.None:logNet.SetMessageDegree(HslMessageDegree.None);

// 不存储任何等级break;}}}publicclassLogNetCollection : LogPathBase, ILogNet, IDisposable{privateint fileMaxSize =

10485760; // 默认 10Mprivateint currentFileSize = 0;private GenerateMode generateMode = GenerateMode.ByEveryYear;

publicLogNetCollection(string filePath, int fileMaxSize = 10485760, GenerateMode generateMode = GenerateMode.ByEveryDay,

int fileQuantity = -1){base.filePath = filePath;this.fileMaxSize = fileMaxSize;this.generateMode = generateMode;

controlFileQuantity = fileQuantity;base.LogSaveMode = LogSaveMode.FileFixedSize;if (!string.IsNullOrEmpty(filePath) && !Directory.Exists(filePath))

{Directory.CreateDirectory(filePath);}}protectedoverridestringGetFileSaveName(){if (string.IsNullOrEmpty(filePath))

{returnstring.Empty;}if (string.IsNullOrEmpty(fileName)){fileName = GetLastAccessFileName();}if (File.Exists(fileName))

{FileInfo fileInfo = new FileInfo(fileName);if (fileInfo.Length > fileMaxSize){fileName = GetDefaultFileName();

}else{currentFileSize = (int)fileInfo.Length;}}return fileName;}privatestringGetLastAccessFileName(){

string[] existLogFileNames = GetExistLogFileNames();foreach (string result in existLogFileNames){FileInfo fileInfo =

new FileInfo(result);if (fileInfo.Length < fileMaxSize) // 判断已创建的日志文件是否达到最大内存{currentFileSize = (int)fileInfo.Length;

return result;}}return GetDefaultFileName(); // 若未创建过,通过指定方式创建}privatestringGetDefaultFileName(){switch

(generateMode){case GenerateMode.ByEveryMinute:return Path.Combine(filePath, "Logs_" + DateTime.Now.ToString(

"yyyyMMdd_HHmm") + ".txt");case GenerateMode.ByEveryHour:return Path.Combine(filePath, "Logs_" + DateTime.Now.ToString(

"yyyyMMdd_HH") + ".txt");case GenerateMode.ByEveryDay:return Path.Combine(filePath, "Logs_" + DateTime.Now.ToString(

"yyyyMMdd") + ".txt");case GenerateMode.ByEveryWeek:{GregorianCalendar gregorianCalendar = new GregorianCalendar();

int weekOfYear = gregorianCalendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstDay, DayOfWeek.Monday);

return Path.Combine(filePath, "Logs_" + DateTime.Now.Year + "_W" + weekOfYear + ".txt");}case GenerateMode.ByEveryMonth:

return Path.Combine(filePath, "Logs_" + DateTime.Now.ToString("yyyy_MM") + ".txt");case GenerateMode.ByEverySeason:

return Path.Combine(filePath, "Logs_" + DateTime.Now.Year + "_Q" + (DateTime.Now.Month / 3 + 1) + ".txt"

);case GenerateMode.ByEveryYear:return Path.Combine(filePath, "Logs_" + DateTime.Now.Year + ".txt");default

:returnstring.Empty;}}publicoverridestringToString(){return$"LogNetFileSize[{fileMaxSize}];LogNetDateTime[{generateMode}]"

;}}////// 消息级别///publicenum MessageDegree{DEBUG = 1,INFO = 2,WARN = 3,ERROR = 4,FATAL =

5,None = 9} 参考:C# 日志记录分级功能使用 按照日期,大小,或是单文件存储( cnblogs.com/dathlin/p/7691693.html)三、通过开源库 NLog 实现通过配置文件配置日志选项

 NLog 是一个基于 .net 平台编写的日志记录类库,我们可以使用 NLog 在应用程序中添加极为完善的跟踪调试代码 本文将通过日志框架 Nlog 和 ConcurrentQueue 队列,实现一个高性能的日志库。

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

NLog 支持结构化和传统日志记录NLog 的特点: 高性能、易于使用、易于扩展和灵活配置ConcurrentQueue:表示线程安全的先进先出(FIFO)集合所有公共成员和受保护成员 ConcurrentQueue 都是线程安全的,可以从多个线程并发使用。

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 。

示例如下:

host="localhost" />  NLog 4.0 之后,与 

NLog.dll 同目录下名如 NLog*.dll 的程序集(如:NLog.CustomTarget.dll)会被自动加载5/5 includes - 指定当前配置文件包含多个子配置文件  通过 ${} 语法可以使用环境变量,下例展示包含一个名为当前机器名的配置文件。

......  NLog 4.4.2 之后可以使用通配符 * 指定多个文件例如:。

示例配置:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"

autoReload="true"throwExceptions="false"internalLogLevel="Off"internalLogFile="c:\temp\nlog-internal.log"

>

layout="${longdate} [${uppercase:${level}}] ${callsite}(${callsite-filename:includeSourcePath=False}:${callsite-linenumber}) - ${message} ${exception:format=ToString}"

/>

="${longdate} [${uppercase:${level}}] ${callsite}(${callsite-filename:includeSourcePath=False}:${callsite-linenumber}) - ${message} ${exception:format=ToString}"

maxArchiveFiles="999"archiveFileName="${basedir}/logs/${appName}-${shortdate}-${###}.log"createDirs="true"

archiveAboveSize="102400"archiveEvery="Day"encoding="UTF-8" />

="Debug"writeTo="logfile" />参考:完善 .Net Core 项目 — NLog入门 (日志组件)(zhuanlan.zhihu.com/p/35469359)

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

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

/>......2. 测试代码staticvoidMain(string[] args){try{LoggerHelper._.Info(

$"完成");LoggerHelper._.Debug($"Debug完成");LoggerHelper._.Error($"Error完成");throw (new Exception());}catch

(Exception ex){LoggerHelper._.Error(ex.Message);}}// 输出日志2023-04-0417:14:45.6651 [INFO] YOKAVerse.Net.Log.LoggerHelper.Info(Logger.cs:

40) - 完成2023-04-0417:14:46.7303 [DEBUG] YOKAVerse.Net.Log.LoggerHelper.Debug(Logger.cs:28) - Debug完成2023

-04-0417:14:47.2924 [ERROR] YOKAVerse.Net.Log.LoggerHelper.Error(Logger.cs:76) - Error完成2023-04-0417:

14:49.5869 [ERROR] YOKAVerse.Net.Log.LoggerHelper.Error(Logger.cs:76) - Exception of type System.Exception

was thrown.3. 日志记录类后续跟新内容:再次感谢评论区的大佬们,博主已经意识到实际上 Nlog 本身已经足够强大,本身就支持队列缓存,此部分就画蛇添足了,不建议使用!以下代码对 NLog 进行了封装,

将日志记录先存在线程安全的队列里,以避免调用写入文件时 I/O 的耗时操作拖垮应用程序队列有两个,一个是操作队列-concurrentQueue_operation,一个是助手队列-concurrentQueue_assistant,程序中的日志记录需求直接写入助手队列,避免影响程序频繁写入造成的系统等待。

当操作队列中的记录处理完成后,再将助手队列的记录转至操作队列,继续进行比较耗时的写入操作当然这种方法在提高系统响应速度的同时,也存在一个弊端,就是在程序崩溃而异常退出时,可能造成积压在队列中的日志记录未全部完成落地

,导致日志内容丢失所以使用时还请权衡利弊,慎重使用3. 日志记录类后续跟新内容:再次感谢评论区的大佬们,博主已经意识到实际上 Nlog 本身已经足够强大,本身就支持队列缓存,此部分就画蛇添足了,不建议使用!。

以下代码对 NLog 进行了封装,将日志记录先存在线程安全的队列里,以避免调用写入文件时 I/O 的耗时操作拖垮应用程序队列有两个,一个是操作队列-concurrentQueue_operation,一个是助手队列-concurrentQueue_assistant,程序中的日志记录需求直接写入助手队列,避免影响程序频繁写入造成的系统等待。

当操作队列中的记录处理完成后,再将助手队列的记录转至操作队列,继续进行比较耗时的写入操作当然这种方法在提高系统响应速度的同时,也存在一个弊端,就是在程序崩溃而异常退出时,可能造成积压在队列中的日志记录未全部完成落地

,导致日志内容丢失所以使用时还请权衡利弊,慎重使用此部分代码额外添加了 ConcurrentQueue 支持,效果不及 NLog async="true" 的异步方式,不建议参考publicclassLoggerHelper

{////// 实例化nLog,即为获取配置文件相关信息(获取以当前正在初始化的类命名的记录器)///privatereadonly NLog.Logger logger = LogManager.GetCurrentClassLogger();

privatestatic LoggerHelper _obj;////// 辅助队列///privatestatic ConcurrentQueue concurrentQueue_assistant =

new ConcurrentQueue();////// 操作队列///privatestatic ConcurrentQueue concurrentQueue_operation =

new ConcurrentQueue();privatestaticstring lockobj_assistant = string.Empty;privatestaticstring

lockobj_operation = string.Empty;publicstatic LoggerHelper LHR{get => _obj ?? (_obj = new LoggerHelper());

set => _obj = value;}publicLoggerHelper(){InitializeTask();}privatestatic LogModel logModel_init = null

;////// 初始化后台线程///privatevoidInitializeTask(){if (logModel_init == null){logModel_init =

new LogModel();Thread t = new Thread(new ThreadStart(LogOperation));t.IsBackground = false;t.Start();

}}////// 记录日志///privatevoidLogOperation(){while (true) // 线程持续处理{if (concurrentQueue_assistant.Count >

0 && concurrentQueue_operation.Count == 0){lock (lockobj_assistant){concurrentQueue_operation = concurrentQueue_assistant;

// 将数据转至操作队列concurrentQueue_assistant = new ConcurrentQueue(); // 注意此处不可用 .Clear() 因为 ConcurrentQueue 为引用类型

}LogModel logModel;// 取出队列 concurrentQueue_operation 中待写入的日志记录,直至全部记录完成while (concurrentQueue_operation.Count >

0 && concurrentQueue_operation.TryDequeue(out logModel)){switch (logModel.type) // 日志类型分流{case NLogLevel.Trace:

if (logModel.exobj != null)logger.Trace(logModel.content);elselogger.Trace(logModel.content, logModel.exobj);

break;case NLogLevel.Debug:if (logModel.exobj != null)logger.Debug(logModel.content);elselogger.Debug(logModel.content, logModel.exobj);

break;case NLogLevel.Info:if (logModel.exobj != null)logger.Info(logModel.content, logModel.exobj);else

logger.Info(logModel.content);break;case NLogLevel.Error:if (logModel.exobj != null)logger.Error(logModel.content, logModel.exobj);

elselogger.Error(logModel.content);break;case NLogLevel.Warn:if (logModel.exobj != null)logger.Warn(logModel.content, logModel.exobj);

elselogger.Warn(logModel.content);break;case NLogLevel.Fatal:if (logModel.exobj != null)logger.Fatal(logModel.content, logModel.exobj);

elselogger.Fatal(logModel.content);break;default:break;}}}elseThread.Sleep(1000);}}////// 加入队列前,根据日志级别统一验证

//////publicvoidEnqueueLogModel(LogModel logModel){if ((logModel.type == NLogLevel.Trace && logger.IsTraceEnabled) || (logModel.type == NLogLevel.Debug && logger.IsDebugEnabled)

|| (logModel.type == NLogLevel.Info && logger.IsInfoEnabled) || (logModel.type == NLogLevel.Warn && logger.IsWarnEnabled)

|| (logModel.type == NLogLevel.Error && logger.IsErrorEnabled) || (logModel.type == NLogLevel.Fatal && logger.IsFatalEnabled))

{lock (lockobj_assistant){concurrentQueue_assistant.Enqueue(logModel);}}}////// Trace,追踪,非常详细的日志,该日志等级通常仅在开发过程中被使用

//////publicvoidTrace(string logcontent){EnqueueLogModel(new LogModel() { type = NLogLevel.Trace, content = logcontent });

}publicvoidTrace(string logcontent, Exception exception){EnqueueLogModel(new LogModel() { type = NLogLevel.Trace, content = logcontent, exobj = exception });

}////// Debug,调试,详尽信息次于 Trace,在生产环境中通常不启用//////publicvoid

Debug(string logcontent){EnqueueLogModel(new LogModel() { type = NLogLevel.Debug, content = logcontent });

}publicvoidDebug(string logcontent, Exception exception){EnqueueLogModel(new LogModel() { type = NLogLevel.Debug, content = logcontent, exobj = exception });

}////// Info,信息,通常在生产环境中通常启用//////publicvoidInfo(string logcontent)

{EnqueueLogModel(new LogModel() { type = NLogLevel.Info, content = logcontent });}publicvoidInfo(string

logcontent, Exception exception){EnqueueLogModel(new LogModel() { type = NLogLevel.Info, content = logcontent, exobj = exception });

}////// Warn,警告,通常用于非关键问题,这些问题可以恢复,或者是暂时的故障//////publicvoid

Warn(string logcontent){EnqueueLogModel(new LogModel() { type = NLogLevel.Warn, content = logcontent });

}publicvoidWarn(string logcontent, Exception exception){EnqueueLogModel(new LogModel() { type = NLogLevel.Warn, content = logcontent, exobj = exception });

}////// Error,错误,多数情况下记录Exceptions(异常)信息//////publicvoid

Error(string logcontent){EnqueueLogModel(new LogModel() { type = NLogLevel.Error, content = logcontent });

}publicvoidError(string logcontent, Exception exception){EnqueueLogModel(new LogModel() { type = NLogLevel.Error, content = logcontent, exobj = exception });

}////// Fatal,致命错误,非常严重的错误//////publicvoidFatal(string logcontent)

{EnqueueLogModel(new LogModel() { type = NLogLevel.Fatal, content = logcontent });}publicvoidFatal(string

logcontent, Exception exception){EnqueueLogModel(new LogModel() { type = NLogLevel.Fatal, content = logcontent, exobj = exception });

}}publicclassLogModel{public NLogLevel type { get; set; }publicstring content { get; set; }public Exception exobj {

get; set; }}////// NLog 日志等级///publicenum NLogLevel{Trace,Debug,Info,Warn,Error,Fatal

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

四、日志查看器 TextAnalysisTool.NET作为一名研发人员,高效率的日志分析是必须的,当然好的工具也是前提条件要想高效分析日志,有几个问题需要解决:快速定位,在海量日志信息中快速定位目标行;。

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

当然,对于普通的业务量不太高的日志记录,NotePad++ 足以满足使用下面介绍一个非常简单实用的开源日志查看工具 TextAnalysisTool.NET官网地址:http://textanalysistool.github.io/ 。

用法地址:http://textanalysistool.github.io/TextAnalysisTool.NET.txt  1. 下载应用程序包下载地址:http://github.com/TextAnalysisTool/Releases/raw/master/TextAnalysisTool.NET.zip 

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

2. 分析的日志文件按照“File -> Open”选择要打开的日志文件。双击任意行,便会跳出“Add Filter”窗口:(Text 默认为鼠标焦点行的内容)

可以通过修改“Text Color”和“Background”来指定查询结果的文本和行底色,达到高亮显示目的其他选项:Description:描述;Excluding:排除,不包含;Case-sensitive。

:大小写敏感;Regular-expression:按照正则表达式查询。如下图示例,查询三个语句,标志为不同的行底色效果:

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

参考:使用TextAnalysisTool来快速提高你分析文本日志的效率(https://blog.csdn.net/bird67/article/details/100702261)作者:橙子家原文链接:

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

支持小薇关注公众号:DotNet开发跳槽❀

点分享

点收藏

点点赞

点在看

免责声明:本站所有信息均搜集自互联网,并不代表本站观点,本站不对其真实合法性负责。如有信息侵犯了您的权益,请告知,本站将立刻处理。联系QQ:1640731186