前言

本文欢迎转载,作者原创地址: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. 非常有用的css使用总结

    积小流以成江海,很多东西你不总结就不是你的东西 常用css总结: /*设置字体*/ @font-face { font-family: 'myFont'; src: url('../font/myFo ...

  2. es6函数的rest参数和拓展运算符(...)的解析

    es6的新特性对函数的功能新增加了rest参数和...的拓展运算符.这是两个什么东西呢? 先来看一个问题:如何获取一个函数除了定义的参数之外的其他参数?传统的做法是借助函数的arguments关键字来 ...

  3. LeetCode 650 - 2 Keys Keyboard

    LeetCode 第650题 Initially on a notepad only one character 'A' is present. You can perform two operati ...

  4. 即时通信系统Openfire分析之五:会话管理

    什么是会话? A拨了B的电话 电话接通 A问道:Are you OK? B回复:I have a bug! A挂了电话 这整个过程就是会话. 会话(Session)是一个客户与服务器之间的不中断的请求 ...

  5. 一步使你的asp.net网站在手机浏览器上全屏显示

    首先要加入下面的代码: <meta name="viewport" content="width=device-width, initial-scale=1.0, ...

  6. asp.net mvc CodeFirst模式数据库迁移步骤

    利用Code First模式构建好基本的类后,项目也开始搭建完毕并成功运行,而且已经将数据库表结构自动生成了. 但是,我有新的类要加入,有字段需要修改,那怎么办呢,删库,跑路 ?  哈哈 利用数据库迁 ...

  7. 超全面!这可能是最全面的 jQuery 知识总结

    个人建议:学习 jQuery 前先掌握基本的 JavaScrpit 语法,特别是对函数要掌握,jQuery 基本上是使用函数. jQuery 简介 jQuery 是一个轻量级 JavaScript 库 ...

  8. DevOps之内容分发网络CDN

    唠叨话 关于德语噢屁事的知识点,仅提供专业性的精华汇总,具体知识点细节,参考教程网址,如需帮助,请留言. <内容分发网络CDN(Content Delivery Network)> 关于虚 ...

  9. PHP 单例模式解析和实战

    一.什么是单例模式? 1.含义 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例.它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用. 2. ...

  10. 备忘:有MTU值设置不当导致的部分网站无法访问问题

    如题,有时候突然weibo.com,webQQ等网站网络连接超时,怎么找也没得原因,今天管理电信的光猫,发现设置的MTU的1400,突然想起之前电脑和路由器上设置的MTU是1500,感觉可能是这个问题 ...