【框架学习与探究之日志组件--Log4Net与NLog】
前言
本文欢迎转载,作者原创地址:http://www.cnblogs.com/DjlNet/p/7604340.html
序
近日,天气渐冷,懒惰的脑虫又开始作祟了,导致近日内功修炼迟迟未能进步,依然徘徊在XXX框架学习当中,当然了并不是说这种学习不好,只是感觉收益不高,但是今天博主依然还是老酒新装,把在单体应用架构当中对于Log这块使用最平凡的两款日志组件拿来说道一二,也是对后面框架集成做好铺垫的准备....其实也算是对框架学习系列的一个凑数行为,捂脸.....
抛出问题和思考
按照国际惯例,这里还是给出各自的官方地址,Log4net:https://logging.apache.org/log4net/ , Nlog :http://nlog-project.org/,这里博主可能就不会去一一解释各种组件当中的重要元素、关键类以及使用API和关于Provider的配置了,这里着重还是博主自己工作或者项目当中常规使用到的一些东西备份记录,所以想看详细解读的同学,可以移步去官方链接或者搜索园中其他相关文,所以老司机就可能需要绕道儿了....其实就目前项目使用log组件程度而言,多半是用来记录应用程序日志的,且大多数是以文本的方式(也就是txt、log)来记录日志,方便在程序上线之后免于远程调试以及不好跟踪的问题,那么问题来了,应用程序大家也知道日积月累的产生的日志量,肯定是很多的,那么为了方便我们好去跟踪问题,应该怎么样去分类存储日志文件方便开发者追溯问题!!!多说一句,当我们的API服务成百上千,我们的应用程序或者系统几十上百,那么这个时候我们的日志还处于单体应用体系的话,一条完整的服务调用连的日志跟踪就是一个大麻烦,亦或者需要统筹各自应用的异常行为和错误数据等等,所以当我们的形态达到一定规模之后,我们需要的就是分布式日志处理分析的平台,关键词:ELK 请自行搜索,感叹社区轮子的威力,不过那都是后话了.....
Log4net处理方案
这里我们按照上面的需求和限定范围得知,log4net 日志框架组件历史由来已久且在使用性和或灵活性上面都颇为好评,众所周知我们的日志等级分为: DEBUG、INFO、WARN、ERROR、FATAL,日志等级由低到高的一个过程,所以这个等级分类也是我们需要参考的一个点,其次就是需要按照年份、月份来划分文件夹,最后才是以日期作为文件名,log作为文件后缀名(txt一样),按照如上所说需要配置的 log4net.config 配置如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<!--添加自定义节点:log4net type:解析类名,程序集名(log4net.dll)-->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<root>
<!--<level value="DEBUG"/>-->
<!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
<!--比如定义级别为INFO,则INFO级别向下的级别,比如DEBUG日志将不会被记录-->
<level value="ALL"/>
<!--根据log级别记录到不同的日志文件-->
<appender-ref ref="DebugLogger" />
<appender-ref ref="InfoLogger" />
<appender-ref ref="WarnLogger" />
<appender-ref ref="ErrorLogger" />
<appender-ref ref="FatalLogger" />
</root>
<!--Debug文件日志记录器-->
<appender name="DebugLogger" type="log4net.Appender.RollingFileAppender">
<!--日志存放文件夹-->
<file value="Log\Debug\"/>
<!--是否追加到文件-->
<appendToFile value="true" />
<!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!--使用UTF-8编码-->
<Encoding value="UTF-8" />
<!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
<maxSizeRollBackups value="-1"/>
<!--是否只写到一个文件中-->
<StaticLogFileName value="false"/>
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date" />
<!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
<param name="datePattern" value="yyyy/yyyy-MM/yyyy-MM-dd.'log'" />
<!--过滤设置,LevelRangeFilter为使用的过滤器。-->
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="DEBUG" />
</filter>
<!--日志格式-->
<layout type="log4net.Layout.PatternLayout">
<!-- 输出格式 日期,日志级别,消息,换行-->
<param name="ConversionPattern" value="%date [%-5p] %message%n" />
</layout>
</appender>
<!--InfoLog文件日志记录器-->
<appender name="InfoLogger" type="log4net.Appender.RollingFileAppender">
<!--日志存放文件夹-->
<file value="Log\Info\"/>
<!--是否追加到文件-->
<appendToFile value="true" />
<!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!--使用UTF-8编码-->
<Encoding value="UTF-8" />
<!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
<maxSizeRollBackups value="-1"/>
<!--是否只写到一个文件中-->
<StaticLogFileName value="false"/>
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date" />
<!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
<param name="datePattern" value="yyyy/yyyy-MM/yyyy-MM-dd.'log'" />
<!--过滤设置,LevelRangeFilter为使用的过滤器。-->
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="INFO" />
</filter>
<!--日志格式-->
<layout type="log4net.Layout.PatternLayout">
<!-- 输出格式 日期,日志级别,消息,换行-->
<param name="ConversionPattern" value="%date [%-5p] %message%n" />
</layout>
</appender>
<!--WarnLog文件日志记录器-->
<appender name="WarnLogger" type="log4net.Appender.RollingFileAppender">
<!--日志存放文件夹-->
<file value="Log\Warn\"/>
<!--是否追加到文件-->
<appendToFile value="true" />
<!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!--使用UTF-8编码-->
<Encoding value="UTF-8" />
<!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
<maxSizeRollBackups value="-1"/>
<!--是否只写到一个文件中-->
<StaticLogFileName value="false"/>
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date" />
<!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
<param name="datePattern" value="yyyy/yyyy-MM/yyyy-MM-dd.'log'" />
<!--过滤设置,LevelRangeFilter为使用的过滤器。-->
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="WARN" />
<levelMax value="WARN" />
</filter>
<!--日志格式-->
<layout type="log4net.Layout.PatternLayout">
<!-- 输出格式 日期,日志级别,消息,换行-->
<param name="ConversionPattern" value="%date [%-5p] %message%n" />
</layout>
</appender>
<!--ErrorLog文件日志记录器-->
<appender name="ErrorLogger" type="log4net.Appender.RollingFileAppender">
<!--日志存放文件夹-->
<file value="Log\Error\"/>
<!--是否追加到文件-->
<appendToFile value="true" />
<!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!--使用UTF-8编码-->
<Encoding value="UTF-8" />
<!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
<maxSizeRollBackups value="-1"/>
<!--是否只写到一个文件中-->
<StaticLogFileName value="false"/>
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date" />
<!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
<param name="datePattern" value="yyyy/yyyy-MM/yyyy-MM-dd.'log'" />
<!--过滤设置,LevelRangeFilter为使用的过滤器。-->
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR" />
<levelMax value="ERROR" />
</filter>
<!--日志格式-->
<layout type="log4net.Layout.PatternLayout">
<!-- 输出格式 日期,日志级别,消息,换行-->
<param name="ConversionPattern" value="%date [%-5p] %message%n" />
</layout>
</appender>
<!--FatalLog文件日志记录器-->
<appender name="FatalLogger" type="log4net.Appender.RollingFileAppender">
<!--日志存放文件夹-->
<file value="Log\Fatal\"/>
<!--是否追加到文件-->
<appendToFile value="true" />
<!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!--使用UTF-8编码-->
<Encoding value="UTF-8" />
<!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
<maxSizeRollBackups value="-1"/>
<!--是否只写到一个文件中-->
<StaticLogFileName value="false"/>
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date" />
<!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
<param name="datePattern" value="yyyy/yyyy-MM/yyyy-MM-dd.'log'" />
<!--过滤设置,LevelRangeFilter为使用的过滤器。-->
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="FATAL" />
<levelMax value="FATAL" />
</filter>
<!--日志格式-->
<layout type="log4net.Layout.PatternLayout">
<!-- 输出格式 日期,日志级别,消息,换行-->
<param name="ConversionPattern" value="%date [%-5p] %message%n" />
</layout>
</appender>
</log4net>
</configuration>
上面的配置楼主已经亲测可以是使用了,且已经按照我们的需求按照日志等级(这里是通过logger对应的filter来控制的)、年份、月份、日期这个要点分类存储了日志文件,且不同等级的日志文件存储在对应等级的文件夹下面,配置文件当中有较为详细的说明可以参考自己的需求自定义配置,例如修改为自己的layout展示效果等等,文件存储效果如下图:


从上图就可以看出基本满足了我们日常单体应用开发的需求了......这里贴出文件配置也是博主借此备份一下,日后好找....至于说怎么使用、异步还是同步那就看各位同学自己把握和封装了....,如果哪位老铁有更好的方式可以告知一二!!!
NLog处理方案
需求还是同上逻辑,且我们使用NLog依然还是以file作为基础实现配置,话不多说Nlog.config 完整配置如下:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
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" throwConfigExceptions="true">
<!-- optional, add some variables
https://github.com/nlog/NLog/wiki/Configuration-file#variables
-->
<!--<variable name="myvar" value="myvalue"/>-->
<variable name="year" value="${date:format=yyyy}"/>
<variable name="year_month" value="${date:format=yyyy-MM}"/>
<!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<!-- all targets in this section will automatically be asynchronous -->
<targets async="true">
<!--
add your targets here
See https://github.com/nlog/NLog/wiki/Targets for possible targets.
See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
-->
<!--
Write events to a file with the date in the filename.
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
-->
<target xsi:type="AsyncWrapper" name="MyLogger">
<target xsi:type="File"
layout="${longdate} ${uppercase:${level}} ${message}"
fileName="${basedir}/Log/${level}/${year}/${year_month}/${shortdate}.log" encoding="utf-8" />
</target>
</targets>
<rules>
<!-- add your logging rules here -->
<logger name="*" minlevel="Trace" maxlevel="Fatal" writeTo="MyLogger" />
<!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" />
-->
</rules>
</nlog>
注意这里的 nlog.config 配置想比较与log4net.config就简单许多,且通过wapper的方式就可以支持异步写入文件,注意这里需要自定义 variable 来达到以年份、月份建立对应文件夹存储日期命名的日志文件,因为这里 nlog 本身木有提供 ${year} 这种类似参数,所以需要自定义配置使用,还好 nlog 考虑到了这方面的灵活性,效果图参考如下:和log4net效果一致.....且对应日志等级的文件写入对应的等级文件夹中,至于更多的配置参考官方或者github wiki 吧

小总结
虽然这两个日志框架,我相信大多人都在使用且也知道一些组织结构或者调用API等等,所以博主这里算是“翻旧账”的行为了,主要是还是对常规日志文件存储的一个备份配置的小文章,途中也查询了相关资料,其实还有很多例如 layout 以及 header + footer 的消息美化,亦或者实现数据库,nosql存储日志等等,都看各自的需求,当然我们在使用日志组件的时候肯定是集成在系统中去使用的,那么何时我们用静态工具类LogHelper的方式还是ILog接口注入的方式呐,相信大家都有各自的理解视情况而定的吧......
【框架学习与探究之日志组件--Log4Net与NLog】的更多相关文章
- .Netcore之日志组件Log4net、Nlog性能比较
转载请注明出处http://www.cnblogs.com/supernebula/p/7506993.html .Netcore之Log4net.Nlog性能比较 最近在写一个开源.netcore ...
- .Net core2.0日志组件Log4net、Nlog简单性能测试
.Net core之Log4net.Nlog简单性能测试 比较log4net.nlog的文件写入性能(.netcore环境),涉及代码和配置如有不正确的地方,还请批评指正. 原创,转载请著名出处:ht ...
- 【框架学习与探究之消息队列--EasyNetQ(2)】
声明 本文欢迎转载,系博主原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7654902.html 前言 此文章,是承接上篇:[框架学习与探究之消息队列--Ea ...
- 4.VUE前端框架学习记录四:Vue组件化编码2
VUE前端框架学习记录四:Vue组件化编码2文字信息没办法描述清楚,主要看编码Demo里面,有附带完整的代码下载地址,有需要的同学到脑图里面自取.脑图地址http://naotu.baidu.com/ ...
- 3.VUE前端框架学习记录三:Vue组件化编码1
VUE前端框架学习记录三:Vue组件化编码1文字信息没办法描述清楚,主要看编码Demo里面,有附带完整的代码下载地址,有需要的同学到脑图里面自取.脑图地址http://naotu.baidu.com/ ...
- ABP .Net Core 日志组件集成使用NLog
一.说明 NLog介绍和使用说明官网:http://nlog-project.org/ NLog和Log4net对比:https://www.cnblogs.com/qinjin/p/5134982. ...
- 【框架学习与探究之宿主服务--Topshelf】
前言 此文欢迎转载,原始链接地址:http://www.cnblogs.com/DjlNet/p/7603819.html 正文 原先也偶然见过这个关键词,当时只是有个大致了解貌似和WinServic ...
- 【框架学习与探究之定时器--Quartz.Net 】
声明 本文欢迎转载,原文地址:http://www.cnblogs.com/DjlNet/p/7572174.html 前言 这里相信大部分玩家之前现在都应该有过使用定时器的时候或者需求,例如什么定时 ...
- 【框架学习与探究之定时器--Hangfire】
声明 本文欢迎转载,请注明文章原始出处:http://www.cnblogs.com/DjlNet/p/7603632.html 前言 在上篇文章当中我们知道关于Quartz.NET的一些情况,其实博 ...
随机推荐
- JS中var和let
前 言 JavaScript 大家都知道声明一个变量时,通常会用'var'来声明,但是在ES6中,定义了另一个关键字'let'.今天我就为大家带来'var'与'let'这两个关键字声明有何异同 ...
- 简单Elixir游戏服设计-玩家进程跑起来
有了玩家模型,我们试试让玩家进程跑起来. 需要搞个PlayerSupervisor来负责启动和监控玩家进程. defmodule PlayerSupervisor do use Supervisor ...
- GRE 协议简介
1. 协议简介 gre(generic routing encapsulation,通用路由封装)协议是对某些网络层协议(如ip 和ipx)的数据报进行封装,使这些被封装的数据报能够在另一个网络 ...
- Spring ——简介及环境搭建跑通Hello
Spring Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用.是为了解决企业应用程序开发复杂性而创建的.框架的主要优 ...
- 第三章 MySQL高级查询(一)
第三章 MySQL高级查询(一) 一.SQL语言的四个分类 1. DML(Data Manipulation Language)(数据操作语言):用来插入,修改和删除表中的数据,如INSE ...
- DevOps之服务-监控工具
唠叨话 关于德语噢屁事的知识点,仅提供精华汇总,具体知识点细节,参考教程网址,如需帮助,请留言. <DevOps教程> <DevOps之服务-监控工具> 注:关于监控工具的具体 ...
- break和continue 的区别
区别 break和continue都可在循环语句里面使用,也都可以控制外层的循环.但是continue只能在循环语句里面使用,break也可以使用在switch语句里面. break具体作用在循环语句 ...
- 作为前端Web开发者,这12个终端命令不可不会
对于开发人员来说,终端是最重要的工具之一.掌握终端,能够有效的提升开发人员的工作流程.使用终端,许多日常任务都被简化为了编写简单的命令并按下 Enter 按钮. 本文列举了一系列 Linux 命令,旨 ...
- python基于万象优图识别图片中的中文
最近一直在研究光学字符识别,即OCR.最开始在谷爹那里了解到了开源的Tesseract,可以拿来识别简单的英文和数字.但是识别中文的准确率并不高. 然后从Tesseract到Tesseract.js, ...
- IDEA搭建SpringMVC+Mybatis+Mysql+Maven框架
相关环境 Intellij IDEA Ultimate Tomcat JDK MySql 5.6(win32/win64) Maven (可使用Intellij IDEA自带的) 搭建步骤 创建项目工 ...