我心中的核心組(zu)件(可插拔的AOP)~第一回 日志記錄組(zu)件之自主的Vlog
對于.net環境而(er)言,日(ri)志(zhi)的開源(yuan)組件(jian)有很(hen)多,像Nlog,log4net等等,而(er)我今(jin)天要介紹的是我的日(ri)志(zhi)組件(jian)VLog,呵呵,事實(shi)上實(shi)現(xian)原(yuan)理與(yu)作用都大同小(xiao)異。
作(zuo)用:記錄程(cheng)序(xu)運行(xing)中(zhong)的相關信息(xi)
特點:提(ti)供(gong)了消息日(ri)(ri)志,錯誤日(ri)(ri)志,調(diao)試日(ri)(ri)志,警(jing)告日(ri)(ri)志,崩潰日(ri)(ri)志等(deng)等(deng)
優(you)勢(shi):提供(gong)了多種(zhong)日(ri)志實(shi)現的方式(shi),如SQL數據庫,XML文(wen)本,WIN日(ri)志等等
配置:它可以通(tong)過(guo)配置文(wen)件進行設置,提供了日(ri)志級別和記錄方式等(deng)參數
說明(ming):VLog項目層(ceng)次分明(ming),一(yi)個接口,一(yi)個基類,5個實現(xian)的功(gong)能類,一(yi)切(qie)都是那(nei)么自然,下面(mian)看一(yi)下結構圖:
一個接口:
1 namespace VLog 2 { 3 /// <summary> 4 /// 日志操作規范 5 /// </summary> 6 public interface IVLog 7 { 8 /// <summary> 9 /// 調(diao)試(shi)型日志 10 /// </summary> 11 /// <param name="msg"></param> 12 void DebugLog(string msg); 13 /// <summary> 14 /// 信息(xi)型日志 15 /// </summary> 16 /// <param name="msg"></param> 17 void InfoLog(string msg); 18 /// <summary> 19 /// 警告型日(ri)志(zhi) 20 /// </summary> 21 /// <param name="msg"></param> 22 void WarnLog(string msg); 23 /// <summary> 24 /// 錯誤(wu)型日志 25 /// </summary> 26 /// <param name="msg"></param> 27 void ErrorLog(string msg); 28 /// <summary> 29 /// 系統崩潰型(xing)日志(zhi) 30 /// </summary> 31 /// <param name="msg"></param> 32 void FatalLog(string msg); 33 } 34 }
一個基類:
1 namespace VLog 2 { 3 /// <summary> 4 /// VLog 基類 5 /// </summary> 6 public abstract class VLogBase : IVLog 7 { 8 #region Protected Properties 9 /// <summary> 10 /// 獲取執行路徑 11 /// </summary> 12 /// <returns>返回 執行(xing)路(lu)徑</returns> 13 protected string GetSenders() 14 { 15 StringBuilder sb = new StringBuilder(); 16 StackFrame[] frames = new StackTrace(true).GetFrames(); 17 for (int index = 2; index < frames.Length; index++) 18 { 19 if (frames[index].GetMethod().ReflectedType == null) 20 { 21 sb.AppendFormat("[systemfuntion:{0}]->", frames[index].GetMethod().Name); 22 } 23 else 24 { 25 sb.AppendFormat("[{0}]->", frames[index].GetMethod().ReflectedType.Name); 26 } 27 } 28 //return sb.ToString(0, sb.Length - 2); 29 return string.Empty; 30 } 31 32 /// <summary> 33 /// 得到(dao)當現異常的URL 34 /// 子類可以根據自己(ji)的邏輯去(qu)復寫本屬性(xing) 35 /// </summary> 36 protected virtual string RequestReffer { get { return HttpContext.Current.Request.Url.AbsoluteUri; } } 37 38 /// <summary> 39 /// 得到當前異常URL的請求方式(shi)(POST,GET或HEAD) 40 /// 子類可以根據自己的邏輯去復(fu)寫本屬性 41 /// </summary> 42 protected virtual string HttpMethod { get { return HttpContext.Current.Request.HttpMethod; } } 43 44 /// <summary> 45 /// 寫日志(zhi)地址 或是 DBConnectionStr 46 /// </summary> 47 protected string Path { get; set; } 48 #endregion 49 50 #region Protected Methods 51 /// <summary> 52 /// 寫日(ri)志,子類必須去實現這個方法 53 /// </summary> 54 /// <param name="text">內(nei)容(rong)</param> 55 /// <returns>返回是否成功(gong)</returns> 56 protected abstract bool Write(VLogEntity entity); 57 #endregion 58 59 #region Delegates & Events 60 /// <summary> 61 /// 日志相關委托(tuo) 62 /// </summary> 63 public delegate void VLogEventHandler(object sender, VLogsEventArgs e); 64 65 /// <summary> 66 /// 添(tian)加日志事(shi)件 67 /// </summary> 68 public static event VLogEventHandler AddVLog; 69 70 /// <summary> 71 /// 觸(chu)發寫(xie)日志事件(jian) 72 /// </summary> 73 /// <param name="entity"></param> 74 public void OnAddVLog(VLogEntity entity) 75 { 76 try 77 { 78 if (AddVLog != null) 79 { 80 AddVLog(this, new VLogsEventArgs(entity)); 81 } 82 } 83 catch (Exception) 84 { 85 throw; 86 } 87 } 88 #endregion 89 90 #region Private Fields 91 static int configLevel = Convert.ToInt32(ConfigurationManager.AppSettings["VLogLevel"]); 92 93 #endregion 94 95 #region IVLog 成員 96 97 public virtual void DebugLog(string msg) 98 { 99 if (configLevel >= (int)VLog.VLogLevel.Debug) 100 this.Write(new VLogEntity { ExceptionID = Guid.NewGuid().ToString(), FullInfo = msg, Level = VLogLevel.Debug }); 101 } 102 103 public virtual void InfoLog(string msg) 104 { 105 if (configLevel >= (int)VLog.VLogLevel.Info) 106 this.Write(new VLogEntity { ExceptionID = Guid.NewGuid().ToString(), FullInfo = msg, Level = VLogLevel.Info }); 107 } 108 109 public virtual void WarnLog(string msg) 110 { 111 if (configLevel >= (int)VLog.VLogLevel.Warn) 112 this.Write(new VLogEntity { ExceptionID = Guid.NewGuid().ToString(), FullInfo = msg, Level = VLogLevel.Warn }); 113 } 114 115 public virtual void ErrorLog(string msg) 116 { 117 if (configLevel >= (int)VLog.VLogLevel.Error) 118 this.Write(new VLogEntity { ExceptionID = Guid.NewGuid().ToString(), FullInfo = msg, Level = VLogLevel.Error }); 119 } 120 121 public void FatalLog(string msg) 122 { 123 if (configLevel >= (int)VLog.VLogLevel.Fatal) 124 this.Write(new VLogEntity { ExceptionID = Guid.NewGuid().ToString(), FullInfo = msg, Level = VLogLevel.Fatal }); 125 } 126 127 #endregion 128 129 } 130 }
一(yi)個生產(chan)日志的工廠:
1 namespace VLog 2 { 3 /// <summary> 4 /// 日志生(sheng)產工廠 5 /// </summary> 6 public class VLogFactory 7 { 8 /// <summary> 9 /// 創建(jian)日志對象 10 /// </summary> 11 /// <returns></returns> 12 public static VLogBase CreateVLog() 13 { 14 if (ConfigurationManager.AppSettings["VLog"] == null) 15 return new VLog.NullVLog(); 16 return (VLogBase)System.Reflection.Assembly.Load("VLog").CreateInstance("VLog." 17 + ConfigurationManager.AppSettings["VLog"]); 18 } 19 } 20 }
五種實現日志的對象
1 /// <summary> 2 /// 空日志 3 /// </summary> 4 public class NullVLog : VLogBase 5 { 6 protected override bool Write(VLogEntity entity) 7 { 8 return true; 9 } 10 }
1 /// <summary> 2 /// SQL數據庫 日志 3 /// </summary> 4 public class SqlVLog : VLogBase 5 { 6 public SqlVLog() 7 { 8 this.Path = LogCommons.GetPath(PathType.DataBase); 9 } 10 11 /// <summary> 12 /// 寫(xie)日志 13 /// </summary> 14 /// <param name="text"></param> 15 /// <returns></returns> 16 protected override bool Write(VLogEntity entity) 17 { 18 19 using (SqlConnection sqlconn = new SqlConnection(this.Path)) 20 { 21 using (SqlCommand sqlcomm = new SqlCommand( 22 "INSERT INTO [Web_ExceptionLog]([ExceptionID],[FullInfo],[Senders],[OccurTime],[HttpMethod],[Level]) VALUES (@ExceptionID,@FullInfo,@Senders,@OccurTime,@HttpMethod,@Level);" 23 , sqlconn)) 24 { 25 SqlParameter parameter = new SqlParameter("@ExceptionID", SqlDbType.VarChar, 36); 26 parameter.Value = entity.ExceptionID; 27 sqlcomm.Parameters.Add(parameter); 28 29 parameter = new SqlParameter("@FullInfo", SqlDbType.NText); 30 parameter.Value = string.Format(@"<p>{0}</p>" 31 , entity.FullInfo 32 ); 33 sqlcomm.Parameters.Add(parameter); 34 35 parameter = new SqlParameter("@OccurTime", SqlDbType.DateTime, 4); 36 parameter.Value = DateTime.Now; 37 sqlcomm.Parameters.Add(parameter); 38 39 parameter = new SqlParameter("@Senders", SqlDbType.VarChar, 2000); 40 parameter.Value = base.RequestReffer; 41 sqlcomm.Parameters.Add(parameter); 42 43 parameter = new SqlParameter("@HttpMethod", SqlDbType.VarChar, 50); 44 parameter.Value = base.HttpMethod; 45 sqlcomm.Parameters.Add(parameter); 46 47 parameter = new SqlParameter("@Level", SqlDbType.Int); 48 parameter.Value = entity.Level; 49 sqlcomm.Parameters.Add(parameter); 50 51 sqlconn.Open(); 52 sqlcomm.ExecuteNonQuery(); 53 sqlconn.Close(); 54 } 55 } 56 OnAddVLog(entity); //觸發寫日志事件,外部訂閱這(zhe)個事件的對象將被執行 57 return true; 58 } 59 60 61 }
1 namespace VLog 2 { 3 /// <summary> 4 /// txt 日志 5 /// </summary> 6 public class TxtVLog : VLogBase 7 { 8 public TxtVLog() 9 { 10 this.Path = LogCommons.GetPath(PathType.Txt); 11 } 12 13 protected override bool Write(VLogEntity entity) 14 { 15 string text = string.Format(@" 16 Senders: {0} 17 Content: {1} 18 Date: {2} 19 Level: {3} 20 ", base.GetSenders() 21 , entity.FullInfo 22 , DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff") 23 , entity.Level 24 ); 25 26 File.AppendAllText(this.Path, text, Encoding.UTF8); 27 28 return true; 29 } 30 } 31 }
1 namespace VLog 2 { 3 /// <summary> 4 /// windows 日志 5 /// </summary> 6 public class WindowsEventVLog : VLogBase 7 { 8 public WindowsEventVLog() 9 { 10 this.Path = LogCommons.GetPath(PathType.WindowsEvent); 11 } 12 13 protected override bool Write(VLogEntity entity) 14 { 15 string text = string.Format(@" 16 Senders: {0} 17 Content: {1} 18 Date: {2} 19 Level: {3} 20 ", base.GetSenders() 21 , entity.FullInfo 22 , DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff") 23 , entity.Level 24 ); 25 System.Diagnostics.EventLog.WriteEntry(this.Path, text, System.Diagnostics.EventLogEntryType.Error); 26 return true; 27 } 28 } 29 }
1 namespace VLog 2 { 3 /// <summary> 4 /// XML 日志 5 /// </summary> 6 public class XmlVLog : VLogBase 7 { 8 9 public XmlDocument xmlDocument = null; 10 11 public XmlVLog() 12 { 13 this.Path = LogCommons.GetPath(PathType.Xml); 14 if (!File.Exists(this.Path)) 15 { 16 ReCreate(this.Path); 17 } 18 this.xmlDocument = new XmlDocument(); 19 this.xmlDocument.Load(this.Path); 20 } 21 22 static void ReCreate(string path) 23 { 24 XmlDocument xmlDocument = new XmlDocument(); 25 XmlDeclaration xmldecl = xmlDocument.CreateXmlDeclaration("1.0", "utf-8", null); 26 xmlDocument.AppendChild(xmldecl); 27 XmlElement ele = xmlDocument.CreateElement("root"); 28 xmlDocument.AppendChild(ele); 29 xmlDocument.Save(path); 30 } 31 32 protected override bool Write(VLogEntity entity) 33 { 34 XmlElement ele = this.xmlDocument.CreateElement("item"); 35 ele.InnerXml = string.Format( 36 @"<Senders>{0}</Senders> 37 <Content>{1}</Content> 38 <Date>{2}</Date> 39 <Level>{3}</Level> 40 " , base.GetSenders() 41 , entity.FullInfo 42 , DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff") 43 , entity.Level 44 ); 45 this.xmlDocument.DocumentElement.AppendChild(ele); 46 xmlDocument.Save(this.Path); 47 return true; 48 } 49 } 50 }
最后在配置文件里再進行設置就(jiu)OK了,呵呵!