在项目完成初期,用户使用不可避免的会发生错误或者异常,
如何使开发人员更及时更准确地获得用户使用的情况,
会对项目质量,进度,客户满意程度产生不小的影响。
所以,我想实现这样一个功能,当程序执行中,捕获异常,
将异常信息和发生异常的位置,通过Email即时发送给开发人员。
目前实现了基本的功能,但是,存在一点问题,用户使用中,
没有理由把发送email的时间也由用户来负担。
那么通过哪种处理方式可以更合理呢?
下面是现在完成的部分,只有记录日志和发送邮件的部分..(发送邮件只做完了不需要验证的smtp部分.).
1.记录日志 如果发送邮件失败,记录未发送的异常信息.
1
2/// <summary>
3/// Record info to path
4/// </summary>
5internal class LogWriter
6{
7 structure
23
24 private string m_path = "";
25
26 /// <summary>
27 /// Record normal info
28 /// </summary>
29 /// <param name="message"></param>
30 internal void WriteInfo(string message)
31 {
32 StreamWriter msgWriter = new StreamWriter(m_path, true, System.Text.Encoding.Default);
33
34 msgWriter.WriteLine(DateTime.Now + ":" + message + "\r\n");
35
36 msgWriter.Flush();
37 msgWriter.Close();
38 msgWriter.Dispose();
39 }
40
41 /// <summary>
42 /// Record exception info
43 /// </summary>
44 /// <param name="ex"></param>
45 internal void WriteInfo(Exception ex)
46 {
47 string eString = ex.ToString();
48 WriteInfo(eString);
49 }
50
51 /// <summary>
52 /// Validate the filePath available..
53 /// </summary>
54 /// <param name="path"></param>
55 internal void ValidatePath(string path)
56 {
57 if (!File.Exists(path))
58 {
59 FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
60
61 fs.Flush();
62 fs.Close();
63 fs.Dispose();
64 }
65 }
66}
67
2/// <summary>
3/// Record info to path
4/// </summary>
5internal class LogWriter
6{
7 structure
23
24 private string m_path = "";
25
26 /// <summary>
27 /// Record normal info
28 /// </summary>
29 /// <param name="message"></param>
30 internal void WriteInfo(string message)
31 {
32 StreamWriter msgWriter = new StreamWriter(m_path, true, System.Text.Encoding.Default);
33
34 msgWriter.WriteLine(DateTime.Now + ":" + message + "\r\n");
35
36 msgWriter.Flush();
37 msgWriter.Close();
38 msgWriter.Dispose();
39 }
40
41 /// <summary>
42 /// Record exception info
43 /// </summary>
44 /// <param name="ex"></param>
45 internal void WriteInfo(Exception ex)
46 {
47 string eString = ex.ToString();
48 WriteInfo(eString);
49 }
50
51 /// <summary>
52 /// Validate the filePath available..
53 /// </summary>
54 /// <param name="path"></param>
55 internal void ValidatePath(string path)
56 {
57 if (!File.Exists(path))
58 {
59 FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
60
61 fs.Flush();
62 fs.Close();
63 fs.Dispose();
64 }
65 }
66}
67
2.通过email发送异常信息.先检查记录位置是否有未发送信息,如果有,发送.
1
2/// <summary>
3/// Class for email Exception info to developer..
4/// </summary>
5public class ExceptionMail
6{
7 structure
15
16 // Get file path from configuration
17 static readonly private string logPath = ConfigurationManager.AppSettings["logPath"];
18
19 // SmtpClient object to send email
20 private SmtpClient mailSender = new SmtpClient("smtp.?????.com", 25);
21
22 /// <summary>
23 /// Send message by email
24 /// </summary>
25 /// <param name="subject">subject of email</param>
26 /// <param name="message">content of email</param>
27 /// <returns></returns>
28 public bool SendMail(string subject, string message)
29 {
30 SendUnsettled();
31
32 AuthorizeSmtp(mailSender);
33
34 try
35 {
36 mailSender.Send("XXXXX@XXXXX.com", "XXXXX@XXXXX.com", subject + DateTime.Now.ToString(), message);
37
38 return true;
39 }
40 catch
41 {
42 LogWriter.CreateInstance(logPath).WriteInfo(message);
43
44 return false;
45 }
46 }
47
48 /// <summary>
49 /// Send exception by email
50 /// </summary>
51 /// <param name="exception">Exception that would be sent</param>
52 /// <returns></returns>
53 public bool SendException(Exception exception)
54 {
55 SendUnsettled();
56
57 AuthorizeSmtp(mailSender);
58
59 string errorInfo = "Message:" + exception.Message + "\r\n" + "Detail:" + exception.ToString();
60
61 try
62 {
63 mailSender.Send("XXXXX@XXXXX.com", "XXXXX@XXXXX.com", "Exception:" + DateTime.Now.ToString(),
64
65 errorInfo);
66
67 return true;
68 }
69 catch
70 {
71 LogWriter.CreateInstance(logPath).WriteInfo(errorInfo);
72 return false;
73 }
74 }
75
76 /// <summary>
77 /// Add credential to make sender authorized
78 /// </summary>
79 /// <param name="smtp">sender</param>
80 private void AuthorizeSmtp(SmtpClient smtp)
81 {
82 smtp.Credentials = new NetworkCredential("?????", "?????");
83
84 smtp.UseDefaultCredentials = true;
85
86 smtp.Timeout = 10000;
87
88 smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
89 }
90
91 /// <summary>
92 /// Deal with message unsettled
93 /// </summary>
94 private void SendUnsettled()
95 {
96 if (File.Exists(logPath))
97 {
98 StreamReader logReader = new StreamReader(logPath, System.Text.Encoding.Default);
99
100 string message = "";
101
102 if (logReader.Peek() >= 0)
103 {
104 message += logReader.ReadLine() + "\r\n";
105 }
106
107 SendMail("Unsettled Log", message);
108
109 logReader.Close();
110 logReader.Dispose();
111 logReader = null;
112 File.Delete(logPath);
113 }
114 }
115}
116
2/// <summary>
3/// Class for email Exception info to developer..
4/// </summary>
5public class ExceptionMail
6{
7 structure
15
16 // Get file path from configuration
17 static readonly private string logPath = ConfigurationManager.AppSettings["logPath"];
18
19 // SmtpClient object to send email
20 private SmtpClient mailSender = new SmtpClient("smtp.?????.com", 25);
21
22 /// <summary>
23 /// Send message by email
24 /// </summary>
25 /// <param name="subject">subject of email</param>
26 /// <param name="message">content of email</param>
27 /// <returns></returns>
28 public bool SendMail(string subject, string message)
29 {
30 SendUnsettled();
31
32 AuthorizeSmtp(mailSender);
33
34 try
35 {
36 mailSender.Send("XXXXX@XXXXX.com", "XXXXX@XXXXX.com", subject + DateTime.Now.ToString(), message);
37
38 return true;
39 }
40 catch
41 {
42 LogWriter.CreateInstance(logPath).WriteInfo(message);
43
44 return false;
45 }
46 }
47
48 /// <summary>
49 /// Send exception by email
50 /// </summary>
51 /// <param name="exception">Exception that would be sent</param>
52 /// <returns></returns>
53 public bool SendException(Exception exception)
54 {
55 SendUnsettled();
56
57 AuthorizeSmtp(mailSender);
58
59 string errorInfo = "Message:" + exception.Message + "\r\n" + "Detail:" + exception.ToString();
60
61 try
62 {
63 mailSender.Send("XXXXX@XXXXX.com", "XXXXX@XXXXX.com", "Exception:" + DateTime.Now.ToString(),
64
65 errorInfo);
66
67 return true;
68 }
69 catch
70 {
71 LogWriter.CreateInstance(logPath).WriteInfo(errorInfo);
72 return false;
73 }
74 }
75
76 /// <summary>
77 /// Add credential to make sender authorized
78 /// </summary>
79 /// <param name="smtp">sender</param>
80 private void AuthorizeSmtp(SmtpClient smtp)
81 {
82 smtp.Credentials = new NetworkCredential("?????", "?????");
83
84 smtp.UseDefaultCredentials = true;
85
86 smtp.Timeout = 10000;
87
88 smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
89 }
90
91 /// <summary>
92 /// Deal with message unsettled
93 /// </summary>
94 private void SendUnsettled()
95 {
96 if (File.Exists(logPath))
97 {
98 StreamReader logReader = new StreamReader(logPath, System.Text.Encoding.Default);
99
100 string message = "";
101
102 if (logReader.Peek() >= 0)
103 {
104 message += logReader.ReadLine() + "\r\n";
105 }
106
107 SendMail("Unsettled Log", message);
108
109 logReader.Close();
110 logReader.Dispose();
111 logReader = null;
112 File.Delete(logPath);
113 }
114 }
115}
116
3.暂存未发送emal的日志文件保存路径,在config文件里加入一个logPath配置项保存.
仔细想了想,可以把发送异常的方法作为独立的进程运行,这样就不会在发生异常
的时候阻塞下面的操作.