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>
        /// Á¬½Ó×Ö·û´®Ãû³Æ
        /// </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(后续上传)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章