三天前基本上把數(shù)據(jù)庫(kù)表設(shè)計(jì)的文檔寫(xiě)好,今天想到了一個(gè)問(wèn)題,還要再加幾個(gè)表,一個(gè)是log表,用來(lái)記錄系統(tǒng)日志,另外再加幾個(gè)字典表,一些需要配置的數(shù)據(jù)但又不好放在像xml文件里面的數(shù)據(jù)可以放在這些字典表里面。
從今天開(kāi)始就正式進(jìn)入系統(tǒng)設(shè)計(jì)與編碼了,詳細(xì)設(shè)計(jì)文檔等系統(tǒng)做好后再補(bǔ)充了,因?yàn)橐婚_(kāi)始全部寫(xiě)好不大現(xiàn)實(shí),中間過(guò)程中會(huì)不斷地去迭代。現(xiàn)在的想法是每個(gè)模塊分別去實(shí)現(xiàn),然后再分別記錄下來(lái)。
今天要寫(xiě)的是日志模塊,因?yàn)樵谏a(chǎn)環(huán)境中,好的日志至于重要,系統(tǒng)運(yùn)行時(shí)出現(xiàn)的任何問(wèn)題可以通過(guò)日志記錄下來(lái),對(duì)于發(fā)現(xiàn)與解決問(wèn)題非常有幫助。因?yàn)槿罩臼且粋€(gè)相對(duì)比較通用的模塊,所以先設(shè)計(jì)好如果寫(xiě)日志模塊,之后再寫(xiě)通用類模塊,再數(shù)據(jù)庫(kù)訪問(wèn)層與用戶自定義控件,然后再數(shù)據(jù)實(shí)體與業(yè)務(wù)處理層,最后再寫(xiě)用戶表現(xiàn)層。
因?yàn)榇舜尾皇褂玫诙娇丶圆豢紤]像log4net,微軟enterPRise中好的日志控件,但是看了它們的代碼,總體思想都差不多,就是各種級(jí)別的日志信息應(yīng)該以什么樣的格式輸出到哪種介質(zhì)中,也就是輸出源,像文本文件還是數(shù)據(jù)庫(kù),還是控制臺(tái),還是系統(tǒng)日志郵件等等。基于它們的思想,把構(gòu)思記錄下來(lái):
日志最主要的就是一個(gè)日志器與附加器,像log4net中可以定義多個(gè)日志器,一個(gè)日志器可以附加多個(gè)輸出源,而日志倉(cāng)庫(kù)就是如何存儲(chǔ)和管理日志器,過(guò)慮器如果過(guò)慮各種級(jí)別的日志,而layout就是如何顯示輸出的消息。
1、輸出源只包含文本文件,數(shù)據(jù)庫(kù),系統(tǒng)日志和郵件。
2、日志級(jí)別分別為Fatal, Error, Warn, Info, Debug。
還是拿代碼為例子來(lái)講吧,首先定義一個(gè)日志器接口與日志操作接口ILog,日志器得先有一個(gè)名字,它的方法就是一個(gè)Log和IsEnabledFor,ILog包含的方法如下,用過(guò)log4net等日志控件的應(yīng)該很熟悉。
日志器接口詳細(xì)代碼如下:
public interface ILogger { /// <summary> /// Gets the name of the logger. /// </summary> string Name { get; } /// <summary> /// This generic form is intended to be used by wrappers. /// </summary> void Log(LogCategory level, object message, Exception exception); bool IsEnabledFor(LogCategory level); }然后再定義一個(gè)包裝接口
public interface ILoggerWrapper { ILogger Logger { get; } }定義ILog接口,最后調(diào)用的都是在這里定義的接口
public interface ILog : ILoggerWrapper { void Debug(object message); void Debug(object message, Exception exception); void DebugFormat(string format, params object[] args); void Info(object message); void Info(object message, Exception exception); void InfoFormat(string format, params object[] args); void Warn(object message); void Warn(object message, Exception exception); void WarnFormat(string format, params object[] args); void Error(object message); void Error(object message, Exception exception); void ErrorFormat(string format, params object[] args); void Fatal(object message); void Fatal(object message, Exception exception); void FatalFormat(string format, params object[] args); bool IsDebugEnabled { get; } bool IsInfoEnabled { get; } bool IsErrorEnabled { get; } bool IsWarnEnabled { get; } bool IsFatalEnabled { get; } }日志器有了,可以附加器呢,也就是源出源,其實(shí)真正的任務(wù)都是委托這些具體的附加器去做的呢,為什么log4net那么強(qiáng)大,我想它的附加器如此之多也是一大原因吧,基本上我們能想到的它都想到了,我們沒(méi)有想到的它也想到了,下面就定義的幾個(gè)具體的附加器。
附加器如何跟前面的說(shuō)的日志器關(guān)聯(lián)呢,20個(gè)附加器不可能都直接與日志器去關(guān)聯(lián)吧,所以定義一個(gè)所有附加器要實(shí)現(xiàn)的接口IAppender.
public interface IAppender { string Name { get; set; } void Close(); void DoAppender(LogCategory level, object message, Exception exception); }拿文本文件為例,日志的輸出源就是文本文件,消息寫(xiě)到這個(gè)介質(zhì)上,下面是一個(gè)基類,然后子類就是繼承這個(gè)類實(shí)現(xiàn)Write方法去寫(xiě)日志信息:
public class TextWriterAppender : TextWriter { private TextWriter m_writer; public TextWriter Writer { get { return m_writer; } set { m_writer = value; } } virtual public string Name { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } #region Public Methods /// <summary> /// Closes the writer and releases any system resources associated with the writer /// </summary> /// <remarks> /// <para> /// </para> /// </remarks> override public void Close() { m_writer.Close(); } /// <summary> /// Dispose this writer /// </summary> /// <param name="disposing">flag indicating if we are being disposed</param> /// <remarks> /// <para> /// Dispose this writer /// </para> /// </remarks> override protected void Dispose(bool disposing) { if (disposing) { ((IDisposable)m_writer).Dispose(); } } /// <summary> /// Flushes any buffered output /// </summary> /// <remarks> /// <para> /// Clears all buffers for the writer and causes any buffered data to be written /// to the underlying device /// </para> /// </remarks> override public void Flush() { m_writer.Flush(); } /// <summary> /// Writes a character to the wrapped TextWriter /// </summary> /// <param name="value">the value to write to the TextWriter</param> /// <remarks> /// <para> /// Writes a character to the wrapped TextWriter /// </para> /// </remarks> override public void Write(char value) { m_writer.Write(value); } /// <summary> /// Writes a character buffer to the wrapped TextWriter /// </summary> /// <param name="buffer">the data buffer</param> /// <param name="index">the start index</param> /// <param name="count">the number of characters to write</param> /// <remarks> /// <para> /// Writes a character buffer to the wrapped TextWriter /// </para> /// </remarks> override public void Write(char[] buffer, int index, int count) { m_writer.Write(buffer, index, count); } /// <summary> /// Writes a string to the wrapped TextWriter /// </summary> /// <param name="value">the value to write to the TextWriter</param> /// <remarks> /// <para> /// Writes a string to the wrapped TextWriter /// </para> /// </remarks> override public void Write(String value) { m_writer.Write(value); } public override Encoding Encoding { get { return m_writer.Encoding; } } #endregion }日志器與附加器都有了,怎么去連接它們了,最后我想還是用泛型比較靈活,定義如下:
public class LogFactory<L, A> : ILog where L : ILogger, new() where A : IAppender, new() { virtual public void Debug(object message) {#if DEBUG Logger.Log(m_levelDebug, message, null);#endif } virtual public void Debug(object message, Exception exception) {#if DEBUG Logger.Log(m_levelDebug, message, exception);#endif } virtual public void DebugFormat(string format, params object[] args) {#if DEBUG if (IsDebugEnabled) { Logger.Log(m_levelDebug, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); }#endif } virtual public void Info(object message) { Logger.Log(LevelInfo, message, null); } virtual public void Info(object message, Exception exception) { Logger.Log(LevelInfo, message, exception); } virtual public void InfoFormat(string format, params object[] args) { if (IsInfoEnabled) { Logger.Log(LevelInfo, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null); } } virtual public void Warn(object message) { Logger.Log(LevelWarn, message, null); } virtual public void Warn(object message, Exception exception) { Logger.Log(LevelWarn, message, exception); } virtual public void WarnFormat(string format, params object[] args) { if (IsWarnEnabled) { Logger.L
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注