大家可能都用过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; } } }
到此完毕!!!!