log4net在Asp.net Mvc中的应用配置与介绍

log4net在.NET中的地位就不多言语了,此篇文章着重配置.较少介绍使用.因为在网上你可以在网上搜到几十万的文章告诉你怎么用.
安装的话也不废话了,很简单.Nuget里搜索一下"log4net"安装即可.

一.配置与配置详解

你可以选择在Web.Config里配置也可以在单独的xml文件里配置或是其他方式.我这里是使用单独的xml文件配置.

A.在Web.Config里配置

需要注意的是在configuration节点下添加configSections节点 节点内添加名为log4net的section

<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
<configuration>

如果选择存到xml文件里这一步也是需要的.如我在根目录下创建了一个log4net.xml的文件.这个文件的内容就是下一步B中的内容直接从<log4net>节点写起.

B.添加与configSections同级节点<log4net>

<log4net>
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <!--日志文件名开头  正斜杠/和反斜杠\都会创建文件夹-->
    <file value="D:/Logs/myexinfo.log" />
    <--<file value="D:/Logs/" />-->
    <staticLogFileName value="false" />
    <!—使用Unicode编码-->
    <encoding value="UTF-8" />
    <!--是否追加到文件-->
    <appendToFile value="true" />
    <!--混合使用日期和文件大小变换日志文件名 日期[Date],文件大小[Size],混合[Composite] -->
    <rollingStyle value="Composite" />
    <!--日期的格式-->
    <datePattern value="yyyyMMdd".log"" />
    <!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
    <maxSizeRollBackups value="30" />
    <!--不以独占方式记录日志,因为部署到服务器上遇到了文件名累加的情况....-->
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <!--最大文件大小-->
    <maximumFileSize value="5MB" />
    <!-- 过滤记录级别
        <filter type="log4net.Filter.LevelRangeFilter">
            <levelMin value="ERROR" />
            <levelMax value="FATAL" />
        </filter>
    -->
    <!--  这个是默认的日志内容格式
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%d [%t] %-5p %m - [%F:%L]%n" />
        </layout>
    -->
    <!—此处用继承了log4net.Layout.PatternLayout的自定义布局,TGLog.ExpandLayout2为命名空间。%property{Operator}、%property{Action}是自定义的输出-->
    <layout type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">
        <param name="ConversionPattern" value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 记录类:%logger     操作者ID:%property{Operator} 操作类型:%property{Action}%n             当前机器名:%property%n当前机器名及登录用户:%username %n               记录位置:%location%n 消息描述:%property{Message}%n 异常:%exception%n 消息:%message%newline%n%n" />
    </layout>
  </appender>
  <root>
    <level value="ALL"></level>
    <appender-ref ref="RollingLogFileAppender"></appender-ref>
  </root>
</log4net>

上边是一些基本的配置.可以看出主要节点配置<appender>节点和<root>节点.

<appender>节点可以有0个或多个 这个节点用来定义日志的输出方式,即日志要写到哪种介质上去.可以自定义此类,需要从log4net.Appender.AppenderSkeleton类继承.
   它的name属性要保证唯一.它的type类型比较多.想了解的可以展开看看.

AdoNetAppender 将日志记录到数据库中。可以采用SQL和存储过程两种方式。

AnsiColorTerminalAppender 将日志高亮输出到ANSI终端。

AspNetTraceAppender  能用asp.net中Trace的方式查看记录的日志。

BufferingForwardingAppender 在输出到子Appenders之前先缓存日志事件。

ConsoleAppender 将日志输出到应用程序控制台。

EventLogAppender 将日志写到Windows Event Log。

FileAppender 将日志输出到文件。

ForwardingAppender 发送日志事件到子Appenders。

LocalSyslogAppender 将日志写到local syslog service (仅用于UNIX环境下)。

MemoryAppender 将日志存到内存缓冲区。

NetSendAppender 将日志输出到Windows Messenger service.这些日志信息将在用户终端的对话框中显示。

OutputDebugStringAppender 将日志输出到Debuger,如果程序没有Debuger,就输出到系统Debuger。如果系统Debuger也不可用,将忽略消息。

RemoteSyslogAppender 通过UDP网络协议将日志写到Remote syslog service。

RemotingAppender 通过.NET Remoting将日志写到远程接收端。

RollingFileAppender 将日志以回滚文件的形式写到文件中。

SmtpAppender 将日志写到邮件中。

SmtpPickupDirAppender 将消息以文件的方式放入一个目录中,像IIS SMTP agent这样的SMTP代理就可以阅读或发送它们。

TelnetAppender 客户端通过Telnet来接受日志事件。

TraceAppender 将日志写到.NET trace 系统。

UdpAppender 将日志以无连接UDP数据报的形式送到远程宿主或用UdpClient的形式广播。

来源:http://www.cnblogs.com/lzrabbit/archive/2012/03/23/2413180.html

<root>节点最多1个 这点需要注意 level指明触发的级别(OFF > FATAL > ERROR > WARN > INFO > DEBUG  > ALL )  顾名思义Off是所有的写入方法都不写到日志里,ALL则相反
         注意这里的层级关系.定义的级别在此级别和此级别之上都会被记录. 假设定义了级别为info,那么debug级别的错误日志讲不会被写入日志,warn,error等却可以写入.
<appender-ref>指明引用那个appender.在root节点中可以有多个,在<appender>节点下也可以使用 但并不是所有类型都支持! 就我测试的而言 RollingFileAppender和FileAppender不支持 
其他节点都写了注释 很容易理解  注意 上边的配置我是所有都列出来了直接复制可能并不能正常写入!
比较特殊的节点有filter和layout
<filter>种类:     

使用过滤器可以过滤掉Appender输出的内容。过滤器通常有以下几种:

DenyAllFilter 阻止所有的日志事件被记录

LevelMatchFilter 只有指定等级的日志事件才被记录

LevelRangeFilter 日志等级在指定范围内的事件才被记录

LoggerMatchFilter 与Logger名称匹配,才记录

PropertyFilter 消息匹配指定的属性值时才被记录

StringMathFilter 消息匹配指定的字符串才被记录

<layout>用于控制Appender的输出格式,节点只能有一个.有多种类型 比较常用的类型就是PatternLayout,顾名思义可以使用某种模式定义显示内容.前边的配置中已经写的很详细了 .
    需要注意的是%property{Operator}这个东西是自定义的 稍后再提 不是必须的
还有一个<logger>节点没介绍,这个节点与<root>节点同级.继承于<root>节点.使用方式相同.需要注意的是由于级别问题可能会覆盖掉<root>的配置.
name属性要保证唯一.在代码里可以直接通过name访问它.

xml:
     <logger name="exceptionInfo">
      <level value="ERROR"/>
      <appender-ref ref="exceptionInfo"/>
    </logger>

C#:
log4net.LogManager.GetLogger("exceptioninfos").Error("这是一个异常");

LogManager类用于管理Log,这里获取指定的exceptioninfosLogger并记录一条错误日志.

配置讲到这里就差不多了.还剩下最后一步也是最重要的一步:启用配置.
在Global.asax文件的启动事件里加入代码.这一句一定要有 否则你会发现你的配置很正确 却不能记录日志:

XmlConfigurator.Configure();
或
XmlConfigurator.ConfigureAndWatch(); //参数为FileInfo类型的配置文件流

Configure有几个重载方法:

  
由参数即可看出可以远程加载配置文件 可以直接放入xml类文档 可以传递自定义的xml文件流;
在一开始的时候提到了自定义的log4net.xml文件.如果我们要加载的它的话可以这么加载:

XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(Server.MapPath("~/log4net.xml")));

带有Watch的方法表明监视这个文件,如果有改动就重新加载.
这时候可能会有人有疑问.不想写这么多代码,通过配置实现可以吗 答案是可以的.
代码里这么写:

XmlConfigurator.Configure();

在项目下边的AssemblyInfo.cs里加入代码(注意文件路径),个人比较喜欢使用这种方式:

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.xml", Watch = true)]

如果你不知道这个文件在哪请看图:
  

二.动态配置存储文件夹与格式化文件名

以日期形式动态显示文件名,几种类型各有区别

A.appender type为FileAppender

<appender name="warninfo" type="log4net.Appender.FileAppender">
     <file type="log4net.Util.PatternString" value="/Logs/%date{yyyy}/%date{yyyy MM dd HH_mm_ss}-warninfos.txt"  />
      <param name="lockingModel"  type="log4net.Appender.FileAppender+MinimalLock" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p %m - [%F:%L]%n" />
      </layout>
</appender>

这里的配置需要注意的地方就是file节点使用log4net.Util.PatternString类型 这样就可以在value中直接使用模式匹配.
前边已经提到了正斜杠和反斜杠都会被认为文件夹的分隔符,使用的时候请注意这点.
日期格式也要注意一下,在C#中写惯了yyyy-MM-dd HH:mm:ss的形式 这里却不能这样 因为windows系统里:作为盘符分隔符 不可以作为文件名!
如果你的文件夹创建了却没有日志文件生成你可能就要检查一下你写的是否含有不可作为文件名的字符了.
另外 HH代表24小时制(如:下午一点 会显示13:00点)   hh代表12小时制(如:下午一点 会显示1:00点)
好了 我们来运行一下 看看生成的结果:

xml:
  <logger name="warninfos">
    <level value="ALL"></level>
    <appender-ref ref="warninfo"></appender-ref>
  </logger>

C#:
LogManager.GetLogger("warninfos").Warn("这是一个警告");

得到的结果如下:

在我们指定的D盘下自动创建了Logs文件夹并且创建了以当前年份为名的文件夹.文件名也按照了我们想要的格式生成了.

B.类型为RollingFileAppender的appender

这种类型有两种方式修改一种是使用上边FileAppender的修改方法(RollingFileAppender继承于FileAppender)
另外一种就是配置datePattern节点,代码如下:

    <appender name="requestInfo" type="log4net.Appender.RollingFileAppender">
      <file value="D:/Logs"/>
      <encoding value="UTF-8" />
      <appendToFile value="true"/>
      <rollingStyle value="Date"/>
      <!--不使用静态文件名-->
      <staticLogFileName value="false"/>
      <maxSizeRollBackups value="-1" />
      <maximumFileSize value="5MB" />
      <param name="lockingModel"  type="log4net.Appender.FileAppender+MinimalLock" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别:  %-5level %n出错类:%logger property: [%property{NDC}] - %n错误描述:%message%newline %n"/>
      </layout>
      <datePattern value="/yyyy/yyyyMM/yyyyMMdd/'request.txt'"/>
    </appender>

这里其实主要配置datePattern,staticLogFileName,rollingStyle三个节点
datePattern  配置文件名的模式. 需要注意的是这里不用写%date这种占位符了 直接写入格式就行
                   后面的'-request.text'是指明这个地方不启用模式匹配 也可以用&quot;区分
staticLogFileName  是否启用静态文件名 true/false
rollingStyle  滚动记录类型 Date/Size/Composite
再次写入一条日志即可看到设成了我们所需要的格式 D:Logs\\2016\\201606\\20160625\\request.txt文件.
到这里动态配置文件名就差不多了.但如果有需求要把file的存储路径改成动态的怎么办?比如从其他配置文件里读取,从数据库里读取或是其他方式.不排除这种需求的存在.
解决方案如下:

C#:
//Global.asax文件
        protected void Application_Start()
        {
            //log4net
            log4net.GlobalContext.Properties["DynamicPath"] = @"D:\MyLogs\";
            XmlConfigurator.Configure();
        }

XML:
//appender  RollingFileAppender和FileAppender都可使用 注意file的type
<file type="log4net.Util.PatternString" value="%property{DynamicPath}" />

这段代码很简单.需要说明一下的就是%property{DynamicPath}  这个是用于显示我们自定义的属性的显示.上边配置文件里有介绍.
使用很简单大括号里加上我们预先定义好的变量名就行了.
在代码里设置的Properties属性.这个值在这里你就可以想怎么搞怎么搞了.从其他地方读取再放进来就行了.
还有种方式就是获取所有Appender节点通过代码修改其结果值的方式达到目的,代码如下:

        protected void Application_Start()
        {
            //log4net
            //log4net.GlobalContext.Properties["mypath"] = @"D:\MyLogs\";
            XmlConfigurator.Configure();

            var repository = log4net.LogManager.GetRepository();
            var appenders = repository.GetAppenders();
            var targetApp = appenders.First(x => x.Name == "exceptioninfo") as RollingFileAppender;
            //改变路径
            targetApp.File = @"D:\MyLogs\";
           //手动替换结果
           targetApp.DatePattern.Replace("'.txt'", "'-excinfo.txt'");
           //激活方才设置的属性
            targetApp.ActivateOptions();
        }

这种方式可以控制多个属性.只要支持了set方法的属性都可进行修改.
如果想更加精细的操作可以自定义Appender实现.  

  

参考文章:
1:Apache log4net manual
2:Log4Net根据不同的Logger名称,生成日志文件到不同的地方。
3:Log4Net配置详解
4:Log4Net 生成多个文件、文件名累加解决方法
5:(转)非常完善的Log4net详细说明 懒惰的肥兔

  

posted @ 2016-06-25 13:04  大杯美式不加糖不加奶  阅读(1310)  评论(0编辑  收藏  举报