大家可能都用过Log4net插件来记录日志,该插件默认提供了这几个字段@log_date,@exception, @thread, @log_level, @logger, @message, 但是这并不能完全满足我们日常记录日志的需求,我们可能需要扩展自己所需的其他字段,来记录到数据库。例如,对于用户操作日志,我们可能需要记录操作人员ID或者姓名,或者操作类型或者操作信息等。
下面简单地介绍一下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; } } } }
第五步,创建LayoutPattern,ActionLayoutPattern,代码如下:
public class ActionLayoutPattern : PatternLayout { public ActionLayoutPattern() { AddConverter(new ConverterInfo { Name = "actionInfo", Type = typeof(ActionConverter) }); } }
第六步,创建Log日志帮助类,LogUtil,代码如下:
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; } } }
到此完毕!!!!