log4net学习笔记

很多技术在项目中用过,但是都是别人封装或搭建好的,自己没有从头到尾梳理过;直接调用或者直接复制到其它项目,也没有发现啥问题,没有踩坑的经历很多东西都会被忽略,log4net就是其中之一。由于好久没有配置过Log4net了,差不多都遗忘了,最近就写了一个基于MVC的小demo从零开始试试log4net,也记录一下学习过程和遇到的问题。

Log4net安装与配置

1、创建项目后用nuget直接安装log4net

 

2、log4net配置

log4net配置可以直接写在系统配置文件中比如app.configweb.config,我为了方便修改和展示,也为了以后方便复用,就抽出来自定义一个配置文件log4net.config

Log4net 有四种主要的组件,分别是Logger(记录器)、Repository(库)、Appender(附着器)以及Layout(布局)。

先放上log4net.config配置文件代码。

注:root节点的配置根据实际情况处理,否则可能会遇到无法写入日志或者重复写入日志问题

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!--<configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>-->
  <!-- Level的级别,由高到低 -->
  <!-- OFF > Fatal > ERROR > WARN > DEBUG > INFO > ALL-->
  <!-- 解释:如果level是ERROR,则在cs文件里面调用log4net的info()方法,则不会写入到日志文件中-->
  <log4net>
    <!--根记录器,所有Logger都默认继承它
    如果没有定义根记录器,调用GetLogger没有找到定义的Logger时不会在日志文件写入日志
    -->
    <root>
      <level value="ALL" />
      <!--错误日志附着器引用
      由于所有记录器都默认继承root,所以此附着器引用对所有的记录器都生效,因此如下配置的情况,调用错误日志记录器时会记录2次错误日志
      -->
      <appender-ref ref="ErrorAppender" />
      <!--<appender-ref ref="ADONetAppender" />-->
    </root>
    <!--错误日志记录器-->
    <logger name="logerror">
      <level value="ALL" />
      <!--定义记录的日志级别-->
      <appender-ref ref="ErrorAppender" />
      <!--记录到哪个介质中去-->
    </logger>
    <!--信息日志记录器-->
    <logger name="loginfo">
      <level value="ALL" />
      <appender-ref ref="InfoAppender" />
      <appender-ref ref="ADONetAppender" />
    </logger>
    <!--错误日志附着器-->
    <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
      <!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称,意思是,指定使用哪种介质-->
      <param name="File" value="Log\LogError\" />
      <!--日志输出到exe程序这个相对目录下-->
      <param name="AppendToFile" value="true" />
      <!--输出的日志不会覆盖以前的信息-->
      <param name="MaxSizeRollBackups" value="100" />
      <!--备份文件的个数-->
      <param name="MaxFileSize" value="10240" />
      <!--当个日志文件的最大大小-->
      <param name="StaticLogFileName" value="false" />
      <!--是否使用静态文件名-->
      <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
      <!--日志文件名-->
      <param name="RollingStyle" value="Date" />
      <!--文件创建的方式,这里是以Date方式创建-->
      <!--错误日志布局-->
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d [%t] %-5p %c %n%m%n" />
      </layout>
    </appender>
    <!--信息日志附着器-->
    <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
      <!--文件路径-->
      <param name="File" value="Log\LogInfo\" />
      <!--所有新的日志都进行追加-->
      <param name="AppendToFile" value="true" />
      <param name="MaxFileSize" value="10240" />
      <param name="MaxSizeRollBackups" value="100" />
      <!--文件名称不固定,可变-->
      <param name="StaticLogFileName" value="false" />
      <!--文件名称格式-->
      <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
      <!--文件名按日期滚动-->
      <param name="RollingStyle" value="Date" />
      <!--信息日志布局-->
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d [%t] %-5p %c %n%m%n" />
      </layout>
    </appender>
    <!--数据库日志附着器-->
    <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender,log4net">
      <!--BufferSize为缓冲区大小,只有日志记录超设定值才会一块写入到数据库-->
      <bufferSize value="1" />
      <!--或写为<param name="BufferSize" value="1" />-->
      <!--引用-->
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <!--连接数据库字符串-->
      <connectionString value="data source=.;database=Test2;user id=sa;password=123456;Enlist=true;Pooling=true;Max Pool Size = 512;" />
      <!--插入到表Log-->
      <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Location],[Exception]) VALUES (@log_date,@thread, @log_level, @logger,@message,@location,@exception)" />
      <!--日志记录时间,RawTimeStampLayout为默认的时间输出格式 -->
      <parameter>
        <parameterName value="@log_date" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.RawTimeStampLayout" />
      </parameter>
      <parameter>
        <parameterName value="@thread" />
        <dbType value="String" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%thread" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@Logger" />
        <dbType value="String" />
        <size value="100" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%logger" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@log_level" />
        <dbType value="String" />
        <size value="100" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%level" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@message" />
        <dbType value="String" />
        <size value="100" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%message" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@location" />
        <dbType value="String" />
        <size value="4000" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%location" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@exception" />
        <dbType value="String" />
        <size value="4000" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%exception" />
        </layout>
      </parameter>
    </appender>
  </log4net>
  
  <!--log4net调式相关配置 需要放到web.config中才会生效  start-->
  <appSettings>
    <!--开启log4net调式-->
    <add key="log4net.Internal.Debug" value="true"/>
  </appSettings>
  <!--log4net调式监听-->
  <system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add name="textWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="Log\log4net.txt" />
      </listeners>
    </trace>
  </system.diagnostics>
  <!--log4net调式相关配置 需要放到web.config中  end-->
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>

</configuration>

可以看到主要包括2个节点configSectionslog4net

1)configSections节点是对log4net配置节点的声明,如果没有这个节点会如下报错:

无法读取配置节“log4net”,因为它缺少节声明

注:如果log4net的配置放在自定义的配置文件里,这个声明是可以省略的

2)所有关于log4net的配置都包含在log4net节点中。(要重点注意root(根记录器)和logger(记录器)之间的关联关系)

3、关联log4net的配置文件

需要在2cs文件中指定log4net的配置文件,分别是AssemblyInfo.csGlobal.asax.cs

1) AssemblyInfo.cs

如果是系统配置web.config,加入以下代码,也可以按自定义配置文件的方式处理。

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

自定义配置文件需指定具体文件名,加入以下代码

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

2) Global.asax.cs

在全局文件中加入以下代码

注:如果在AssemblyInfo.cs中指定了配置文件且文件放在根目录下,以下代码是可以省略的

//配置log4
log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(Server.MapPath("~/log4net.config")));

4、测试写入日志

做好以上3个步骤后,就可以开始测试写入日志了,写入日志分为2个步骤

1、首先通过GetLogger方法获取Logger(记录器),方法参数为记录器的名称.

2、调用记录器各级别方法写入日志

获取记录器有如下2种情况:

1、传入配置文件中定义好的记录器名称获取记录器,代码如下:

private ILog logError = LogManager.GetLogger("logerror");

2、也可以传入相关调用处的类名,3中方式任选其一,代码如下:

注:如果是使用这种方式,就一定要配置root根记录器,否则你会发现只创建了空的日志文件,没有往日志文件中写入日志

private ILog log = LogManager.GetLogger("DefaultController");

private ILog log = LogManager.GetLogger(typeof(DefaultController));

private ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

 

 

 

从日志文件中可以看到,”测试错误记录器”这个日志写入了2次。这是因为我们定义了root根记录器和logerror记录器,而且所有记录器默认都继承root,所以当我们调用logerror记录器时相当于是logerror+root的效果,从下面的代码中可以看到,root和logerror都引用了ErrorAppender附着器,所以写入了2次日志。

如果不定义root根记录器,你用类名GetLogger获取记录器时会发现无法写入日志。

    <root>

      <level value="ALL" />

      <!--错误日志附着器引用

      由于所有记录器都默认继承root,所以此附着器引用对所有的记录器都生效,因此如下配置的情况,调用错误日志记录器时会记录2次错误日志

      -->

      <appender-ref ref="ErrorAppender" />

      <!--<appender-ref ref="ADONetAppender" />-->

    </root>

    <!--错误日志记录器-->

    <logger name="logerror">

      <level value="ALL" />

      <!--定义记录的日志级别-->

      <appender-ref ref="ErrorAppender" />

      <!--附着器引用-->

    </logger>

到此处就完成了log4net配置,并成功写入了日志,下面再简单说下配置文件里各节点的关系。

log4net节点介绍

从配置文件中可以看到,我们主要用了3种节点root(根记录器)、logger(记录器)、appender(附着器)。

从数量上看,我们只定义了1root节点、2logger节点(错误日志记录器、信息日志记录器),3appender节点(错误日志附着器、信息日志附着器、数据库日志附着器),这让我们知道我们可以定义多个logger记录器、多个appender附着器。

logger记录器

我们再看loginfo记录器,包含2种节点level(日志级别)appender-ref(附着器引用)

其中Level的级别,由高到低OFF> Fatal > ERROR > WARN > DEBUG > INFO > ALL,大于等于你配置级别的日志才能写入,比如你level节点value配置成DEBUG,则INFO级别日志不会写入。

appender-ref节点则表示附着器引用,一个记录器可以引用多个附着器,我们上面loginfo记录器就配置了写入日志文件,同时也写入数据库。

appender附着器

最后我们再看看数据库日志附着器ADONetAppender,里面有用到layout布局来获取插入数据库各字段的值,我们用的都是log4net自带的布局PatternLayout,能获取到一些常用信息,比如记录器名称%logger、信息%message,如果你要使用一些自定义字段,需要自己在代码中自定义布局,可参考Log4Net写入到数据库配置过程中的一些小问题备忘。常用信息如下所示:

%mmessage)输出日志消息

%nnewline)换行

%ddatetime)输出当前语句运行的时刻

%rruntime)输出当前语句的运行时刻

%tthread id)当前语句所在的线程ID

%ppriority)日志的当前优先级别,DEBUG INFO ……

%cclass)当前日志对象的名称

%L 输出语句所在的行号

%F 输出语句所在的文件名

%-数字 表示该项的最小长度,如果不够,用空格填充

ADONetAppender节点下commandText节点是配置插入语句,需要在数据库中建好对应的表,数据库字段可以多于插入语句中的字段,但是不能少。创建表的语句:

CREATE TABLE [dbo].[Log](

[ID] [int] IDENTITY(1,1) NOT NULL,

[Date] [datetime] NOT NULL,

[Thread] [varchar](100) NULL,

[Level] [varchar](100) NULL,

[Logger] [varchar](200) NULL,

[Message] [text] NULL,

[Location] [text] NULL,

[Exception] [text] NULL

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

对于插入数据库相关附着器的配置,也可以直接查看binlog4net.xml文件,这个文件是安装log4net包后在bin下生成的,提供了一个sql  server相关附着器的例子,可以直接复制这个附着器,也能节省一点找资料的时间

 

 

log4net调试

最后再提一下log4net调试,当log4net出问题时可以看看里面记录的信息,如配置文件读取不到、记录器无法创建等等一些简单问题还是可以从中获取到的,至少比出问题时一脸蒙,无从下手要强。

需要在系统配置文件web.config中加入如下代码:

   <appSettings>

    <!--开启log4net调式-->

    <add key="log4net.Internal.Debug" value="true"/>

  </appSettings>

  <!--log4net调式监听-->

  <system.diagnostics>

    <trace autoflush="true">

      <listeners>

        <add name="textWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="Log\log4net.txt" />

      </listeners>

    </trace>

  </system.diagnostics>

 根据配置的路径查看log4net.txt文件,如下:

 

 

 

参考:

Log4net的配置学习与总结 

非常完善的Log4net详细说明

Log4Net写入到数据库配置过程中的一些小问题备忘

 

原文地址:https://www.cnblogs.com/hsybs/p/15129091.html