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. 建立数据库表
    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 - 登录成功
    





你可能感兴趣的:(ext)