<log4net> <root> <level value="WARN"/> <level value="INFO"/> <level value="DEBUG"/> <level value="FINE"/> <!--<appender-ref ref="LogFileAppender" />--> <appender-ref ref="ADONetAppender" /> </root> <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名称--> <file value="log.txt" /> <!--所有新的日志都进行追加--> <appendToFile value="true" /> <!--文件名称格式--> <datePattern value="-yyyy.MM.dd" /> <!--文件名按日期滚动--> <rollingStyle value="Date" /> <maxSizeRollBackups value="10" /> <!--文件名称不固定,可变--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n" /> </layout> </appender> <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender"> <!--BufferSize为缓冲区大小,只有日志记录超1条才会一块写入到数据库--> <bufferSize value="1"/> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> <connectionString value="Data Source=****;Initial Catalog=***;Persist Security Info=True;User ID=sa;Password=***;MultipleActiveResultSets=True"/> <commandText value="INSERT INTO edu_log (Date,Thread,Level,Logger,Message,SchoolID,SysTypeID) values(@log_date,@thread,@log_level,@logger,@content,@s_id,@t_id)"/> <parameter> <parameterName value="@log_date" /> <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="50" /> <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="@content" /> <dbType value="String" /> <size value="4000" /> <layout type="FuNong.Framework.Logger.CustomLayout"> <conversionPattern value="%property{content}" /> </layout> </parameter> <parameter> <parameterName value="@s_id" /> <dbType value="String" /> <size value="50" /> <layout type="FuNong.Framework.Logger.CustomLayout"> <conversionPattern value="%property{s_id}" /> </layout> </parameter> <parameter> <parameterName value="@t_id" /> <dbType value="String" /> <size value="50" /> <layout type="FuNong.Framework.Logger.CustomLayout"> <conversionPattern value="%property{t_id}" /> </layout> </parameter> </appender> </log4net>
注意上面配置代码中:log4net.Layout.PatternLayout 是log4net本身提供的配置模板,如果你有的字段需要用到其本身的模板字段的话,就可以使用。
还需要注意这段话: <conversionPattern value="%property{s_id}" />,它表明,我们将会利用log4net提供的已有的property转义模板来识别我们的字段。
但是如果你有自定义字段的话,你就需要自己写layout和converter了。在上面的配置文件中,content,s_id,t_id是我自定义的三个字段,如何让这三个字段也写入到数据库呢,我们一步一步来配置。
首先,需要将三个自定义字段放到一个entity类中:
namespace FuNong.Framework.Logger { public class LogContent { public LogContent(string content, string s_id, string t_id) { this.content = content; this.s_id = s_id; this.t_id = t_id; } public string content { get; set; } public string s_id { get; set; } public string t_id { get; set; } } }
然后,定义我们自己的layout,由于我们使用了property字段模板,所以我们这里需要按照如下方式添加:
namespace FuNong.Framework.Logger { public class CustomLayout:PatternLayout { public CustomLayout() { this.AddConverter("property", typeof(XPatternConverter)); } } }
最后,就是我们的Converter实现了:
namespace FuNong.Framework.Logger { public class XPatternConverter : PatternLayoutConverter { protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent) { if (this.Option != null) { // Write the value for the specified key WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent)); } else { // Write all the key value pairs WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties()); } } /// <summary> /// 通过反射获取传入的日志对象的某个属性的值 /// </summary> /// <param name="property"></param> /// <returns></returns> private Object LookupProperty(String property, log4net.Core.LoggingEvent loggingEvent) { Object propertyValue = String.Empty; PropertyInfo propertyInfo; propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null); } return propertyValue; } } }
从上面代码,我们可以看到,log4net会通过反射来识别我们logContent这个entity中的字段,然后逐个赋值,再写到数据库的。
下面我们稍微包装一下:
namespace FuNong.Framework.Logger { public interface ILoggerService { void Debug(object message); void Error(object message); void Fatal(object message); void Info(object message); void Warn(object message); } }
namespace FuNong.Framework.Logger { public class LoggerService:ILoggerService { public LoggerService() { log4net.Config.XmlConfigurator.Configure(); logger = LogManager.GetLogger(typeof(LoggerService)); } private readonly ILog logger; public void Info(object message) { logger.Info(message); } public void Warn(object message) { logger.Warn(message); } public void Debug(object message) { logger.Debug(message); } public void Error(object message) { logger.Error(message); } public void Fatal(object message) { logger.Fatal(message); } } }
由于我用了autofac做ioc,所以我们就直接看使用方法吧:
protected override void OnAuthorization(AuthorizationContext filterContext) { if (auth) { var collection = cookie.GetCookieCollection("FuNong.UserInfo.Login"); if (collection == null) { logger.Warn(new LogContent("用户登陆信息提取失败,将会跳转到登陆界面...", "1", "2")); filterContext.Result = new RedirectResult("Home/Login"); } else { logger.Info(new LogContent("用户验证成功,请继续之前操作...","1","2")); } } }
这样,当我们运行起来后,我们就发现,程序已经将数据写入数据库了。
整个配置不难,但是细节挺多,稍微不小心,就可能导致写入不到数据库。
原文:http://www.cnblogs.com/scy251147/p/4456327.html