学堂 学堂 学堂公众号手机端

我心中的核心组件(可插拔的AOP)~第一回 日志记录组件之自主的Vlog

lewis 1年前 (2024-04-23) 阅读数 13 #技术

​​回到目录​​

对于.net环境而言,日志的开源组件有很多,像Nlog,log4net等等,而我今天要介绍的是我的日志组件VLog,呵呵,事实上实现原理与作用都大同小异。

作用:记录程序运行中的相关信息


特点:提供了消息日志,错误日志,调试日志,警告日志,崩溃日志等等

优势:提供了多种日志实现的方式,如SQL数据库,XML文本,WIN日志等等

配置:它可以通过配置文件进行设置,提供了日志级别和记录方式等参数

说明:VLog项目层次分明,一个接口,一个基类,5个实现的功能类,一切都是那么自然,下面看一下结构图:

一个接口:

1 namespace VLog
2 {
3 /// <summary>
4 /// 日志操作规范
5 /// </summary>
6 public interface IVLog
7 {
8 /// <summary>
9 /// 调试型日志
10 /// </summary>
11 /// <param name="msg"></param>
12 void DebugLog(string msg);
13 /// <summary>
14 /// 信息型日志
15 /// </summary>
16 /// <param name="msg"></param>
17 void InfoLog(string msg);
18 /// <summary>
19 /// 警告型日志
20 /// </summary>
21 /// <param name="msg"></param>
22 void WarnLog(string msg);
23 /// <summary>
24 /// 错误型日志
25 /// </summary>
26 /// <param name="msg"></param>
27 void ErrorLog(string msg);
28 /// <summary>
29 /// 系统崩溃型日志
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>返回 执行路径</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 /// 得到当现异常的URL
34 /// 子类可以根据自己的逻辑去复写本属性
35 /// </summary>
36 protected virtual string RequestReffer { get { return HttpContext.Current.Request.Url.AbsoluteUri; } }
37
38 /// <summary>
39 /// 得到当前异常URL的请求方式(POST,GET或HEAD)
40 /// 子类可以根据自己的逻辑去复写本属性
41 /// </summary>
42 protected virtual string HttpMethod { get { return HttpContext.Current.Request.HttpMethod; } }
43
44 /// <summary>
45 /// 写日志地址 或是 DBConnectionStr
46 /// </summary>
47 protected string Path { get; set; }
48 #endregion
49
50 #region Protected Methods
51 /// <summary>
52 /// 写日志,子类必须去实现这个方法
53 /// </summary>
54 /// <param name="text">内容</param>
55 /// <returns>返回是否成功</returns>
56 protected abstract bool Write(VLogEntity entity);
57 #endregion
58
59 #region Delegates & Events
60 /// <summary>
61 /// 日志相关委托
62 /// </summary>
63 public delegate void VLogEventHandler(object sender, VLogsEventArgs e);
64
65 /// <summary>
66 /// 添加日志事件
67 /// </summary>
68 public static event VLogEventHandler AddVLog;
69
70 /// <summary>
71 /// 触发写日志事件
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

一个生产日志的工厂:

1 namespace VLog
2 {
3 /// <summary>
4 /// 日志生产工厂
5 /// </summary>
6 public class VLogFactory
7 {
8 /// <summary>
9 /// 创建日志对象
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 /// 写日志
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); //触发写日志事件,外部订阅这个事件的对象将被执行
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

最后在配置文件里再进行设置就OK了,呵呵!

​​回到目录​​

作者:仓储大叔,张占岭,
荣誉:微软MVP



版权声明

本文仅代表作者观点,不代表博信信息网立场。

热门