对于.net环境而言,日志的开源组件有很多,像Nlog,log4net等等,而我今天要介绍的是我的日志组件VLog,呵呵,事实上实现原理与作用都大同小异。
作用:记录程序运行中的相关信息
特点:提供了消息日志,错误日志,调试日志,警告日志,崩溃日志等等
优势:提供了多种日志实现的方式,如SQL数据库,XML文本,WIN日志等等
配置:它可以通过配置文件进行设置,提供了日志级别和记录方式等参数
说明:VLog项目层次分明,一个接口,一个基类,5个实现的功能类,一切都是那么自然,下面看一下结构图:
一个接口:
1 namespace VLog 2 { 3 ///4 /// 日志操作规范 5 /// 6 public interface IVLog 7 { 8 ///9 /// 调试型日志10 /// 11 /// 12 void DebugLog(string msg);13 ///14 /// 信息型日志15 /// 16 /// 17 void InfoLog(string msg);18 ///19 /// 警告型日志20 /// 21 /// 22 void WarnLog(string msg);23 ///24 /// 错误型日志25 /// 26 /// 27 void ErrorLog(string msg);28 ///29 /// 系统崩溃型日志30 /// 31 /// 32 void FatalLog(string msg);33 }34 }
一个基类:
1 namespace VLog 2 { 3 ///4 /// VLog 基类 5 /// 6 public abstract class VLogBase : IVLog 7 { 8 #region Protected Properties 9 ///10 /// 获取执行路径 11 /// 12 ///返回 执行路径 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 ///33 /// 得到当现异常的URL 34 /// 子类可以根据自己的逻辑去复写本属性 35 /// 36 protected virtual string RequestReffer { get { return HttpContext.Current.Request.Url.AbsoluteUri; } } 37 38 ///39 /// 得到当前异常URL的请求方式(POST,GET或HEAD) 40 /// 子类可以根据自己的逻辑去复写本属性 41 /// 42 protected virtual string HttpMethod { get { return HttpContext.Current.Request.HttpMethod; } } 43 44 ///45 /// 写日志地址 或是 DBConnectionStr 46 /// 47 protected string Path { get; set; } 48 #endregion 49 50 #region Protected Methods 51 ///52 /// 写日志,子类必须去实现这个方法 53 /// 54 /// 内容 55 ///返回是否成功 56 protected abstract bool Write(VLogEntity entity); 57 #endregion 58 59 #region Delegates & Events 60 ///61 /// 日志相关委托 62 /// 63 public delegate void VLogEventHandler(object sender, VLogsEventArgs e); 64 65 ///66 /// 添加日志事件 67 /// 68 public static event VLogEventHandler AddVLog; 69 70 ///71 /// 触发写日志事件 72 /// 73 /// 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 #endregion128 129 }130 }
一个生产日志的工厂:
1 namespace VLog 2 { 3 ///4 /// 日志生产工厂 5 /// 6 public class VLogFactory 7 { 8 ///9 /// 创建日志对象10 /// 11 ///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 ///2 /// 空日志 3 /// 4 public class NullVLog : VLogBase 5 { 6 protected override bool Write(VLogEntity entity) 7 { 8 return true; 9 }10 }
1 ///2 /// SQL数据库 日志 3 /// 4 public class SqlVLog : VLogBase 5 { 6 public SqlVLog() 7 { 8 this.Path = LogCommons.GetPath(PathType.DataBase); 9 }10 11 ///12 /// 写日志13 /// 14 /// 15 ///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(@" {0}
"31 , entity.FullInfo32 );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); //触发写日志事件,外部订阅这个事件的对象将被执行57 return true;58 }59 60 61 }
1 namespace VLog 2 { 3 ///4 /// txt 日志 5 /// 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.FullInfo22 , DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")23 , entity.Level24 );25 26 File.AppendAllText(this.Path, text, Encoding.UTF8);27 28 return true;29 }30 }31 }
1 namespace VLog 2 { 3 ///4 /// windows 日志 5 /// 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.FullInfo22 , DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")23 , entity.Level24 );25 System.Diagnostics.EventLog.WriteEntry(this.Path, text, System.Diagnostics.EventLogEntryType.Error);26 return true;27 }28 }29 }
1 namespace VLog 2 { 3 ///4 /// XML 日志 5 /// 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 @"{0} 37{1} 38{2} 39{3} 40 " , base.GetSenders()41 , entity.FullInfo42 , DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")43 , entity.Level44 );45 this.xmlDocument.DocumentElement.AppendChild(ele);46 xmlDocument.Save(this.Path);47 return true;48 }49 }50 }
最后在配置文件里再进行设置就OK了,呵呵!