1. 程式人生 > >log4net配置自定義欄位存入資料庫

log4net配置自定義欄位存入資料庫

 

前言

以bs專案中引入log4net為例。log4net存入資料庫提供了基本的(時間、執行緒、等級、message)欄位。 但是實際日誌場景中可能需要統計IP、使用者ID或者其他業務相關的資訊記入日誌。 需要重寫log4net的部分方法來實現。本文展示使用log4net從0開始到記錄自定義欄位入庫的過程。

關鍵程式碼在第三步

一. 資料庫表

隨便建立一個測試的表,有test1和test2兩個欄位,後續用log4net存入資料。

二. log4net基礎配置

1.nuget搜尋log4net並安裝。

2.Global.asax全域性配置

   在Global.asax中新增  log4net.Config.XmlConfigurator.Configure();這句。如圖。

三.建立自定義類

1.建立一個自己資料庫裡日誌表的實體,方便傳值、新增資料等。

我這裡命名為BaseLog.cs, 欄位為test1和test2 ,和資料庫表對應

using System;
using System.ComponentModel;

namespace DataStatisticsApi.Log
{
    /// <summary>
    /// 日誌基礎類
    /// </summary>
    [Serializable]
    public class BaseLog
    {
        public BaseLog()
        {
        }

        ///<summary>
        ///唯一識別符號
        ///</summary>
        [Description("測試1")]
        public string test1
        {
            get; set;
        }
        ///<summary>
        ///請求時間
        ///</summary>
        [Description("測試2")]
        public string test2
        {
            get; set;
        }
    }
}

2.增加資料庫連線字串屬性

建立一個類,繼承log4net的AdoNetAppender類。


using log4net.Appender;
using System.Configuration;
namespace DataStatisticsApi.Log
{

    public class CustomAdoNetAppender : AdoNetAppender
    {
        /// <summary>
        /// Á¬½Ó×Ö·û´:registered:Ãû³Æ
        /// </summary>
        public new string ConnectionStringName
        {
            set
            {
                this.ConnectionString = ConfigurationManager.ConnectionStrings[value].ConnectionString;
            }
        }

    }
}

3.增加一個自定義的日誌類

建立一個類,作為一個自定義的日誌。我這裡叫DataLogAdoAppender, 同樣繼承自log4net的AdoNetAppender類。

在該類中寫自己插入表的語句和引數,並在最後呼叫log4net的ActivateOptions方法初始化載入log4net配置。


using System;

using log4net.Appender;
using System.Data;
using log4net.Layout;
namespace DataStatisticsApi.Log
{
    public class DataLogAdoAppender : CustomAdoNetAppender
    {
        public DataLogAdoAppender()
        {
            //System.Data.SqlClient
            Type t = typeof(System.Data.SqlClient.SqlConnection);
            string s = t.Assembly.FullName.ToString();
            //資料連線型別
            this.ConnectionType = $"System.Data.SqlClient.SqlConnection, {s}";

            base.UseTransactions = false;
            this.CommandType = CommandType.Text;
            //sql語句
            this.CommandText = @"INSERT INTO [dbo].[testLog]
                                       ([test1]
                                       ,[test2])
                                      
                                 VALUES
                                       (@test1
                                       ,@test2
                                       )";
            //填充引數
            string parameterName = "test1";
            this.AddParameter(new AdoNetAppenderParameter() { ParameterName = "@" + parameterName, DbType = DbType.String, Size = 50, Layout = new Layout2RawLayoutAdapter(new LogLayout("%" + parameterName)) });
            parameterName = "test2";
            this.AddParameter(new AdoNetAppenderParameter() { ParameterName = "@" + parameterName, DbType = DbType.String, Size = 200, Layout = new Layout2RawLayoutAdapter(new LogLayout("%" + parameterName)) });

            base.ActivateOptions();
        }
    }
}

4.增加一個自定義的轉換類

 建立一個自定義轉換類,把log4net物件轉換成自定義日誌類的欄位屬性。繼承log4net的PatternLayout類,並重寫ActivateOptions方法。

using System.IO;

using log4net.Core;
using log4net.Layout;
using log4net.Layout.Pattern;

namespace DataStatisticsApi.Log
{
    public class LogLayout : PatternLayout
    {
        public LogLayout(string pattern)
            : base(pattern)
        {

        }
        public override void ActivateOptions()
        {
            this.AddConverter("test1", typeof(test1Converter));

            this.AddConverter("test2", typeof(test2Converter));

            base.ActivateOptions();
        }
    }

    #region 轉換
    internal sealed class test1Converter : PatternLayoutConverter
    {
        override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
        {
            BaseLog log = (BaseLog)loggingEvent.MessageObject;
            if (log != null)
                writer.Write(log.test1);
        }
    }

    internal sealed class test2Converter : PatternLayoutConverter
    {
        override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
        {
            BaseLog log = (BaseLog)loggingEvent.MessageObject;
            if (log != null)
                writer.Write(log.test2);
        }
    }

    #endregion


}

 

 

四.log4net存庫配置

在web.config中新增<log4net>節點

<log4net>
  <!-- 業務日誌-“資料庫”記錄器 -->
  <appender name="DataLogAdoAppender" type="DataStatisticsApi.Log.DataLogAdoAppender">
    <!-- 依賴的資料庫連結名稱 -->
    <connectionStringName value="ConnectionString"/>
    <!-- 快取條數,到達value值時批量插入,1為每次都插入。實際環境根據日誌量設定500或者更多-->
    <bufferSize value="1"/>
  </appender>
  <root>
    <level value="DEBUG" />
  </root>
  <!-- 自定義記錄日誌-->
  <logger name="DataLogAdoAppenderLogger">
    <!--資訊級別僅限(FATAL)-->
    <level value="INFO" />
    <!--日誌配置,ref對應appender配置-->
    <appender-ref ref="DataLogAdoAppender" />
  </logger>
</log4net>

在web.config中新增<connectionStrings>節點(資料庫連線字串)

<connectionStrings>
 <add name="ConnectionString" connectionString="Data Source=1.1.1.3,1355; User ID=xxx; Password=xxx; Initial Catalog=dbName" providerName="System.Data.SqlClient" />
 </connectionStrings>

五.Api測試

測試訪問,日誌資料成功入庫

 

詳細程式碼見github(後續上傳)