1、CConfiguration.cs using System; using System.Collections.Specialized; using System.Xml; using System.Configuration; namespace com.lenovo.zhangyuk.logger { /// <summary> /// CConfiguration 的摘要说明。 /// </summary> public class CConfiguration { // 程序全局配置(配置文件相应内容在内存中的映射) private static NameValueCollection _configration = new NameValueCollection(); private CConfiguration() { } /// <summary> /// 取配置项 /// </summary> /// <param name="key"></param> /// <returns></returns> public static string getConfiguration( string key ) { // 如果第一次取配置项,那么将所有配置项从文件读入内存,否则从内存中取出。 if( _configration.Count==0 ) { _configration = ConfigurationSettings.AppSettings; } return (null != _configration[key]) ? _configration[key].ToString().Trim() : ""; } } }
2、ILogger.cs using System; using System.Diagnostics; namespace com.lenovo.zhangyuk.logger { /// <summary> /// 日志输出级别 /// </summary> public enum enumLevel { DEBUG, INFO, WARN, ERROR, FATAL } /// <summary> /// 日志内容,参考 myLogEntryWrittenArgs /// </summary> public class myEventLogEntry { /// <summary> /// 日志源,用以记载日志的来源 /// </summary> public string Source = ""; /// <summary> /// 日志内容 /// </summary> public string Message = ""; /// <summary> /// 写入日志的时间 /// </summary> public DateTime TimeWritten = DateTime.Now; /// <summary> /// 日志的类型,可以参考 EventLogEntryType 的定义 /// </summary> public enumLevel Type = enumLevel.INFO; } /// <summary> /// 日志外部处理函数的参数 /// </summary> public class myLogEntryWrittenArgs : EventArgs { public myLogEntryWrittenArgs() { Entry = new myEventLogEntry(); } public myEventLogEntry Entry; } /// <summary> /// 日志外部的处理入口函数声明 /// </summary> public delegate void myLogEntryWrittenHandler( object sender, myLogEntryWrittenArgs e ); /// <summary> /// /// 根据日志输出级别写日志 /// /// 特性: /// /// 1、可以根据日志输出级别写日志 /// /// 日志的输出级别:DEBUG < INFO < WARN < ERROR < FATAL /// /// 例如,日志级别是 INFO,则调用 debug() 不会输出,调用其他方法会输出; /// 日志级别是 WARN,则调用 debug() 和 info() 不会输出,调用其他方法会输出。 /// /// 2、写日志时调用外部处理入口 /// /// 可以添加外部处理入口函数(声明见 myLogEntryWrittenHandler ),在写日志时,程序 /// 依次调用外部处理入口函数,调用着可以在外部处理入口函数中得到日志的相关信息。 /// 这里使用了观察者模式。 /// /// 例如: /// private static ILogger logger = CLoggerFactory.getLogger(); /// public void logEntryWritten(object sender, myLogEntryWrittenArgs e) /// { /// //...... /// } /// logger.addEntryWrittenHander( new myLogEntryWrittenHandler(this.logEntryWritten) ); /// /// 那么在写日志的时候,logEntryWritten()会被调用。 /// /// </summary> public interface ILogger { // 写日志 void debug( string message, string source ); void info ( string message, string source ); void warn ( string message, string source ); void error( string message, string source ); void fatal( string message, string source ); // 设置和返回日志输出级别 void setLevel(enumLevel level); enumLevel getLevel(); // 管理外部程序处理入口 void addEntryWrittenHander( Delegate handler ); void clearEntryWrittenHander(); void enableEntryWrittenHander( bool enabled ); } } 3、CLoggerAbstract.cs using System; using System.IO; using System.Diagnostics; using System.Collections; namespace com.lenovo.zhangyuk.logger { /// <summary> /// 日志处理的抽象类 /// /// 这里使用了基于继承的模板模式 /// 在CLoggerAbstract中实现了向各种日志源输出的通用操作 /// 向具体日志源输出的动作则通过虚函数_writeLog在子类实现 /// </summary> abstract class CLoggerAbstract : ILogger { // 写日志时触发外部方法的HANDLE private static ArrayList _entryWrittenEventHandler = new ArrayList(); // 写日志时是否触发外部方法 private static bool _bEnableEntryWritten = true; // 日志输出级别,默认是 INFO private static enumLevel _outputLevel = enumLevel.INFO; // 抽象函数,具体的写日志操作由子类实现 public abstract void _writeLog(string message, string source, enumLevel type); /// <summary> /// 构造函数 /// </summary> /// <param name="strEventSource"></param> /// <param name="strEventLog"></param> public CLoggerAbstract( enumLevel level ) { _outputLevel = level; } /// <summary> /// 设置日志输出级别 /// </summary> /// <param name="level">级别</param> public void setLevel(enumLevel level) { _outputLevel = level; } /// <summary> /// 获得日志输出级别 /// </summary> /// <returns>级别</returns> public enumLevel getLevel() { return _outputLevel; } /// <summary> /// 写调试信息 /// </summary> /// <param name="message"></param> public void debug( string message, string source ) { if( _outputLevel <= enumLevel.DEBUG ) write( message, source, enumLevel.DEBUG ); } /// <summary> /// 写一般信息 /// </summary> /// <param name="message"></param> public void info( string message, string source ) { if( _outputLevel <= enumLevel.INFO ) write( message, source, enumLevel.INFO ); } /// <summary> /// 写警告信息 /// </summary> /// <param name="message"></param> public void warn( string message, string source ) { if( _outputLevel <= enumLevel.WARN ) write( message, source, enumLevel.WARN ); } /// <summary> /// 写错误信息 /// </summary> /// <param name="message"></param> public void error( string message, string source ) { if( _outputLevel <= enumLevel.ERROR ) write( message, source, enumLevel.ERROR ); } /// <summary> /// 写严重错误信息 /// </summary> /// <param name="message"></param> public void fatal( string message, string source ) { if( _outputLevel <= enumLevel.FATAL ) write( message, source, enumLevel.FATAL ); } /// <summary> /// 设置写日志时触发的外部方法 /// </summary> /// <param name="handler">外部方法HANDLE</param> public void addEntryWrittenHander( Delegate handler ) { try { if( !_entryWrittenEventHandler.Contains(handler) ) _entryWrittenEventHandler.Add( handler ); } catch( Exception ex ) { this.warn("add entry written hander error:"+ex.Message, this.ToString()); } } /// <summary> /// 清除写日志时触发的外部方法 /// </summary> public void clearEntryWrittenHander() { try { _entryWrittenEventHandler.Clear(); } catch( Exception ex ) { this.warn("clear entry written hander error:"+ex.Message, this.ToString()); } } /// <summary> /// 设置是否在写日志时触发的外部方法,默认为TRUE。 /// </summary> /// <param name="enabled">是否</param> public void enableEntryWrittenHander( bool enabled ) { _bEnableEntryWritten = enabled; } /// <summary> /// 将控制转给外部处理方法 /// </summary> /// <param name="source"></param> /// <param name="e"></param> private void OnEntryWritten( string message, string source, enumLevel type)//object source, EntryWrittenEventArgs e) { if( _entryWrittenEventHandler.Count >0 ) { myLogEntryWrittenArgs args = new myLogEntryWrittenArgs(); args.Entry.TimeWritten = DateTime.Now; args.Entry.Message = message; args.Entry.Type = type; args.Entry.Source = source; foreach( myLogEntryWrittenHandler aHandler in _entryWrittenEventHandler ) { aHandler( this, args ); } } } /// <summary> /// 写事件日志 /// </summary> /// <param name="strMessage">事件内容</param> /// <param name="eventType">事件类别,错误、警告或者消息</param> private void write( string message, string source, enumLevel type ) { try { _writeLog( message, source, type ); OnEntryWritten( message, source, type ); } catch( Exception ex ) { Trace.WriteLine("Write logger error:" + ex.Message); } } } }
4、CLoggerDatabase.cs using System; using System.IO; using System.Diagnostics; using System.Data; using System.Data.OleDb; namespace com.lenovo.zhangyuk.logger { /// <summary> /// 向数据库写日志 /// </summary> class CLoggerDatabase : CLoggerAbstract { // 数据库连接 private static OleDbConnection _connection = null; // 向数据库写日志的带参数的SQL串,通常是一条带参数的INSERT语句 private static string _updateStr = ""; /// <summary> /// 构造函数 /// </summary> /// <param name="strUpdate">向数据库写日志的带参数的SQL串,通常是一条带参数的INSERT语句</param> /// <param name="level">日志输出的级别</param> public CLoggerDatabase( string strUpdate, enumLevel level ) : base(level) { if( null == _connection ) { _connection = new OleDbConnection(CConfiguration.getConfiguration("database.connectionString")); } Trace.WriteLineIf( ( strUpdate.Length <=0 ), "error : update string is empty !" ); _updateStr = strUpdate; } /// <summary> /// 向数据库写日志 /// override抽象类的相应函数 /// </summary> /// <param name="message">日志内容</param> /// <param name="source">日志源</param> /// <param name="type">日志级别</param> public override void _writeLog(string message, string source, enumLevel type) { try { OleDbCommand command = new OleDbCommand(); command.Connection = _connection; command.CommandText = string.Format(_updateStr, DateTime.Now.ToLocalTime(), message, source, type.ToString()); command.CommandType = CommandType.Text; _connection.Open(); command.ExecuteNonQuery(); _connection.Close(); } catch( Exception ex ) { _connection.Close(); throw ex; } } } } 5、CLoggerFile.cs using System; using System.IO; using System.Diagnostics; namespace com.lenovo.zhangyuk.logger { /// <summary> /// 向文件写日志 /// </summary> class CLoggerFile : CLoggerAbstract { // 文件句柄 private static Stream _fileStream = null; /// <summary> /// 构造函数 /// </summary> /// <param name="strFileName">日志文件名</param> /// <param name="level">日志输出的级别</param> public CLoggerFile( string strFileName, enumLevel level ) : base(level) { Trace.WriteLineIf( ( strFileName.Length <=0 ), "error : logger file name is empty !" ); if( null == _fileStream ) { _fileStream = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Write ); } } /// <summary> /// 向文件写日志 /// override抽象类的相应函数 /// </summary> /// <param name="message">日志内容</param> /// <param name="source">日志源</param> /// <param name="type">日志级别</param> public override void _writeLog(string message, string source, enumLevel type) { try { _fileStream.Seek(0,SeekOrigin.End); StreamWriter sw = new StreamWriter(_fileStream); sw.WriteLine( DateTime.Now.ToString() + " " + type.ToString() + " " + source + " " + message); sw.Flush(); } catch( Exception ex ) { throw ex; } } } } 6、CLoggerEvent.cs using System; using System.Diagnostics; namespace com.lenovo.zhangyuk.logger { /// <summary> /// 向系统写入日志 /// </summary> class CLoggerEvent : CLoggerAbstract { // 事件日志 private static EventLog _eventLog = new EventLog(); // 事件日志名 private static string _eventName = "com.lenovo.zhangyu"; /// <summary> /// 构造函数 /// </summary> /// <param name="strEventName">事件日志名</param> /// <param name="level">日志输出的级别</param> public CLoggerEvent( string strEventName, enumLevel level ) : base(level) { _eventName = strEventName; _eventLog.Log = _eventName; _eventLog.EnableRaisingEvents = false; } /// <summary> /// 向系统写入日志 /// override抽象类的相应函数 /// </summary> /// <param name="message">日志内容</param> /// <param name="source">日志源</param> /// <param name="type">日志级别</param> public override void _writeLog(string message, string source, enumLevel type) { try { if (!EventLog.SourceExists( source )) { EventLog.CreateEventSource( source,_eventName ); } _eventLog.Source = source; _eventLog.WriteEntry( message, myType2EventType( type ) ); } catch( Exception ex ) { throw ex; } } /// <summary> /// 将自定义的日志级别转换为系统约定的日志级别 /// DEBUG INFO --> Information /// ERROR FATAL --> Error /// WARN --> Warning /// </summary> /// <param name="type">自定义的日志级别</param> /// <returns>系统约定的日志级别</returns> private EventLogEntryType myType2EventType( enumLevel type ) { EventLogEntryType eventType = EventLogEntryType.Information; if( type == enumLevel.DEBUG || type == enumLevel.INFO ) eventType = EventLogEntryType.Information; else if( type == enumLevel.ERROR || type == enumLevel.FATAL ) eventType = EventLogEntryType.Error; else if( type == enumLevel.WARN ) eventType = EventLogEntryType.Warning; return eventType; } } } 7、CLoggerFactory.cs using System; using System.Collections; using System.Reflection; namespace com.lenovo.zhangyuk.logger { /// <summary> /// CLoggerFactory 的摘要说明。 /// </summary> public class CLoggerFactory { private CLoggerFactory() { } /// <summary> /// 根据配置文件中的设置创建日志类 /// </summary> /// <returns></returns> public static ILogger getLogger() { // 日志类型 string logger = CConfiguration.getConfiguration("logger.type"); // 日志名或日志文件名 string loggerName = CConfiguration.getConfiguration("logger.name"); // 日志级别 enumLevel level = str2enum( CConfiguration.getConfiguration("logger.level") ); // 创建日志类 if( logger.ToLower().Equals("file") ) // 文件日志 { return new CLoggerFile( loggerName, level ); } else if( logger.ToLower().Equals("database") ) // 数据库日志 { return new CLoggerDatabase( loggerName, level ); } else// if( logger.ToLower().Equals("system") ) // 缺省使用系统日志 { return new CLoggerEvent( loggerName, level ); } } /// <summary> /// 将string类型的日志输出级别转换成程序可识别的enum型 /// </summary> /// <param name="strLevel">string类型的日志输出级别</param> /// <returns>enumLevel类型的日志输出级别</returns> private static enumLevel str2enum( string strLevel ) { enumLevel level = 0; if( strLevel.ToLower().Equals("debug") ) level = enumLevel.DEBUG; else if( strLevel.ToLower().Equals("info") ) level = enumLevel.INFO; else if( strLevel.ToLower().Equals("warn") ) level = enumLevel.WARN; else if( strLevel.ToLower().Equals("error") ) level = enumLevel.ERROR; else if( strLevel.ToLower().Equals("fatal") ) level = enumLevel.FATAL; else level = enumLevel.INFO; return level; } } } 8、 <?xml version="1.0" encoding="gb2312"?> <configuration> <appSettings> <add key="database.connectionString" value="Provider=OraOLEDB.Oracle.1;Password=zy;User ID=zy;Data Source=mytest" /> <add key="logger.type" value="file" /> <add key="logger.level" value="debug" /> <add key="logger.name" value="c:\\mylog.txt"/> </appSettings> </configuration> 作者简介:张昱([email protected]) 
|