如何在通用權限管理系統中集成log4net日誌功能

開發人員都知道,在系統運行中要記錄各類日誌,本身寫一個日誌功能,不管是在效率仍是功能擴展上來講都不是很好,目前大多用的是第三方的日誌系統,其中一個很是有名,用的最多的就是log4net。下面是關於這個組件的介紹html

Log4net是基於.net開發的一款很是著名的記錄日誌開源組件。最先是2001年7月由NeoWorks Limited啓動的項目,基本的框架源, 於另外的一個很是著名的姐妹組件-log4j。現由Apache組織開發與維護。此日誌架構是可靈活擴展,且經過配置文件來設置日誌的屬性及輸出,不一樣修 改代碼便可實現程序的靈活跟蹤。能夠將日誌分不一樣的等級,經過不一樣的過濾條件,以不一樣的樣式,將日誌輸出到不一樣的媒介。能夠從http://logging.apache.org/log4net/l網站下載最新版本的Log4net源碼。web

目前的log4net的最新版本是1.2.13.0數據庫

下面介紹下如何在通用權限管理系統的項目中使用這個組件實現將日誌輸出到文件和Oracle數據庫中,重點介紹下日誌輸出到數據庫中。apache

首先在官網下載最新源碼,目前的源碼可用VS2010打開。緩存

 

源碼中已經實現了能夠日誌輸出到MSSQL的功能,但個人項目目前使用的都是Oracle數據庫,源碼中是沒有實現的,須要本身實現一下:安全

 

 

OracleAppender.cs源碼架構

    public class OracleAppender : BufferingAppenderSkeleton
    {
        // Fields
        private static readonly Type declaringType = typeof(AdoNetAppender);
        private string m_commandText;
        private CommandType m_commandType = CommandType.Text;
        private string m_connectionString;
        private string m_connectionType;
        private OracleCommand m_dbCommand;
        private OracleConnection m_dbConnection;
        protected ArrayList m_parameters = new ArrayList();
        private bool m_reconnectOnError = false;
        private SecurityContext m_securityContext;
        protected bool m_usePreparedCommand;
        private bool m_useTransactions = true;

        // Methods
        public override void ActivateOptions()
        {
            base.ActivateOptions();
            this.m_usePreparedCommand = (this.m_commandText != null) && (this.m_commandText.Length > 0);
            if (this.m_securityContext == null)
            {
                this.m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this);
            }
            this.InitializeDatabaseConnection();
            this.InitializeDatabaseCommand();
        }

        public void AddParameter(OracleAppenderParameter parameter)
        {
            this.m_parameters.Add(parameter);
        }

        protected virtual string GetLogStatement(LoggingEvent logEvent)
        {
            if (this.Layout == null)
            {
                this.ErrorHandler.Error("ADOAppender: No Layout specified.");
                return "";
            }
            StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
            this.Layout.Format(writer, logEvent);
            return writer.ToString();
        }

        private void InitializeDatabaseCommand()
        {
            if ((this.m_dbConnection != null) && this.m_usePreparedCommand)
            {
                try
                {
                    this.m_dbCommand = this.m_dbConnection.CreateCommand();
                    this.m_dbCommand.CommandText = this.m_commandText;
                    this.m_dbCommand.CommandType = this.m_commandType;
                }
                catch (Exception exception)
                {
                    this.ErrorHandler.Error("Could not create database command [" + this.m_commandText + "]", exception);
                    if (this.m_dbCommand != null)
                    {
                        try
                        {
                            this.m_dbCommand.Dispose();
                        }
                        catch
                        {
                        }
                        this.m_dbCommand = null;
                    }
                }
                if (this.m_dbCommand != null)
                {
                    try
                    {
                        foreach (OracleAppenderParameter parameter in this.m_parameters)
                        {
                            try
                            {
                                parameter.Prepare(this.m_dbCommand);
                            }
                            catch (Exception exception2)
                            {
                                this.ErrorHandler.Error("Could not add database command parameter [" + parameter.ParameterName + "]", exception2);
                                throw;
                            }
                        }
                    }
                    catch
                    {
                        try
                        {
                            this.m_dbCommand.Dispose();
                        }
                        catch
                        {
                        }
                        this.m_dbCommand = null;
                    }
                }
                if (this.m_dbCommand != null)
                {
                    try
                    {
                        this.m_dbCommand.Prepare();
                    }
                    catch (Exception exception3)
                    {
                        this.ErrorHandler.Error("Could not prepare database command [" + this.m_commandText + "]", exception3);
                        try
                        {
                            this.m_dbCommand.Dispose();
                        }
                        catch
                        {
                        }
                        this.m_dbCommand = null;
                    }
                }
            }
        }

        private void InitializeDatabaseConnection()
        {
            try
            {
                this.m_dbConnection = new OracleConnection();
                this.m_dbConnection.ConnectionString = this.m_connectionString;
                using (this.SecurityContext.Impersonate(this))
                {
                    this.m_dbConnection.Open();
                }
            }
            catch (Exception exception)
            {
                this.ErrorHandler.Error("Could not open database connection [" + this.m_connectionString + "]", exception);
                this.m_dbConnection = null;
            }
        }

        protected override void OnClose()
        {
            base.OnClose();
            if (this.m_dbCommand != null)
            {
                this.m_dbCommand.Dispose();
                this.m_dbCommand = null;
            }
            if (this.m_dbConnection != null)
            {
                this.m_dbConnection.Close();
                this.m_dbConnection = null;
            }
        }

        protected virtual Type ResolveConnectionType()
        {
            Type type;
            try
            {
                type = SystemInfo.GetTypeFromString(this.m_connectionType, true, false);
            }
            catch (Exception exception)
            {
                this.ErrorHandler.Error("Failed to load connection type [" + this.m_connectionType + "]", exception);
                throw;
            }
            return type;
        }

        protected override void SendBuffer(LoggingEvent[] events)
        {
            if (this.m_reconnectOnError && ((this.m_dbConnection == null) || (this.m_dbConnection.State != ConnectionState.Open)))
            {
                LogLog.Debug(declaringType, "OracleAppender: Attempting to reconnect to database. Current Connection State: " + ((this.m_dbConnection == null) ? "<null>" : this.m_dbConnection.State.ToString()));
                this.InitializeDatabaseConnection();
                this.InitializeDatabaseCommand();
            }
            if ((this.m_dbConnection != null) && (this.m_dbConnection.State == ConnectionState.Open))
            {
                if (this.m_useTransactions)
                {
                    OracleTransaction dbTran = null;
                    try
                    {
                        dbTran = this.m_dbConnection.BeginTransaction();
                        this.SendBuffer(dbTran, events);
                        dbTran.Commit();
                    }
                    catch (Exception exception)
                    {
                        if (dbTran != null)
                        {
                            try
                            {
                                dbTran.Rollback();
                            }
                            catch (Exception)
                            {
                            }
                        }
                        this.ErrorHandler.Error("Exception while writing to database", exception);
                    }
                }
                else
                {
                    this.SendBuffer(null, events);
                }
            }
        }

        protected virtual void SendBuffer(OracleTransaction dbTran, LoggingEvent[] events)
        {
            if (!this.m_usePreparedCommand)
            {
                throw new NotImplementedException();
            }
            if (this.m_dbCommand != null)
            {
                ArrayList list = null;
                foreach (OracleAppenderParameter parameter in this.m_parameters)
                {
                    list = new ArrayList();
                    OracleParameter parameter2 = this.m_dbCommand.Parameters[parameter.ParameterName];
                    foreach (LoggingEvent event2 in events)
                    {
                        object obj2 = parameter.Layout.Format(event2);
                        if (obj2.ToString() == "(null)")
                        {
                            obj2 = DBNull.Value;
                        }
                        list.Add(obj2);
                    }
                    parameter2.Value = list.ToArray();
                }
                this.m_dbCommand.ArrayBindCount = events.Length;
                this.m_dbCommand.ExecuteNonQuery();
            }
        }

        // Properties
        public string CommandText
        {
            get
            {
                return this.m_commandText;
            }
            set
            {
                this.m_commandText = value;
            }
        }

        public CommandType CommandType
        {
            get
            {
                return this.m_commandType;
            }
            set
            {
                this.m_commandType = value;
            }
        }

        protected OracleConnection Connection
        {
            get
            {
                return this.m_dbConnection;
            }
            set
            {
                this.m_dbConnection = value;
            }
        }

        public string ConnectionString
        {
            get
            {
                return this.m_connectionString;
            }
            set
            {
                this.m_connectionString = value;
            }
        }

        public bool ReconnectOnError
        {
            get
            {
                return this.m_reconnectOnError;
            }
            set
            {
                this.m_reconnectOnError = value;
            }
        }

        public SecurityContext SecurityContext
        {
            get
            {
                return this.m_securityContext;
            }
            set
            {
                this.m_securityContext = value;
            }
        }

        public bool UseTransactions
        {
            get
            {
                return this.m_useTransactions;
            }
            set
            {
                this.m_useTransactions = value;
            }
        }
    }
View Code

OracleAppenderParameter.cs源碼oracle

    public class OracleAppenderParameter
    {
        // Fields
        private DbType m_dbType;
        private bool m_inferType = true;
        private IRawLayout m_layout;
        private string m_parameterName;
        private byte m_precision = 0;
        private byte m_scale = 0;
        private int m_size = 0;

        // Methods
        public virtual void FormatValue(OracleCommand command, LoggingEvent loggingEvent)
        {
            OracleParameter parameter = command.Parameters[this.m_parameterName];
            parameter.Value = this.Layout.Format(loggingEvent);
        }

        public virtual void Prepare(OracleCommand command)
        {
            OracleParameter param = command.CreateParameter();
            param.ParameterName = this.m_parameterName;
            if (!this.m_inferType)
            {
                param.DbType = this.m_dbType;
            }
            if (this.m_precision != 0)
            {
                param.Precision = this.m_precision;
            }
            if (this.m_scale != 0)
            {
                param.Scale = this.m_scale;
            }
            if (this.m_size != 0)
            {
                param.Size = this.m_size;
            }
            command.Parameters.Add(param);
        }

        // Properties
        public DbType DbType
        {
            get
            {
                return this.m_dbType;
            }
            set
            {
                this.m_dbType = value;
                this.m_inferType = false;
            }
        }

        public IRawLayout Layout
        {
            get
            {
                return this.m_layout;
            }
            set
            {
                this.m_layout = value;
            }
        }

        public string ParameterName
        {
            get
            {
                return this.m_parameterName;
            }
            set
            {
                this.m_parameterName = value;
            }
        }

        public byte Precision
        {
            get
            {
                return this.m_precision;
            }
            set
            {
                this.m_precision = value;
            }
        }

        public byte Scale
        {
            get
            {
                return this.m_scale;
            }
            set
            {
                this.m_scale = value;
            }
        }

        public int Size
        {
            get
            {
                return this.m_size;
            }
            set
            {
                this.m_size = value;
            }
        }
    }
View Code


將源碼從新編譯,生成log4net.dll文件,下面的項目將引用這個類庫文件。app

爲了在程序中更方便的將日誌輸出到文件、Email、數據庫中,封裝了一下日誌輸出功能,DotNet.Log是封裝的類庫框架

其中的DotNet.Business,DotNet.IService,DotNet.Model,DotNet.Utilities類庫是通用權限系統底層的,

DotNet.Log引用了其中的DotNet.Model,主要目的是爲了將用戶相關信息存儲到日誌的表中。

其中的LogHelper.cs代碼

//-------------------------------------------------------------------------------------
// All Rights Reserved , Copyright (C) 2014 , ZTO , Ltd .
//-------------------------------------------------------------------------------------

using System;
using System.Configuration;
using System.IO;

namespace DotNet.Log
{
    using DotNet.Utilities;
    using log4net;
    using log4net.Appender;

    /// <summary>
    /// ZTOLog4NetHelper
    /// 
    /// 修改紀錄
    /// 
    /// 系統運行日誌可寫入到文本文件或數據庫(ORACLE)
    /// 
    /// 2014-10-17 版本:1.0 SongBiao 建立文件。   
    /// 
    /// <author>
    ///     <name>SongBiao</name>
    ///     <date>2014-10-17</date>
    /// </author>
    /// </summary>
    public class LogHelper
    {
        /// <summary>
        /// 日誌對象  沒有在配置文件設置(沒有類定義) 則經過反射 
        /// 方法使用root的配置
        /// </summary>
        private static ILog log;
        private static LogHelper logHelper = null;
        /// <summary>
        /// 初始化
        /// </summary>
        /// <returns></returns>
        public static ILog GetInstance()
        {
            logHelper = new LogHelper(null);
            return log;
        }
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="configPath"></param>
        /// <returns></returns>
        public static ILog GetInstance(string configPath)
        {
            logHelper = new LogHelper(configPath);
            return log;
        }
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="configPath"></param>
        private LogHelper(string configPath)
        {
            if (!string.IsNullOrEmpty(configPath))
            {
                log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                //log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(configPath));
                //初始化Log4net
                log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(System.Web.HttpContext.Current.Server.MapPath(configPath)));
            }
            else
            {
                log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            }
        }

        #region 日誌寫入到文件
        /// <summary>
        /// 調試日誌
        /// </summary>
        private static readonly ILog logDebugFile = DotNetLogManager.GetLogger("LogDebug");
        /// <summary>
        /// 寫入調試日誌
        /// </summary>
        /// <param name="info"></param>
        public static void WriteDebugLog(string info)
        {
            if (logDebugFile.IsInfoEnabled)
            {
                logDebugFile.Info(info);
            }
        }

        /// <summary>
        /// 信息日誌
        /// </summary>
        private static readonly ILog logInfoFile = DotNetLogManager.GetLogger("LogInfo");
        /// <summary>
        /// 寫入信息日誌
        /// </summary>
        /// <param name="info"></param>
        public static void WriteInfoLog(string info)
        {
            if (logInfoFile.IsInfoEnabled)
            {
                logInfoFile.Info(info);
            }
        }

        /// <summary>
        /// 警告日誌
        /// </summary>
        private static readonly ILog logErrorFile = DotNetLogManager.GetLogger("LogError");
        /// <summary>
        /// 寫入錯誤異常日誌
        /// </summary>
        /// <param name="info"></param>
        /// <param name="se"></param>
        public static void WriteErrorLog(string info, Exception se)
        {
            if (logErrorFile.IsErrorEnabled)
            {
                logErrorFile.Error(info, se);
            }
        }

        /// <summary>
        /// 警告日誌
        /// </summary>
        private static readonly ILog logWarnFile = DotNetLogManager.GetLogger("LogWarn");
        /// <summary>
        /// 寫入警告日誌
        /// </summary>
        /// <param name="info"></param>
        /// <param name="se"></param>
        public static void WriteWarnLog(string info, Exception se)
        {
            if (logWarnFile.IsErrorEnabled)
            {
                logWarnFile.Error(info, se);
            }
        }

        /// <summary>
        /// 毀滅級別日誌
        /// </summary>
        private static readonly ILog logFatalFile = DotNetLogManager.GetLogger("LogFatal");
        /// <summary>
        /// 寫入毀滅級別日誌
        /// </summary>
        /// <param name="info"></param>
        /// <param name="se"></param>
        public static void WriteFatalLog(string info, Exception se)
        {
            if (logFatalFile.IsFatalEnabled)
            {
                logFatalFile.Error(info, se);
            }
        }

        /// <summary>
        /// 非安全行爲日誌記錄
        /// </summary>
        private static readonly log4net.ILog logSafeFile = DotNetLogManager.GetLogger("LogSafe");
        /// <summary>
        /// 非安全行爲日誌記錄
        /// </summary>
        /// <param name="info"></param>
        public static void WriteSafeLog(string info)
        {
            if (logSafeFile.IsInfoEnabled)
            {
                logSafeFile.Info(info);
            }
        }

        /// <summary>
        /// 緩存記錄變更的日誌對象 當前配置是輸出到文件中
        /// </summary>
        private static readonly ILog logCacheFile = DotNetLogManager.GetLogger("logcache");
        /// <summary>
        /// 寫入緩存變更日誌
        /// </summary>
        /// <param name="info"></param>
        public static void WriteCacheLog(string info)
        {
            if (logCacheFile.IsInfoEnabled)
            {
                logCacheFile.Info(info);
            }
        }
        #endregion
        #region 發送到郵箱
        /// <summary>
        /// 發送到郵箱
        /// </summary>
        private static readonly ILog logEmailWarn = DotNetLogManager.GetLogger("LogEmail");

        /// <summary>
        /// 郵件通知 通常是警告類或異常類 內網可能發不了
        /// </summary>
        /// <param name="info"></param>
        /// <param name="se"></param>
        public static void WriteEmailLog(string info, Exception se)
        {
            if (logEmailWarn.IsInfoEnabled)
            {
                logEmailWarn.Error(info, se);
            }
        }
        #endregion
        #region 日誌寫入到Oracle數據庫表
        /// <summary>
        /// Oracle數據庫記錄
        /// </summary>
        public static IZTOLog logOracle = DotNetLogManager.GetLogger("LogOracle");
        /// <summary>
        /// 5. 調試級別
        /// </summary>
        /// <param name="userInfo">用戶信息</param>
        /// <param name="message">日誌信息</param>
        /// <param name="type">出錯類的類名,可自定義</param>
        public static void OracleDebug(BaseUserInfo userInfo, string title, object message, string functionName, Type type)
        {
            logOracle.Debug(userInfo, type.ToString(), functionName, title, message);
        }

        /// <summary>
        /// 4. 消息級別
        /// </summary>
        /// <param name="userInfo">用戶信息</param>
        /// <param name="message">日誌信息</param>
        /// <param name="type">出錯類的類名,可自定義</param>
        public static void OracleInfo(BaseUserInfo userInfo, string title, object message, string functionName, Type type)
        {
            logOracle.Info(userInfo, type.ToString(), functionName, title, message);
        }

        /// <summary>
        /// 3. 警告級別
        /// </summary>
        /// <param name="userInfo">用戶信息</param>
        /// <param name="message">日誌信息</param>
        /// <param name="type">出錯類的類名,可自定義</param>
        public static void OracleWarn(BaseUserInfo userInfo, string title, object message, string functionName, Type type)
        {
            logOracle.Warn(userInfo, type.ToString(), functionName, title, message, null);
        }

        /// <summary> 
        /// 3. 警告級別 帶異常
        /// </summary>
        /// <param name="userInfo">用戶信息</param>
        /// <param name="message">日誌信息</param>
        /// <param name="type">出錯類的類名,可自定義</param>
        public static void OracleWarn(BaseUserInfo userInfo, string title, object message, string functionName, Type type, System.Exception ex)
        {
            logOracle.Warn(userInfo, type.ToString(), functionName, title, message, ex);
        }

        /// <summary>
        /// 2. 錯誤級別 不帶異常
        /// </summary>
        /// <param name="userInfo"></param>
        /// <param name="message"></param>
        /// <param name="functionName"></param>
        /// <param name="type"></param>
        public static void OracleError(BaseUserInfo userInfo, string title, object message, string functionName, Type type)
        {
            logOracle.Error(userInfo, type.ToString(), functionName, title, message, null);
        }

        /// <summary>
        /// 2. 錯誤級別 待異常
        /// </summary>
        /// <param name="userInfo">用戶信息</param>
        /// <param name="title">日誌標題</param>
        /// <param name="message">日誌信息</param>
        /// <param name="type">出錯類的類名,可自定義</param>
        /// <param name="Exception">異常信息</param>
        public static void OracleError(BaseUserInfo userInfo, string title, object message, string functionName, Type type, System.Exception ex)
        {
            logOracle.Error(userInfo, type.ToString(), functionName, title, message, ex);
        }

        /// <summary>
        /// 1. 毀滅級別 不帶異常
        /// </summary>
        /// <param name="userInfo"></param>
        /// <param name="title">日誌標題</param>
        /// <param name="message"></param>
        /// <param name="functionName"></param>
        /// <param name="type"></param>
        public static void OracleFatal(BaseUserInfo userInfo, string title, object message, string functionName, Type type)
        {
            logOracle.Fatal(userInfo, type.ToString(), functionName, title, message, null);
        }

        /// <summary>
        /// 1. 毀滅級別 帶異常
        /// </summary>
        /// <param name="userInfo">用戶信息</param>
        /// <param name="title">日誌標題</param>
        /// <param name="message">日誌信息</param>
        /// <param name="type">出錯類的類名,可自定義</param>
        public static void OracleFatal(BaseUserInfo userInfo, string title, object message, string functionName, Type type, System.Exception ex)
        {
            logOracle.Fatal(userInfo, type.ToString(), functionName, title, message, ex);
        }
        #endregion
    }

}

/* Oracle數據庫表建立
 -- Create table
create table SECURITY_LOG4NET
(
  LOG_ID        NUMBER not null,
  LOG_DATE      DATE,
  LOG_LEVEL     VARCHAR2(255),
  LOG_MESSAGE   VARCHAR2(4000),
  LOG_EXCEPTION VARCHAR2(4000),
  LOG_LOGGER    VARCHAR2(255),
  LOG_SOURCE    VARCHAR2(1000),
  USERID        NUMBER,
  LOGTYPE       VARCHAR2(255),
  IP            VARCHAR2(20),
  FUNCTIONNAME  VARCHAR2(255),
  REALNAME      VARCHAR2(50),
  SYSTEMCODE    VARCHAR2(200),
  LOG_TITLE     VARCHAR2(60)
)
tablespace USERS
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    next 8K
    minextents 1
    maxextents unlimited
  );
-- Add comments to the columns 
comment on column SECURITY_LOG4NET.LOG_ID
  is 'ID主鍵';
comment on column SECURITY_LOG4NET.LOG_DATE
  is '記錄時間';
comment on column SECURITY_LOG4NET.LOG_LEVEL
  is '日誌級別:調試級別:Debug,消息級別:Info,警告級別:Warn,錯誤級別:Error,毀滅級別:Fatal';
comment on column SECURITY_LOG4NET.LOG_MESSAGE
  is '操做描述';
comment on column SECURITY_LOG4NET.LOG_EXCEPTION
  is '異常消息';
comment on column SECURITY_LOG4NET.LOG_LOGGER
  is '日誌記錄器';
comment on column SECURITY_LOG4NET.LOG_SOURCE
  is '日誌源';
comment on column SECURITY_LOG4NET.USERID
  is '用戶主鍵ID';
comment on column SECURITY_LOG4NET.LOGTYPE
  is '操做類';
comment on column SECURITY_LOG4NET.IP
  is '操做IP';
comment on column SECURITY_LOG4NET.FUNCTIONNAME
  is '方法名稱';
comment on column SECURITY_LOG4NET.REALNAME
  is '用戶姓名';
comment on column SECURITY_LOG4NET.SYSTEMCODE
  is '子系統編號';
comment on column SECURITY_LOG4NET.LOG_TITLE
  is '日誌標題';
-- Create/Recreate primary, unique and foreign key constraints 
alter table SECURITY_LOG4NET
  add constraint SECURITY_LOG4NET_PK primary key (LOG_ID)
  using index 
  tablespace USERS
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
 */
View Code

項目中將日誌記錄到各個介質就引用這個LogHelper了。

在項目中再引用DotNet.Log,個人是一個web項目,須要設置一個配置文件。


Log4Net.config是配置日誌向各類介質輸出的功能,所有配置代碼:

<?xml version="1.0" encoding="utf-8"?>
<log4net>
  <root>
    <!--<level value="INFO" />-->
    <!--啓用按日期分割-->
    <!--<appender-ref ref="LogFileAppenderByDate" />-->
    <!--啓用按容量分割-->
    <!--<appender-ref ref="LogFileAppenderBySize" />-->
    <!--啓用保存到數據庫-->
    <!--<appender-ref ref="AdoNetAppender" />-->
  </root>

  <!--DEBUG 調試信息記錄器-->
  <logger name="LogDebug"  additivity="false">
    <level value="DEBUG" />
    <appender-ref ref="logger.DebugAppender" />
  </logger>
  <appender name="logger.DebugAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="LOG//DEBUG//" />
    <!--是否續寫 True/false,默認爲true。當文件存在時,是否在原文件上追加內容。-->
    <param name="AppendToFile" value="true" />
    <!--單個文件大小 當RollingStyle爲Composite或Size,這裏設置最大文件大小(能夠KB,MB,GB爲單位,默認爲字節)-->
    <param name="MaxFileSize" value="10240" />
    <!--備份日誌數目 默認爲0 可設最多保存多少個文件-->
    <param name="MaxSizeRollBackups" value="0" />
    <!--寫入的文件名 爲true時,RollingStyler的date值將無效。且爲true時,須要在file裏指定文件名,全部日誌都會記錄在這個文件裏。-->
    <param name="StaticLogFileName" value="false" />
    <!--當RollingStyle爲Composite或Date,這裏設置文件名格式-->
    <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
    <!--建立新文件的方式,可選爲Size(按文件大小),Date(按日期), Once(每啓動一次建立一個文件),Composite(按日期及文件大小),默認爲Composite-->
    <param name="RollingStyle" value="Date" />
    <!--log4net的日誌輸出格式-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="Header" value="◇◇◇◇◇開始◇◇◇◇◇◇" />
      <param name="Footer" value="◆◆◆◆◆結束◆◆◆◆◆◆" />
      <param name="ConversionPattern" value="%n時間:%d %n級別:%level %n類名:%c%n文件:%F 第%L行%n日誌內容:%m%n-----------------------------------------%n" />
    </layout>
  </appender>
  
  <!--INFO 普通訊息記錄器-->
  <logger name="LogInfo"  additivity="false">
    <level value="INFO" />
    <appender-ref ref="logger.InfoAppender" />
  </logger>
  <appender name="logger.InfoAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="LOG//INFO//" />
    <!--是否續寫 True/false,默認爲true。當文件存在時,是否在原文件上追加內容。-->
    <param name="AppendToFile" value="true" />
    <!--單個文件大小 當RollingStyle爲Composite或Size,這裏設置最大文件大小(能夠KB,MB,GB爲單位,默認爲字節)-->
    <param name="MaxFileSize" value="10240" />
    <!--備份日誌數目 默認爲0 可設最多保存多少個文件-->
    <param name="MaxSizeRollBackups" value="0" />
    <!--寫入的文件名 爲true時,RollingStyler的date值將無效。且爲true時,須要在file裏指定文件名,全部日誌都會記錄在這個文件裏。-->
    <param name="StaticLogFileName" value="false" />
    <!--當RollingStyle爲Composite或Date,這裏設置文件名格式-->
    <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
    <!--建立新文件的方式,可選爲Size(按文件大小),Date(按日期), Once(每啓動一次建立一個文件),Composite(按日期及文件大小),默認爲Composite-->
    <param name="RollingStyle" value="Date" />
    <!--log4net的日誌輸出格式-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="Header" value="◇◇◇◇◇開始◇◇◇◇◇◇" />
      <param name="Footer" value="◆◆◆◆◆結束◆◆◆◆◆◆" />
      <param name="ConversionPattern" value="%n時間:%d %n級別:%level %n類名:%c%n文件:%F 第%L行%n日誌內容:%m%n-----------------------------------------%n" />
    </layout>
  </appender>

  <!--ERROR 錯誤記錄器-->
  <logger name="LogError" additivity="false">
    <level value="ERROR" />
    <appender-ref ref="logger.ErrorAppender" additivity="false"/>
  </logger>
  <appender name="logger.ErrorAppender" type="log4net.Appender.RollingFileAppender">
    <!--是否續寫-->
    <param name="AppendToFile" value="true" />
    <!--備份日誌數目 默認爲0 可設最多保存多少個文件-->
    <param name="MaxSizeRollBackups" value="0" />
    <!--單個文件大小-->
    <param name="MaxFileSize" value="10240" />
    <!--寫入的文件名 爲true時,RollingStyler的date值將無效。且爲true時,須要在file裏指定文件名,全部日誌都會記錄在這個文件裏。-->
    <param name="StaticLogFileName" value="false" />
    <param name="File" value="Log//ERROR//" />
    <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;"/>
    <param name="RollingStyle" value="Date" />
    <!--log4net的日誌輸出格式-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="Header" value="◇◇◇◇◇開始◇◇◇◇◇◇" />
      <param name="Footer" value="◆◆◆◆◆結束◆◆◆◆◆◆" />
      <!--<param name="ConversionPattern" value="%n%d [%t] %-5p %c [%x] - %m%n%n%n" />-->
      <param name="ConversionPattern" value="%n時間:%d %n級別:%level %n類名:%c%n文件:%F 第%L行%n日誌內容:%m%n-----------------------------------------%n" />
    </layout>
  </appender>

  <!--WARN 警告日誌記錄器-->
  <logger name="LogWarn" additivity="false">
    <level value="WARN" />
    <appender-ref ref="logger.WarnAppender" additivity="false"/>
  </logger>
  <appender name="logger.WarnAppender" type="log4net.Appender.RollingFileAppender">
    <!--是否續寫-->
    <param name="AppendToFile" value="true" />
    <!--備份日誌數目 默認爲0 可設最多保存多少個文件-->
    <param name="MaxSizeRollBackups" value="0" />
    <!--單個文件大小-->
    <param name="MaxFileSize" value="10240" />
    <!--寫入的文件名 爲true時,RollingStyler的date值將無效。且爲true時,須要在file裏指定文件名,全部日誌都會記錄在這個文件裏。-->
    <param name="StaticLogFileName" value="false" />
    <param name="File" value="LOG//WARN//" />
    <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;"/>
    <param name="RollingStyle" value="Date" />
    <!--log4net的日誌輸出格式-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="Header" value="◇◇◇◇◇開始◇◇◇◇◇◇" />
      <param name="Footer" value="◆◆◆◆◆結束◆◆◆◆◆◆" />
      <!--<param name="ConversionPattern" value="%n%d [%t] %-5p %c [%x] - %m%n%n%n" />-->
      <param name="ConversionPattern" value="%n時間:%d %n級別:%level %n類名:%c%n文件:%F 第%L行%n日誌內容:%m%n-----------------------------------------%n" />
    </layout>
  </appender>

  <!--FATAL 毀滅級別日誌記錄器-->
  <logger name="LogFatal" additivity="false">
    <level value="FATAL" />
    <appender-ref ref="logger.FatalAppender" additivity="false"/>
  </logger>
  <appender name="logger.FatalAppender" type="log4net.Appender.RollingFileAppender">
    <!--是否續寫-->
    <param name="AppendToFile" value="true" />
    <!--備份日誌數目 默認爲0 可設最多保存多少個文件-->
    <param name="MaxSizeRollBackups" value="0" />
    <!--單個文件大小-->
    <param name="MaxFileSize" value="10240" />
    <!--寫入的文件名 爲true時,RollingStyler的date值將無效。且爲true時,須要在file裏指定文件名,全部日誌都會記錄在這個文件裏。-->
    <param name="StaticLogFileName" value="false" />
    <param name="File" value="LOG//FATAL//" />
    <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;"/>
    <param name="RollingStyle" value="Date" />
    <!--log4net的日誌輸出格式-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="Header" value="◇◇◇◇◇開始◇◇◇◇◇◇" />
      <param name="Footer" value="◆◆◆◆◆結束◆◆◆◆◆◆" />
      <!--<param name="ConversionPattern" value="%n%d [%t] %-5p %c [%x] - %m%n%n%n" />-->
      <param name="ConversionPattern" value="%n時間:%d %n級別:%level %n類名:%c%n文件:%F 第%L行%n日誌內容:%m%n-----------------------------------------%n" />
    </layout>
  </appender>

  

  <!--CACHE 緩存變動記錄器-->
  <logger name="LogCache"  additivity="false">
    <level value="ALL" />
    <appender-ref ref="logger.CacheAppender" />
  </logger>
  <appender name="logger.CacheAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="LOG//CACHE//" />
    <!--是否續寫 True/false,默認爲true。當文件存在時,是否在原文件上追加內容。-->
    <param name="AppendToFile" value="true" />
    <!--單個文件大小 當RollingStyle爲Composite或Size,這裏設置最大文件大小(能夠KB,MB,GB爲單位,默認爲字節)-->
    <param name="MaxFileSize" value="10240" />
    <!--備份日誌數目 默認爲0 可設最多保存多少個文件-->
    <param name="MaxSizeRollBackups" value="0" />
    <!--寫入的文件名 爲true時,RollingStyler的date值將無效。且爲true時,須要在file裏指定文件名,全部日誌都會記錄在這個文件裏。-->
    <param name="StaticLogFileName" value="false" />
    <!--當RollingStyle爲Composite或Date,這裏設置文件名格式-->
    <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
    <!--建立新文件的方式,可選爲Size(按文件大小),Date(按日期), Once(每啓動一次建立一個文件),Composite(按日期及文件大小),默認爲Composite-->
    <param name="RollingStyle" value="Date" />
    <!--log4net的日誌輸出格式-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="Header" value="◇◇◇◇◇開始◇◇◇◇◇◇" />
      <param name="Footer" value="◆◆◆◆◆結束◆◆◆◆◆◆" />
      <!--<param name="ConversionPattern" value="%n%d [%t] %-5p %c [%x] - %m%n%n%n" />-->
      <param name="ConversionPattern" value="%n時間:%d %n級別:%level %n類名:%c%n文件:%F 第%L行%n日誌內容:%m%n-----------------------------------------%n" />
    </layout>
  </appender>

  <!--非安全行爲 日誌記錄器-->
  <logger name="LogSafe"  additivity="false">
    <level value="ALL" />
    <appender-ref ref="logger.SafeAppender" />
  </logger>
  <appender name="logger.SafeAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="LOG//SAFE//" />
    <!--是否續寫 True/false,默認爲true。當文件存在時,是否在原文件上追加內容。-->
    <param name="AppendToFile" value="true" />
    <!--單個文件大小 當RollingStyle爲Composite或Size,這裏設置最大文件大小(能夠KB,MB,GB爲單位,默認爲字節)-->
    <param name="MaxFileSize" value="10240" />
    <!--備份日誌數目 默認爲0 可設最多保存多少個文件-->
    <param name="MaxSizeRollBackups" value="0" />
    <!--寫入的文件名 爲true時,RollingStyler的date值將無效。且爲true時,須要在file裏指定文件名,全部日誌都會記錄在這個文件裏。-->
    <param name="StaticLogFileName" value="false" />
    <!--當RollingStyle爲Composite或Date,這裏設置文件名格式-->
    <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
    <!--建立新文件的方式,可選爲Size(按文件大小),Date(按日期), Once(每啓動一次建立一個文件),Composite(按日期及文件大小),默認爲Composite-->
    <param name="RollingStyle" value="Date" />
    <!--log4net的日誌輸出格式-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="Header" value="◇◇◇◇◇開始◇◇◇◇◇◇" />
      <param name="Footer" value="◆◆◆◆◆結束◆◆◆◆◆◆" />
      <!--<param name="ConversionPattern" value="%n%d [%t] %-5p %c [%x] - %m%n%n%n" />-->
      <param name="ConversionPattern" value="%n時間:%d %n級別:%level %n類名:%c%n文件:%F 第%L行%n日誌內容:%m%n-----------------------------------------%n" />
    </layout>
  </appender>


  <!--EMAIL 發郵件 注意內網可能不能發送郵件 -->
  <logger name="LogEmail" additivity="false">
    <level value="ALL" />
    <appender-ref ref="logger.EmaiAppender" />
  </logger>
  <appender name="logger.EmaiAppender" type="log4net.Appender.SMTPAppender">
    <authentication  value="Basic"/>
    <subject  value="【中通快遞系統】運行異常狀態報告" />
    <to  value="songbiao@zto.cn" />
    <from  value="ztoexception@zto.cn" />
    <smtphost  value="mail.zto.cn" />
    <username  value="ztoexception" />
    <password  value="d1fbf1ff" />
    <port value="25"/>
    <bufferSize  value="2048" />
    <!--超長部分是否丟棄-->
    <lossy value="true" />
    <!-- 下面的定義, 就是 日誌級別 大於 WARN 的, 才發郵件. -->
    <evaluator type="log4net.Core.LevelEvaluator">
      <threshold value="WARN" />
    </evaluator>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%property{log4net:HostName} :: %level :: %message %newlineLogger: %logger%newlineThread: %thread%newlineDate: %date%newlineNDC: %property{NDC}%newline%newline" />
    </layout>
  </appender>

  <!--專門爲Oracle寫的日誌記錄器 -->
  <logger name="LogOracle" additivity="false">
    <level value="ALL" />
    <appender-ref ref="logger.AdoNetAppender_Oracle" />
  </logger>
  <appender name="logger.AdoNetAppender_Oracle" type="DotNet.Log.OracleAdoNetAppender">
    <bufferSize value="1" />
    <connectionType value="Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=4.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
    <ConnectionStringName value="Log4NetOracleDBConnection" />
    <commandText value="INSERT INTO SECURITY_LOG4NET (LOG_ID, LOG_DATE, LOG_LEVEL, LOG_MESSAGE, LOG_EXCEPTION, LOG_LOGGER, LOG_SOURCE,USERID,LOGTYPE,IP,FUNCTIONNAME,REALNAME,LOG_TITLE,SYSTEMCODE) VALUES (SEQ_SECURITY_LOG4NET.nextval, :log_date, :log_level,:log_message, :log_exception, :logger, :source,:USERID,:LOGTYPE,:IP,:FUNCTIONNAME,:REALNAME,:LOG_TITLE,:SYSTEMCODE)" />
    <!--注意自定義的字段的大小寫要一致   -->
    <parameter>
      <parameterName value=":log_date" />
      <dbType value="DateTime" />
      <layout type="log4net.Layout.RawTimeStampLayout">
        <conversionPattern value="%d{yyyy/MM/dd HH:mm:ss}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":log_level" />
      <dbType value="String" />
      <size value="10" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%level" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":log_message" />
      <dbType value="String" />
      <size value="4000" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%m" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":log_exception" />
      <dbType value="String" />
      <size value="4000" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%exception" />
      </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=":source" />
      <dbType value="String" />
      <size value="1000" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%file:%line" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":USERID" />
      <dbType value="Int32" />
      <layout type="DotNet.Log.CustomLayout">
        <conversionPattern value="%property{UserID}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":LOGTYPE" />
      <dbType value="String" />
      <layout type="DotNet.Log.CustomLayout">
        <conversionPattern value="%property{LOGTYPE}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":IP" />
      <dbType value="String" />
      <layout type="DotNet.Log.CustomLayout">
        <conversionPattern value="%property{IP}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":FUNCTIONNAME" />
      <dbType value="String" />
      <layout type="DotNet.Log.CustomLayout">
        <conversionPattern value="%property{FUNCTIONNAME}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":REALNAME" />
      <dbType value="String" />
      <layout type="DotNet.Log.CustomLayout">
        <conversionPattern value="%property{REALNAME}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":LOG_TITLE" />
      <dbType value="String" />
      <layout type="DotNet.Log.CustomLayout">
        <conversionPattern value="%property{LOG_TITLE}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value=":SYSTEMCODE" />
      <dbType value="String" />
      <layout type="DotNet.Log.CustomLayout">
        <conversionPattern value="%property{SYSTEMCODE}" />
      </layout>
    </parameter>
  </appender>

  <!--日誌信息輸出到頁面的Trace上下文環-->
  <logger name="LogAspNetTrace" additivity="false">
    <level value="ALL" />
    <appender-ref ref="logger.AspNetTraceAppender" />
  </logger>
  <!--這段配置可將日誌信息輸出到頁面的Trace上下文環境。
  若是日誌的級別低於WARN,會以 System.Web.TraceContext.Write方法輸出;
  若是級別爲WARN或WARN以上則會以 System.Web.TraceContext.Warn方法輸出,輸出的不一樣顏色能夠說明這一點-->
  <appender name ="logger.AspNetTraceAppender"  type ="log4net.Appender.AspNetTraceAppender">
    <layout type ="log4net.Layout.PatternLayout" >
      <conversionPattern value ="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
    </layout>
  </appender>

  <!--日誌信息輸出到控制檯 高亮顯示Error信息-->
  <logger name="LogColoredConsole" additivity="false">
    <level value="ALL" />
    <appender-ref ref="logger.ColoredConsoleAppender" />
  </logger>
  <!--ColoredConsoleAppender將日誌信息輸出到控制檯。
  默認狀況下,日誌信息被髮送到控制檯標準輸出流。下面這個示例演示瞭如何高亮顯示Error信息。-->
  <appender name ="logger.ColoredConsoleAppender"  type ="log4net.Appender.ColoredConsoleAppender">
    <mapping >
      <level value ="ERROR" />
      <foreColor value ="White"/>
      <backColor value ="Red, HighIntensity"/>
    </mapping>
    <mapping>
      <level value ="DEBUG"/>
      <backColor value ="Green"/>
    </mapping>
    <layout type ="log4net.Layout.PatternLayout" >
      <conversionPattern value ="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
    </layout>
  </appender>

  <!--日誌信息輸出到控制檯 高亮顯示Error信息-->
  <logger name="LogConsole" additivity="false">
    <level value="ALL" />
    <appender-ref ref="logger.ConsoleAppender" />
  </logger>
  <!--CONSOLEAPPENDER將日誌信息輸出到控制檯標準輸出流。-->
  <appender name ="logger.ConsoleAppender" type ="log4net.Appender.ConsoleAppender">
    <layout type ="log4net.Layout.PatternLayout" >
      <!--<param name ="ConversionPattern" value ="%d [%t] %-5p %c [%x] - %m%n"/>-->
      <conversionPattern value="[時間]:%d%n[級別]:%p%n[內容]:%m%n%n"></conversionPattern>
    </layout>
  </appender>

  <!--日誌寫入本地機器的應用程序事件日誌中-->
  <logger name="LogEventlog" additivity="false">
    <level value="ALL" />
    <appender-ref ref="logger.EventLogAppender" />
  </logger>
  <!--EventLogAppender將日誌寫入本地機器的應用程序事件日誌中。
  默認狀況下,該日誌的源(Source)是AppDomain.FriendlyName,也能夠手動指定其它名稱。-->
  <appender  name ="logger.EventLogAppender"  type ="log4net.Appender.EventLogAppender">
    <layout  type ="log4net.Layout.PatternLayout" >
      <param  name ="ConversionPattern"  value ="%d [%t] %-5p %c [%x] - %m%n"/>
    </layout>
  </appender>

  <!--FileAppender將日誌信息輸出到指定的日誌文件。
  File指定了文件名稱,可使用相對路徑,
  此時日誌文件的位置取決於項目的類型(如控制檯、Windows Forms、ASP.NET等);
  也可使用絕對路徑;甚至可使用環境變量,如<file value="${TMP}\log-file.txt" />。
  AppendToFile指定是追加到仍是覆蓋掉已有的日誌文件。還能夠添加以下屬性<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  來使用最小鎖定模型(minimal locking model),以容許多個進程能夠寫入同一個文件。-->
  <appender name ="LogFileAppender"  type ="log4net.Appender.FileAppender">
    <param name ="File"  value ="WebUtilClient.log"/>
    <param name ="AppendToFile"  value ="true"/>
    <layout type ="log4net.Layout.PatternLayout">
      <param name ="ConversionPattern"  value ="%d [%t] %-5p %c [%x] - %m%n"/>
    </layout>
  </appender>

  <!--ForwardingAppender能夠用來爲一個Appender指定一組約束
  在這個示例中,爲ConsoleAppender添加了約束,Threshold爲WARN。這意味着對於一條日誌信息,
  若是直接使用 ConsoleAppender,那麼不論它是什麼級別,總會進行輸出,而若是使用這個ForwardingAppender,
  則只有那些WARN或 WARN以上的日誌纔會發送到ConsoleAppender。-->
  <appender name ="ForwardingAppender" type ="log4net.Appender.ForwardingAppender">
    <threshold value ="WARN" />
    <appender-ref ref ="ConsoleAppender"/>
  </appender>

  <!--彷佛不該該使用配置文件來配置MemoryAppender,但若是你非要這麼作,看看這個示例(未驗證):-->
  <appender  name ="MemoryAppender"  type ="log4net.Appender.MemoryAppender" >
    <onlyFixPartialEventData  value ="true"   />
  </appender>

  <!--NetSendAppender向特定用戶的屏幕發送消息(未驗證)-->
  <appender name ="NetSendAppender"  type ="log4net.Appender.NetSendAppender" >
    <threshold value ="ERROR"/>
    <server value ="Anders"/>
    <recipient value ="xym"/>
    <layout type ="log4net.Layout.PatternLayout">
      <conversionPattern  value ="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
    </layout>
  </appender>

  <!--下面這個例子描述瞭如何配置該Appender以向OutputDebugString API寫入日誌(未驗證)。-->
  <appender  name ="OutputDebugStringAppender"  type ="log4net.Appender.OutputDebugStringAppender">
    <layout  type ="log4net.Layout.PatternLayout" >
      <conversionPattern  value ="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
    </layout>
  </appender>

  <!--remotingAppender向特定的Sink發送日誌信息(未驗證):-->
  <appender  name ="RemotingAppender"  type ="log4net.Appender.RemotingAppender">
    <sink  value ="tcp://localhost:8085/LoggingSink"/>
    <lossy  value ="false"/>
    <bufferSize  value ="95"/>
    <onlyFixPartialEventData  value ="true"/>
  </appender>

 
  <!--如何防止自定義的logger和root重複寫入日誌
  logger是從root繼承而來,默認的用logger寫的日誌會被root重複寫一份,
  如何防止這種狀況呢,網上有人提出能夠去掉root裏的 appender-ref,這不是一個好的解決方法,
  logger只是爲了單獨處理一些日誌,大部分的日誌仍是要依靠root來完成。
  其實log4net提供了一種很好的解決方式,斷開logger與root的繼承關係,
  只要在配置文件裏的logger加上屬性additivity="false" 就能夠了。-->

  <!--Log4Net 日誌級別
    Log4net 分爲以下幾個級別:
    FATAL  毀滅級別
    ERROR 錯誤級別
    WARN 警告級別
    INFO 消息級別
    DEBUG 調試級別
    這幾種日誌級別高低:FATAL> ERROR> WARN > INFO > DEBUG。
    只有日誌輸出級別大於或等於配置的級別才能輸出日誌信息。
    好比個人日誌配置級別爲INFO,那麼只有log.Info(), log.Warn(), log.Error(), log.Fatal()才能輸出日誌信息,Debug方式就不能輸出。
    Log4net中還有兩種特殊的配置級別: ALL - 容許全部的日誌級別輸出,OFF - 拒絕全部的日誌級別輸出。
      %m[%message]       : 輸出的日誌消息
      %n                 : 換行
      %d[%datetime]      : 輸出當前語句運行的時刻
      %r                 : 輸出程序從運行到執行到當前語句時消耗的毫秒數
      %d                 : 當前語句所在的線程ID
      %p                 : 日誌的當前優先級別
      %c                 :當前日誌對象的名稱
      %L                 : 輸出語句所在的行號
      %F                 :輸出語句所在的文件名
      %-數字              :表示該項的最小長度,若是不夠,則用空格填充
    -->
</log4net>
View Code

在項目的web.config中須要配置的項目

其中的數據庫鏈接是配置將日誌寫入到oracle數據庫中,鏈接字符串進行了加密處理。

在Global.asax文件中的配置

 

 能夠看到, LogHelper.GetInstance("/Config/Log4Net.config")是設置日誌記錄的配置文件

下面的LogHelper.WriteInfoLog是將系統啓動信息記錄到文本文件中,LogHelper.OracleInfo是將系統啓動信息記錄到數據庫中。由於啓動時是沒法獲取用戶信息的,所以傳入了null。

再給一下global.asax.cs記錄非法請求的日誌功能

        /// <summary>
        /// 在此處進行安全檢測和防範
        /// Application_BeginRequest
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Application_AcquireRequestState(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            string putData = string.Empty;
            if (Request.Cookies != null)
            {
                if (GeneralSafe.CookieData(out putData))
                {
                    ResponseWarnMessage(context, "Cookie數據有惡意字符!", putData);
                }
            }
            if (Request.UrlReferrer != null)
            {
                if (GeneralSafe.Referer(out putData))
                {
                    ResponseWarnMessage(context, "Referrer數據有惡意字符!", putData);
                }
            }
            if (Request.RequestType.ToUpper() == "POST")
            {
                if (GeneralSafe.PostData(out putData))
                {
                    ResponseWarnMessage(context, "Post數據有惡意字符!", putData);
                }
            }
            if (Request.RequestType.ToUpper() == "GET")
            {
                if (GeneralSafe.GetData(out putData))
                {
                    ResponseWarnMessage(context, "Get數據有惡意字符!", putData);
                }
            }
        }
        /// <summary>
        /// 非安全行爲 輸出警告信息
        /// </summary>
        /// <param name="errorMessage"></param>
        /// <param name="putData"></param>
        private void ResponseWarnMessage(HttpContext context, string errorMessage, string putData)
        {
            //記錄一下惡意攻擊行爲
            string ipAddress = Utilities.GetIPAddress(true);
            BaseUserInfo userInfo = context.Session[DotNet.Business.Utilities.SessionName] as BaseUserInfo;
            //非安全行爲同時記錄到數據庫和文本文件中
            LogHelper.OracleWarn(userInfo, "惡意訪問行爲", "來自IP:" + ipAddress + "的訪問存在惡意行爲:" + errorMessage + "字符內容:" + putData, " private void ResponseErrorMessage(string errorMessage, string putData)", typeof(AccountController), null);
            LogHelper.WriteSafeLog("來自IP:" + ipAddress + "的訪問存在惡意行爲:" + errorMessage + "字符內容:" + putData);
            RouteData routeData = new RouteData();
            routeData.Values.Add("controller", "Error");
            routeData.Values.Add("action", "General");
            routeData.Values.Add("title", "非法訪問與請求提醒");
            routeData.Values.Add("error", "你提交的" + errorMessage + "字符內容:" + putData);
            IController errorController = new ErrorController();
            errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
            context.Response.End();
        }

以上代碼可檢測COOKIE,Referrer,POST,GET中傳入的非法字符。頁面顯示效果截圖以下

數據庫日誌記錄的內容截圖以下:

文本文件中記錄的內容以下截圖

 

以上就是基於log4net和通用權限管理系統底層作的一個日誌記錄功能,最新版本通用權限管理系統將會使用這個日誌功能。

若有改進建議,歡迎你們提出。

相關文章
相關標籤/搜索