1. 程式人生 > >C# 利用log4net 把日誌寫入到資料庫

C# 利用log4net 把日誌寫入到資料庫

效果圖:


1:第一步建立SQL表結構
CREATE TABLE [dbo].[LogDetails] (
[LogID] int NOT NULL IDENTITY(1,1) ,
[LogDate] datetime NOT NULL ,
[LogThread] nvarchar(100) NOT NULL ,
[LogLevel] nvarchar(200) NOT NULL ,
[LogLogger] nvarchar(500) NOT NULL ,
[LogMessage] nvarchar(3000) NOT NULL ,
[LogActionClick] nvarchar(4000) NULL ,
[UserName] nvarchar(30) NULL ,
[UserIP] varchar(20) NULL 
)

3:建立 log4net.config

<?xml version="1.0" encoding="utf-8" ?>

<log4net debug="false">
  <!-- name屬性指定其名稱,type則是log4net.Appender名稱空間的一個類的名稱,意思是,指定使用哪種介質-->
  <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
    <!--日誌快取寫入條數 設定為0時只要有一條就立刻寫到資料庫-->
    <bufferSize value="0" />
    <!--日誌資料庫連線串-->
    <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <connectionString value="DATABASE=GoodLook;SERVER=xx.xx.140.170;UID=sa;PWD=123456a;Connect Timeout=30;" />
    <!--日誌資料庫指令碼-->
    <commandText value="INSERT INTO LogDetails ([LogDate],[LogThread],[LogLevel],[LogLogger],[LogActionClick],[LogMessage],[UserName],[UserIP]) VALUES (@log_date, @thread, @log_level, @logger, @ActionsClick, @message,@UserName,@UserIP)" />
    <!--日誌時間LogDate -->
     <parameter>
      <parameterName value="@log_date" />
      <dbType value="DateTime" />
      <layout type="log4net.Layout.RawTimeStampLayout" />
    </parameter>
    <!--執行緒號-->
    <parameter>
      <parameterName value="@thread" />
      <dbType value="String" />
      <size value="100" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%t" />
      </layout>
    </parameter>
    <!--日誌型別LogLevel -->
    <parameter>
      <parameterName value="@log_level" />
      <dbType value="String" />
      <size value="200" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%p" />
      </layout>
    </parameter>
    <!--日誌名稱-->
    <parameter>
      <parameterName value="@logger" />
      <dbType value="String" />
      <size value="500" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%logger" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@message" />
      <dbType value="String" />
      <size value="3000" />
      <layout type="Log4NetApply.MyLayout">
        <conversionPattern value="%property{Message}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@ActionsClick" />
      <dbType value="String" />
      <size value="4000" />
        <layout type="Log4NetApply.MyLayout" >
        <conversionPattern value = "%property{ActionsClick}"/>
      </layout>
    </parameter>
    <!--自定義UserName -->
    <parameter>  
        <parameterName value="@UserName" />  
        <dbType value="String" />  
        <size value="30" />
      <layout type="Log4NetApply.MyLayout" >
        <!--log4net.MDC.Set("UserName", "asdfasdf");
        <conversionPattern value = "%X{UserName}"/>-->
        <conversionPattern value = "%property{UserName}"/>
      </layout>
      </parameter>  
   <parameter>  
        <parameterName value="@UserIP" />  
        <dbType value="String" />  
        <size value="20" />
        <layout type="Log4NetApply.MyLayout" >
          <conversionPattern value = "%property{UserIP}"/>
        </layout>
      </parameter>  
  </appender>
  <!-- setup the root category, add the appenders and set the default level -->
  <root>
    <level value="Warn"/><!-- 定義記錄的日誌級別-->
    <level value="Info"/>
    <level value="Debug"/>
    <level value="Fine"/>
    <appender-ref ref="ADONetAppender" /><!-- 記錄到什麼介質中-->
  </root>
  <!-- specify the level for some specific categories -->
  <!--//關於上邊root到logger這塊,如果同時出現,有可能會出現重複插入記錄的情況:-->
  <!--<logger name="iNotes">
    <level value="WARN"/>
    <level value="INFO"/>
    <level value="DEBUG"/>
    <level value="FINE"/>
    <appender-ref ref="ADONetAppender"/>
  </logger>
  <logger name="StellaLogger">
    <level value="ALL"/>
    <appender-ref ref="AdoNetAppender" />
  </logger>-->
  <appender name="ReflectionLayout" type="log4net.Appender.RollingFileAppender,log4net">

    <!--日誌檔案路徑,按檔案大小方式輸出時在這裡指定檔名,並且前面的日誌按天在檔名後自動添加當天日期形成檔案-->
    <param name="File" value="D:/Log/" />

    <!--是否追加到檔案-->
    <param name="AppendToFile" value="true" />

    <!--記錄日誌寫入檔案時,不鎖定文字檔案-->
    <!--<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />-->

    <!--Unicode編碼-->
    <!--<Encoding value="UTF-8" />-->

    <!--最多產生的日誌檔案數,value="-1"為不限檔案數-->
    <!--<param name="MaxSizeRollBackups" value="10" />-->

    <!--是否只寫到一個檔案中-->
    <param name="StaticLogFileName" value="false" />

    <!--按照何種方式產生多個日誌檔案(日期[Date],檔案大小[Size],混合[Composite])-->
    <param name="RollingStyle" value="Composite" />

    <!--按日期產生資料夾,檔名[在日期方式與混合方式下使用]-->
    <param name="DatePattern" value="yyyy-MM-dd/"ReflectionLayout.log""  />
    <!--<param name="DatePattern" value="yyyyMMdd/yyyyMMdd"-TimerServer.log""  />-->
    <!--<param name="DatePattern" value="yyyyMMdd/"TimerServer/TimerServer.log""  />-->

    <!--每個檔案的大小。只在混合方式與檔案大小方式下使用,超出大小的在檔名後自動增加1重新命名-->
    <param name="maximumFileSize" value="500KB" />

    <!--記錄的格式。-->
    <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>

  
 
  
</log4net>

4:在Web.config 裡面加 configSections 節點 (CS可直接寫在app.config裡面,或者都寫在一個config裡面)

<configuration>
<strong> <span style="color:#FF0000;"> <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
  <log4net configSource="log4net.config"/></span></strong>
  
  <system.web>
      <compilation debug="true" targetFramework="4.5" />
      <httpRuntime targetFramework="4.5" />
    </system.web>

</configuration>

5:Properties 屬性下面的AssemblyInfo.cs 追加 必須有這個,否則寫入不到資料庫中
//[assembly: log4net.Config.XmlConfigurator(Watch = true)]
 //注意: ConfigFile 可以指定相對路徑 和 絕對路徑。 eg: /log/xxxx.log  或者 d://log//xxxx.log
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", ConfigFileExtension = "config", Watch = true)]

6:新增 Global.asax

然後在Application_Start 追加 讀取配置程式檔案

 protected void Application_Start(object sender, EventArgs e)
        {
            //應用程式啟動時,自動載入配置log4Net  
            XmlConfigurator.Configure();  
        }
7:建立自定義類 LogPublicClass.cs,為了方便寫入資料庫中 自定義的一些資訊
using log4net.Layout;
using log4net.Layout.Pattern;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;

namespace Log4NetApply
{
    /// <summary>
    /// 包含了所有的自定欄位屬性
    /// </summary>
    public class LogContent
    {
        public LogContent(string macAddress, string computerName, string actionsclick, string description)
        {
            UserIP = macAddress;
            UserName = computerName;
            ActionsClick = actionsclick;
            Message = description;
        }
   
        /// <summary>
        /// 訪問IP
        /// </summary>
        public string UserIP { get; set; }

        /// <summary>
        /// 系統登陸使用者
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 動作事件
        /// </summary>
        public string ActionsClick { get; set; }

        /// <summary>
        /// 日誌描述資訊
        /// </summary>
        public string Message { get; set; }


    }
	public class MyLayout : PatternLayout
    {
         public MyLayout()
        {
            this.AddConverter("property", typeof(LogInfoPatternConverter));
         }
     }

    public class LogInfoPatternConverter : PatternLayoutConverter
    {

        protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent)
        {
            if (Option != null)
            {
                // Write the value for the specified key
                WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent));
            }
            else
            {
                // Write all the key value pairs
                WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties());
            }
        }
        /// <summary>
        /// 通過反射獲取傳入的日誌物件的某個屬性的值
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>

        private object LookupProperty(string property, log4net.Core.LoggingEvent loggingEvent)
        {
            object propertyValue = string.Empty;
            PropertyInfo propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property);
            if (propertyInfo != null)
                propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null);
            return propertyValue;
        }
    }
}

8:示例使用
   try
                {
                    log.Info(new LogContent("127.0.0.1", "111111", "登陸系統", "登陸成功"));
                    var ss = 1 - int.Parse("sss");
                }
                catch(Exception ex)
                {
                    log.Error(new LogContent("127.0.0.1", "111111", "登陸系統", ex.Message+":"+ex.StackTrace));
                }

其他自行參考下列文章
http://www.cnblogs.com/kissazi2/p/3393151.html
http://blog.csdn.net/zdw_wym/article/details/48802821
http://blog.csdn.net/ydm19891101/article/details/50561638
http://www.w2bc.com/Article/70140
http://www.cnblogs.com/yuangang/archive/2016/05/16/5497140.html