开发人员都知道,在系统运行中要记录各种日志,自己写一个日志功能,无论是在效率还是功能扩展上来说都不是很好,目前大多用的是第三方的日志系统,其中一个非常有名,用的最多的就是log4net。下面是关于这个组件的介绍
”Log4net是基于.net开发的一款非常著名的记录日志开源组件。最早是2001年7月由NeoWorks Limited启动的项目,基本的框架源, 于另外的一个非常著名的姐妹组件-log4j。现由Apache组织开发与维护。此日志架构是可灵活扩展,且通过配置文件来设置日志的属性及输出,不同修 改代码即可实现程序的灵活跟踪。可以将日志分不同的等级,通过不同的过滤条件,以不同的样式,将日志输出到不同的媒介。可以从http://logging.apache.org/log4net/l网站下载最新版本的Log4net源码。“
目前的log4net的最新版本是1.2.13.0
下面介绍下如何在通用权限管理系统的项目中使用这个组件实现将日志输出到文件和Oracle数据库中,重点介绍下日志输出到数据库中。
首先在官网下载最新源码,目前的源码可用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; } } }