前言

本文欢迎转载,作者原创地址: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】的更多相关文章

  1. .Netcore之日志组件Log4net、Nlog性能比较

    转载请注明出处http://www.cnblogs.com/supernebula/p/7506993.html .Netcore之Log4net.Nlog性能比较 最近在写一个开源.netcore ...

  2. .Net core2.0日志组件Log4net、Nlog简单性能测试

    .Net core之Log4net.Nlog简单性能测试 比较log4net.nlog的文件写入性能(.netcore环境),涉及代码和配置如有不正确的地方,还请批评指正. 原创,转载请著名出处:ht ...

  3. 【框架学习与探究之消息队列--EasyNetQ(2)】

    声明 本文欢迎转载,系博主原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7654902.html 前言 此文章,是承接上篇:[框架学习与探究之消息队列--Ea ...

  4. 4.VUE前端框架学习记录四:Vue组件化编码2

    VUE前端框架学习记录四:Vue组件化编码2文字信息没办法描述清楚,主要看编码Demo里面,有附带完整的代码下载地址,有需要的同学到脑图里面自取.脑图地址http://naotu.baidu.com/ ...

  5. 3.VUE前端框架学习记录三:Vue组件化编码1

    VUE前端框架学习记录三:Vue组件化编码1文字信息没办法描述清楚,主要看编码Demo里面,有附带完整的代码下载地址,有需要的同学到脑图里面自取.脑图地址http://naotu.baidu.com/ ...

  6. ABP .Net Core 日志组件集成使用NLog

    一.说明 NLog介绍和使用说明官网:http://nlog-project.org/ NLog和Log4net对比:https://www.cnblogs.com/qinjin/p/5134982. ...

  7. 【框架学习与探究之宿主服务--Topshelf】

    前言 此文欢迎转载,原始链接地址:http://www.cnblogs.com/DjlNet/p/7603819.html 正文 原先也偶然见过这个关键词,当时只是有个大致了解貌似和WinServic ...

  8. 【框架学习与探究之定时器--Quartz.Net 】

    声明 本文欢迎转载,原文地址:http://www.cnblogs.com/DjlNet/p/7572174.html 前言 这里相信大部分玩家之前现在都应该有过使用定时器的时候或者需求,例如什么定时 ...

  9. 【框架学习与探究之定时器--Hangfire】

    声明 本文欢迎转载,请注明文章原始出处:http://www.cnblogs.com/DjlNet/p/7603632.html 前言 在上篇文章当中我们知道关于Quartz.NET的一些情况,其实博 ...

随机推荐

  1. LDA工程实践之算法篇之(一)算法实现正确性验证(转)

    研究生二年级实习(2010年5月)开始,一直跟着王益(yiwang)和靳志辉(rickjin)学习LDA,包括对算法的理解.并行化和应用等等.毕业后进入了腾讯公司,也一直在从事相关工作,后边还在yiw ...

  2. Ubuntu16笔记本双显卡安装NVIDIA驱动

    blockquote { direction: ltr; color: rgb(0, 0, 0) } blockquote.western { font-family: "Liberatio ...

  3. php获取音悦台视频

    <?php $url=isset($_GET['url'])?trim($_GET['url']):''; $url = "http://v.yinyuetai.com/video/6 ...

  4. 给tableView设置headerView时遇到的问题

    在ViewDidLoad里面设置了 self.tableView.tableHeaderView = 自定义的View 然后在模拟器上运行后,发现这个HeaderView挡住了后面的Cell,也就是c ...

  5. php使用curl下载指定大小的文件

    php中使用基于libcurl的curl函数,可以对目标url发起http请求并获取返回的响应内容.通常的请求方式类似如下的代码: public function callFunction($url, ...

  6. C#线程池多线程Socket通讯 服务器端和客户端示例

    using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; ...

  7. pb9常见错误及含义

    1. by zero  发生被0除错误 2. Null object reference  空对象引用 3. Array boundary exceeded  数组越界 4. Enumerated v ...

  8. 详解面向对象编程——JavaScriptOOP

        前  言 絮叨絮叨 学习了JS之后,不知道大家觉得怎们样呢? 今天我们就来讲一下JS中最重要的一个环节,JavaScript中的面向对象编程OOP,这里的东西有点难,也有点绕. 可是! 不要灰 ...

  9. 【Vue】浅谈Vue(一):从模板语法数据绑定、指令到计算属性

    写在前面 今年前端届比较有意思,从大漠穷秋发表文章比较angular和vue,继而致歉vue作者.社区,从谷歌辞去Angular Developer PM in China一职并且呼吁大家停止各种无谓 ...

  10. 51nod 1522 上下序列

    题目描述 现在有1到n的整数,每一种有两个.要求把他们排在一排,排成一个2*n长度的序列,排列的要求是从左到右看,先是不降,然后是不升. 特别的,也可以只由不降序列,或者不升序列构成. 例如,下面这些 ...