ExtAspNet应用技巧(八) - log4net配置与使用
前言
为了实践项目驱动的ExtAspNet开发过程,最近我启动了另外一个开源项目 - AppBox。
AppBox项目使用ExtAspNet作为前台展现层,SubSonic作为ORM层,SqlServer2005作为数据库,在Asp.Net2.0基础之上实现一个企业综合管理系统所必须的基础组件。
包括用户管理,菜单管理,权限管理,组织结构管理等各个部分,虽然AppBox不是给最终用户使用的,但是可以作为开发人员搭建网站的一个框架,同时在项目中遇到的控件会优先在ExtAspNet中实现。
由于在AppBox中使用了log4net作为日志记录组件,所以这篇文章就来分享一下log4net的配置和使用。
log4net配置
1. 首先到 http://logging.apache.org/ 下载最新的log4net v1.2.10。
2. 建立数据库表
3. 在网站根目录添加log4net.config文件
注:这里我们使用了两种类型的日志记录方式,文件和数据库。
文件保存在网站根目录下的 log\log.config ,必须保证Asp.Net服务进程对此文件夹有写权限,否则不能写入文件并且没有任何提示。
比如在WindowXP下需要设置 ASPNET (Windows2003不是这个名称,可以Google一下) 对此文件夹的写权限。
同时注意我们使用log.config而不是log.txt,是为了防止匿名用户非法下载系统日志。
在数据库配置上也有个小技巧,我们设置了 bufferSize value="0",也就是说产生一条日志就写到数据库。
我刚开始也是在这个地方遇到麻烦,设置bufferSize为10,刚开始怎么也观察不到日志插入数据库,后来才知道被缓存了。
不要在多处定义数据库连接字符串
因为我们已经在Web.config中定义了数据库连接字符串:
因此如果在log4net.config中再定义数据库连接字符串,总觉得不爽。
经过在网上一番搜索,居然发现log4net v1.2.10不支持这个Asp.Net2.0的特性,不过这篇文章给出了一个解决方法。
我们需要在AppBox中添加一个CS文件:
然后修改log4net.config文件:
注意,在log4net.config中我们指定使用名为 Default 的连接字符串。
使用log4net
调用方法倒很简单,比如在登录页面:
生成log记录类似:
为了实践项目驱动的ExtAspNet开发过程,最近我启动了另外一个开源项目 - AppBox。
AppBox项目使用ExtAspNet作为前台展现层,SubSonic作为ORM层,SqlServer2005作为数据库,在Asp.Net2.0基础之上实现一个企业综合管理系统所必须的基础组件。
包括用户管理,菜单管理,权限管理,组织结构管理等各个部分,虽然AppBox不是给最终用户使用的,但是可以作为开发人员搭建网站的一个框架,同时在项目中遇到的控件会优先在ExtAspNet中实现。
由于在AppBox中使用了log4net作为日志记录组件,所以这篇文章就来分享一下log4net的配置和使用。
log4net配置
1. 首先到 http://logging.apache.org/ 下载最新的log4net v1.2.10。
2. 建立数据库表
CREATE TABLE [dbo].[Log] ( [Id] [int] IDENTITY (1, 1) NOT NULL, [Date] [datetime] NOT NULL, [Thread] [varchar] (255) NOT NULL, [Level] [varchar] (50) NOT NULL, [Logger] [varchar] (255) NOT NULL, [Message] [varchar] (4000) NOT NULL, [Exception] [varchar] (2000) NULL )
3. 在网站根目录添加log4net.config文件
<log4net> <root> <level value="ALL"/> <appender-ref ref="AdoNetAppender"/> <appender-ref ref="RollingFileAppender"/> </root> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender,log4net"> <param name="File" value="log\log.config"/> <param name="AppendToFile" value="true"/> <param name="MaxSizeRollBackups" value="10"/> <param name="MaximumFileSize" value="5MB"/> <param name="RollingStyle" value="Size"/> <param name="StaticLogFileName" value="true"/> <layout type="log4net.Layout.PatternLayout,log4net"> <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n"/> </layout> </appender> <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender"> <bufferSize value="0"/> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089"/> <connectionString value="Password=sa;Persist Security Info=True;User ID=sa;Initial Catalog=AppBox;Data Source=."/> <commandText value="insert into X_Log(DATETIME,THREAD,LOG_LEVEL,LOGGER,MESSAGE,EXCEPTION) values (@log_date,@thread,@log_level,@logger,@message,@exception)"/> <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="@message"/> <dbType value="String"/> <size value="4000"/> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message"/> </layout> </parameter> <parameter> <parameterName value="@exception"/> <dbType value="String"/> <size value="2000"/> <layout type="log4net.Layout.ExceptionLayout"/> </parameter> </appender> </log4net>
注:这里我们使用了两种类型的日志记录方式,文件和数据库。
文件保存在网站根目录下的 log\log.config ,必须保证Asp.Net服务进程对此文件夹有写权限,否则不能写入文件并且没有任何提示。
比如在WindowXP下需要设置 ASPNET (Windows2003不是这个名称,可以Google一下) 对此文件夹的写权限。
同时注意我们使用log.config而不是log.txt,是为了防止匿名用户非法下载系统日志。
在数据库配置上也有个小技巧,我们设置了 bufferSize value="0",也就是说产生一条日志就写到数据库。
我刚开始也是在这个地方遇到麻烦,设置bufferSize为10,刚开始怎么也观察不到日志插入数据库,后来才知道被缓存了。
不要在多处定义数据库连接字符串
因为我们已经在Web.config中定义了数据库连接字符串:
<connectionStrings> <clear/> <add name="Default" connectionString="Password=sa;Persist Security Info=True;User ID=sa;Initial Catalog=AppBox;Data Source=."/> </connectionStrings>
因此如果在log4net.config中再定义数据库连接字符串,总觉得不爽。
经过在网上一番搜索,居然发现log4net v1.2.10不支持这个Asp.Net2.0的特性,不过这篇文章给出了一个解决方法。
我们需要在AppBox中添加一个CS文件:
using System; using System.Collections.Generic; using System.Web; using log4net; using log4net.Appender; using System.Configuration; namespace AppBox { /// <summary> /// http://issues.apache.org/jira/browse/LOG4NET-88 /// An appender for Log4Net that uses a database based on the connection string name. /// </summary> public class Log4NetConnectionStringNameAdoNetAppender : AdoNetAppender { private static ILog _Log; /// <summary> /// Gets the log. /// </summary> /// <value>The log.</value> protected static ILog Log { get { if (_Log == null) _Log = LogManager.GetLogger(typeof(Log4NetConnectionStringNameAdoNetAppender)); return _Log; } } private string _ConnectionStringName; /// <summary> /// Initialize the appender based on the options set /// </summary> /// <remarks> /// <para> /// This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object /// activation scheme. The <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> method must /// be called on this object after the configuration properties have /// been set. Until <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> is called this /// object is in an undefined state and must not be used. /// </para> /// <para> /// If any of the configuration properties are modified then /// <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> must be called again. /// </para> /// </remarks> public override void ActivateOptions() { PopulateConnectionString(); base.ActivateOptions(); } /// <summary> /// Populates the connection string. /// </summary> private void PopulateConnectionString() { // if connection string already defined, do nothing if (!String.IsNullOrEmpty(ConnectionString)) return; // if connection string name is not available, do nothing if (String.IsNullOrEmpty(ConnectionStringName)) return; // grab connection string settings ConnectionStringSettings settings = ConfigurationManager .ConnectionStrings[ConnectionStringName]; // if connection string name was not found in settings if (settings == null) { // log error if (Log.IsErrorEnabled) Log.ErrorFormat("Connection String Name not found in Configuration: {0}", ConnectionStringName); // do nothing more return; } // retrieve connection string from the name ConnectionString = settings.ConnectionString; } /// <summary> /// Gets or sets the name of the connection string. /// </summary> /// <value>The name of the connection string.</value> public string ConnectionStringName { get { return _ConnectionStringName; } set { _ConnectionStringName = value; } } } }
然后修改log4net.config文件:
<appender name="AdoNetAppender" type="AppBox.Log4NetConnectionStringNameAdoNetAppender"> <bufferSize value="0"/> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089"/> <connectionStringName value="Default"></connectionStringName> ........ ........ </appender>
注意,在log4net.config中我们指定使用名为 Default 的连接字符串。
使用log4net
调用方法倒很简单,比如在登录页面:
private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); protected void btnSubmit_Click(object sender, EventArgs e) { // .... logger.Info(String.Format("用户 - {0} - 登录成功", tbxUserName.Text)); }
生成log记录类似:
2009-08-19 18:05:37,932 [11] INFO AppBox._default [(null)] - 用户 - admin - 登录成功