背景

  在程序中,我们调试运行时信息,Log4Net是一个不错的解决方案。不知道是我用的不好,用到最后反而都不想看日志了。原因是因为我n个功能使用的默认的Logger来记录日志,这样以来,所有功能记录的信息都依赖同一个配置,于是所有的信息都在一个文件中,有时候查找起来,极其不方便。

  我想,能不能按照功能分类呢?如果通过配置不同的logger,然后功能根据不同的LoggerName加载Ilog实例,是可以做到。但由于这些功能的log配置差异性极小,也许仅仅就是文件名不同。于是想通过代码进行配置。

解决方案

  想来这样的需求应该也算正常,但经过查找,发现在log4j中有相关的咨询,但看不懂,只能自己下载log4net的源码,看看它的运行原理。

  如果我们需要通过配置不同的ILog,流程是这样的,首先要创建一个ILoggerRepository,通过它来进行日志等级的配置,和各种Appender,接着通过LogManager在ILoggerRepository获取一个Ilog对象,就可以写日志了。代码如下:

        public static ILog GetLogger(string repositoryName = "")
{
if (string.IsNullOrEmpty(repositoryName)) return LogManager.GetLogger("Defalut"); ILoggerRepository repository = null;
try
{
repository = LogManager.GetRepository(repositoryName);
}
catch (Exception) { } //找到直接返回ilog
if (repository != null)
return LogManager.GetLogger(repositoryName, "Defalut"); //未找到则创建,多线程下很有可能创建时,就存在了
try
{
repository = LogManager.CreateRepository(repositoryName);
}
catch (Exception)
{
repository = LogManager.GetRepository(repositoryName);
} //配置日志等级 读取Appsettings默认配置
var appSet = ConfigurationManager.AppSettings.AllKeys; //查找日志等级
const string logLevel = "LogLevel";
var hasSettings = Array.IndexOf(appSet, logLevel);
if (hasSettings > -)
{
var level = ConfigurationManager.AppSettings[logLevel].ToLower();
if (level == "all") repository.Threshold = Level.All;
else if (level == "debug") repository.Threshold = Level.Debug;
else if (level == "info") repository.Threshold = Level.Info;
else if (level == "warn") repository.Threshold = Level.Warn;
else if (level == "error") repository.Threshold = Level.Error;
else if (level == "fatal") repository.Threshold = Level.Fatal;
else if (level == "off") repository.Threshold = Level.Off;
}
else repository.Threshold = Level.All; //查找输出Appender
const string logAppender = "LogAppender";
hasSettings = Array.IndexOf(appSet, logAppender);
if (hasSettings > -)
{
var appenders = ConfigurationManager.AppSettings[logAppender].ToLower().Split(',');
foreach (var appender in appenders)
{
if (appender == "rollingfile") LoadRollingFileAppender(repository);
else if (appender == "console") LoadConsoleAppender(repository);
else if(appender == "trace") LoadTraceAppender(repository);
}
}
else LoadRollingFileAppender(repository); return LogManager.GetLogger(repositoryName, "Default");
}

  Log4net 会自动维护ILog和ILoggerRepository,所以不用保存,通过LogManger获取即可。但是我没有找到方法来查找指定的ILoggerRepository是否存在,所以在上述代码中通过try catch进行判断。由于我们是通过代码方式配置log4net,但仍旧希望通过配置来设置日志等级和输出类型,所以我选择在Appsettings文件中进行配置,一次配置,针对所有的ILoggerRepository都生效。之所以不是针对每一个功能进行配置,主要是由于配置麻烦,而且如果真要这么做,直接在log4net中配置不同的logger,通过loggername引用,可能会更好些。

日志维护

  于是接下来的问题是,如何删除日志?

  log4net可以配置RollingFileAppender,翻译过来是滚动文件。通过设置MaximumFileSize和MaxSizeRollBackups 2个参数可以完成这样的目的,该日志文件每达到一定大小就会产生一个新文件,文件最大总数则为MaxSizeRollBackups,但前提的是文件名一致。

  比如我们采用如下配置:

    <!--RollingFileAppender:输出到文件中-->
<appender name="SysAppender" type="log4net.Appender.RollingFileAppender">
<!--日志的路径-->
<file value="Logs/" />
<!--是否覆盖,默认是追加true-->
<appendToFile value="true"/>
<!--不占用日志文件进程-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<rollingStyle value="Composite"/>
<!--文件名称-->
<DatePattern value="yyyy-MM-dd HH'时.log'"></DatePattern>
<!--设置无限备份=-1 ,最大备份数为1000-->
<param name="MaxSizeRollBackups" value="1000"/>
<!--每个文件的大小-->
<param name="MaximumFileSize" value="500KB"/>
<!--名称是否可以更改 为false为可以更改-->
<param name="StaticLogFileName" value="false"/>
<layout type="log4net.Layout.PatternLayout">
<!--输出格式-->
<conversionPattern value="%n【记录时间】%date%n【描述】%message%n"/>
</layout>
</appender>

  效果则是 日志以小时为单位,每小时最大备份总数为1000,每到500kb后形成日志文件。当随着天数的增加,文件也开始变多,需要我们自己去清理。所以上述配置可以稍微改下:

    <!--RollingFileAppender:输出到文件中-->
<appender name="SysAppender" type="log4net.Appender.RollingFileAppender">
<!--日志的路径-->
<file value="Logs/日志.log" />
<!--是否覆盖,默认是追加true-->
<appendToFile value="true"/>
<!--不占用日志文件进程-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<rollingStyle value="Composite"/>
<!--文件名称-->
<DatePattern value="yyyy-MM-dd HH'时.log'"></DatePattern>
<!--设置无限备份=-1 ,最大备份数为1000-->
<param name="MaxSizeRollBackups" value="1000"/>
<!--每个文件的大小-->
<param name="MaximumFileSize" value="500KB"/>
<!--名称是否可以更改 为false为可以更改-->
<param name="StaticLogFileName" value="true"/>
<layout type="log4net.Layout.PatternLayout">
<!--输出格式-->
<conversionPattern value="%n【记录时间】%date%n【描述】%message%n"/>
</layout>
</appender>

  主要是设置了日志文件名,而且是静态名称,不允许更改。这样以来,日志文件最多只有1000个了,就不用手工维护了,你会看到这样的日志文件名:

  日志.log   日志.log.1  日志.log.2   ... 默认是文件名最后的数字越大,时间最老,所以查看新日志,主要是在 第一个文件名 中。

  另外提醒下:如果设置Appender使用了静态文件名,那么历史日志会被覆盖,而极其在意历史日志的应用,建议不要使用此方案,清理日志的话,还是老老实实写代码吧。

测试代码下载

Log4Net日志分类和自动维护的更多相关文章

  1. Log4net日志文件自动按月份存放和日志独占问题的解决

    让log4net日志文件自动按月份存放 log4net日志文件的作用还真不小,可以保存管理员.用户对数据库的任何操作,保存管理员和用户的登录记录,分析系统运行错误,所以不舍得随便将日志文件Delete ...

  2. 如何让Log4net日志文件按每月归成一个文件夹,StaticLogFileName参数的用法

    想要让Log4net日志(以下称日志)按每月自动归类为一个文件夹,为此,学习和修改了log4net.config文件.查了资料,重点是以下这些参数:      <param name=" ...

  3. LOG4NET日志配置及使用

    Log4net的安装 Install-Package log4net 1.先弄个日志记录的类 /// <summary> /// 使用LOG4NET记录日志的功能,在WEB.CONFIG里 ...

  4. log4net日志的配置及简单应用

    在程序运行中,往往会出现各种出乎开发人员意料的异常或者错误,所以,记录详细的程序运行日志信息,有利于开发人员和运维人员排查异常信息,提高工作效率.而本菜鸟在大神推荐和指导下使用log4net这一插件工 ...

  5. Log4net日志使用教程-控制台、文本、数据库三种记录方式

    一.log4net简介: 1. Log4net的优点: 几乎所有的大型应用都会有自己的用于跟踪调试的API.因为一旦程序被部署以后,就不太可能再利用专门的调试工具了.然而一个管理员可能需要有一套强大的 ...

  6. mysql日志分类

    mysql的日志分类: (1)错误日志:记录mysql服务的启动,运行,停止mysql服务时出现的问题 [mysqld] log_error=[/path/filename] (2)通用查询日志:记录 ...

  7. C# Log4Net 日志

    C#使用Log4Net记录日志 第一步:下载Log4Net            下载地址:http://logging.apache.org/log4net/download_log4net.cgi ...

  8. 如何在通用权限管理系统中集成log4net日志功能

    开发人员都知道,在系统运行中要记录各种日志,自己写一个日志功能,无论是在效率还是功能扩展上来说都不是很好,目前大多用的是第三方的日志系统,其中一个非常有名,用的最多的就是log4net.下面是关于这个 ...

  9. ASP.NET MVC4中加入Log4Net日志记录功能

    前言 在之前的.NET中,微软还没有提供过像样的日志框架,目前能用的一些框架比如Log4Net.NLog.CommonLogging等,虽然多多少少使用起来有点费劲,但这里还是简单分享一下Log4Ne ...

随机推荐

  1. ZOJ3329 概率DP

    One Person Game Time Limit: 1 Second      Memory Limit: 32768 KB      Special Judge There is a very ...

  2. BZOJ 1441: Min(裴蜀定理)

    BZOJ 1441:Min Description 给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1*X1+...An*Xn>0,且S的值最小 Input 第一行给出数 ...

  3. ELK之Elasticsearch

    安装并运行Elasetisearch cd elasticsearch-<version> ./bin/elasticsearch 如果你想把 Elasticsearch 作为一个守护进程 ...

  4. [原]sencha touch之表单二(注册页面)

    接着上一篇的登陆页面,来一个最简单的注册页面,几乎包含了常用的field Ext.application({ id:'itKingApp', launch:function(){ var formPa ...

  5. 《Cracking the Coding Interview》——第16章:线程与锁——题目6

    2014-04-27 20:25 题目:关于java中标有synchronized的成员方法? 解法:这代表同一个对象实例的synchronized方法不能被多个线程同时调用.注意有这么多个地方都加粗 ...

  6. Python 3基础教程8--if else、if elif else

    本文介绍if else语句,不多说,直接看例子. if elif else语句

  7. Kotlin中的“忍者”函数 —— 理解泛型的能力(KAD 12)

    作者:Antonio Leiva 时间:Feb 8, 2017 原文链接:https://antonioleiva.com/generic-functions-kotlin/ Kotlin的一些特性组 ...

  8. [转]unity之LOD

    LOD技术有点类似于Mipmap技术,不同的是,LOD是对模型建立了一个模型金字塔,根据摄像机距离对象的远近,选择使用不同精度的模型. 它的好处是可以在适当的时候大量减少需要绘制的顶点数目. 它的缺点 ...

  9. Mecanim动画

    1.基础 现在Animation编辑器给个模型设计一个动画,都会自动为此模型加上Animator组件,并产生一个controller后缀的控制器和一个相关的anim后缀的动画剪辑, unity根据An ...

  10. 孤荷凌寒自学python第三十五天python的文件操作之针对文件操作的os模块的相关内容

     孤荷凌寒自学python第三十五天python的文件操作之针对文件操作的os模块的相关内容 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.打开文件后,要务必记得关闭,所以一般的写法应当 ...