Log4Net 自定义字段记录到数据库

时间:2022-08-30 07:59:26

      大家可能都用过Log4net插件来记录日志,该插件默认提供了这几个字段@log_date,@exception, @thread, @log_level, @logger, @message, 但是这并不能完全满足我们日常记录日志的需求,我们可能需要扩展自己所需的其他字段,来记录到数据库。例如,对于用户操作日志,我们可能需要记录操作人员ID或者姓名,或者操作类型或者操作信息等。

下面简单地介绍一下Log4Net 自定义字段记录到数据库:

第一步,当然是创建对应的数据库日志表,如下图所示:

Log4Net 自定义字段记录到数据库

第二步,配置Web.config,如下所示:

<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
  </configSections>
  <log4net>
    <!--Database Output-->
    <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
      <bufferSize value="1" />
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <connectionString value="server=10.10.120.98\SQLEXPRESS;database=manufacturingDev;User ID=sa;Password=nova123;" />
      <commandText value="INSERT INTO OperateLogs ([CreatedTime],[LastUpdatedTime],[Thread],[LogLevel],[Logger],[Message],[OperateType],[Detail],[UserId],[UserName]) VALUES (@log_date,@log_date1, @thread, @log_level, @logger, @message,@operatetype,@detail,@userid,@username)" />
      <parameter>
        <parameterName value="@log_date"/>
        <dbType value="DateTime"/>
        <layout type="log4net.Layout.RawTimeStampLayout"/>
      </parameter>
      <parameter>
        <parameterName value="@log_date1"/>
        <dbType value="DateTime"/>
        <layout type="log4net.Layout.RawTimeStampLayout"/>
      </parameter>
      <parameter>
        <parameterName value="@thread"/>
        <dbType value="String"/>
        <size value="255"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%thread"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@log_level"/>
        <dbType value="String"/>
        <size value="255"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%level"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@logger"/>
        <dbType value="String"/>
        <size value="255"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%logger"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@message"/>
        <dbType value="String"/>
        <size value="4000"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%message"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@operatetype"/>
        <dbType value="Int32"/>
        <layout type="CardsPocketsManufacturing.Infrastructure.Log4NET.ActionLayoutPattern">
          <conversionPattern value="%actionInfo{operatetype}"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@detail"/>
        <dbType value="String"/>
        <size value="4000"/>
        <layout type="CardsPocketsManufacturing.Infrastructure.Log4NET.ActionLayoutPattern">
          <conversionPattern value="%actionInfo{detail}"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@userid"/>
        <dbType value="Int32"/>
        <layout type="CardsPocketsManufacturing.Infrastructure.Log4NET.ActionLayoutPattern">
          <conversionPattern value="%actionInfo{userid}"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@username"/>
        <dbType value="String"/>
        <size value="4000"/>
        <layout type="CardsPocketsManufacturing.Infrastructure.Log4NET.ActionLayoutPattern">
          <conversionPattern value="%actionInfo{username}"/>
        </layout>
      </parameter>

    </appender>
    <!-- Specify the level for some specific categories -->
    <root>
      <level value="ALL" name="OperateLogger" />
      <appender-ref ref="AdoNetAppender" />
    </root>
  </log4net>

 第三步,创建Custom实体,ActionLoggerInfo,代码如下:

public class ActionLoggerInfo
    {
        public int UserId { get; set; }
        public string UserName { get; set; }
        public int OperateType { get; set; }
        public string Detail { get; set; }
        public ActionLoggerInfo(int operatetpye, int userId, string userName, string detail)
        {
            this.OperateType = operatetpye;
            this.UserId = userId;
            this.UserName = userName;
            this.Detail = detail;
        }
    }
 

 第四步,建立Custom转换器ActionConverter,代码如下:

 public class ActionConverter : PatternConverter
    {
        protected override void Convert(System.IO.TextWriter writer, object state)
        {
            if (state == null)
            {
                writer.Write(SystemInfo.NullText);
                return;
            }

            var loggingEvent = state as LoggingEvent;
            var actionInfo = loggingEvent.MessageObject as ActionLoggerInfo;

            if (actionInfo == null)
            {
                writer.Write(SystemInfo.NullText);
            }
            else
            {
                switch (this.Option.ToLower())
                {
                    case "userid":
                        writer.Write(actionInfo.UserId);
                        break;
                    case "username":
                        writer.Write(actionInfo.UserName);
                        break; 
                    case "operatetype":
                        writer.Write(actionInfo.OperateType);
                        break;
                    case "detail":
                        writer.Write(actionInfo.Detail);
                        break;
                    default:
                        writer.Write(SystemInfo.NullText);
                        break;
                }
            }
        }
    }

第五步,创建LayoutPatternActionLayoutPattern,代码如下:

public class ActionLayoutPattern : PatternLayout
    {
        public ActionLayoutPattern()
        {
            AddConverter(new ConverterInfo
            {
                Name = "actionInfo",
                Type = typeof(ActionConverter)
            });
        }
    }

第六步,创建Log日志帮助类,LogUtil,代码如下:

Log4Net 自定义字段记录到数据库Log4Net 自定义字段记录到数据库
public class LogUtil    {
        public LogUtil() { }

        private static ActionLoggerInfo _message = null;
        private static log4net.ILog _log;
        public static log4net.ILog Log
        {
            get
            {
                if (_log == null)
                { 
                    _log = LogManager.GetLogger("OperateLogger");                 
                }
                return _log;
            }
        }
        public static void Debug()
        {
            if (Log.IsDebugEnabled)
            {
                Log.Debug(_message);
            }
        }
        public static void Error()
        {
            if (Log.IsErrorEnabled)
            {
                Log.Error(_message);
            }
        }
        public static void Fatal()
        {
            if (Log.IsFatalEnabled)
            {
                Log.Fatal(_message);
            }
        }
        public static void Info()
        {
            if (Log.IsInfoEnabled)
            {
                Log.Info(_message);
            }
        }
        public static void Warn()
        {
            if (Log.IsWarnEnabled)
            {
                Log.Warn(_message);
            }
        }
        /// <summary>
        /// call Log method
        /// </summary>
        /// <param name="operateType"></param>
        /// <param name="userId"></param>
        /// <param name="userName"></param>
        /// <param name="detail"></param>
        /// <param name="level"></param>
        public static void SaveMessage(int operateType, int userId, string userName, string detail, int level)
        {
            _message = new ActionLoggerInfo(operateType, userId, userName, detail);
            switch (level)
            {
                case 1: Info(); break;
                case 2: Warn(); break;
                case 3: Error(); break;
                case 4: Fatal(); break;
                default: break;
            }
        }
    }
View Code

到此完毕!!!!