天天看點

C# 簡易異步日志類 [ C# | Log | TextWriterTraceListener ]

前言

  即使是小型項目,也需要日志的功能,這裡就不讨論log4net之類的架構,提供一個異步的、控制台輸出+日志檔案輸出的簡易日志幫助類。

正文

  一、幫助類檔案logger.cs

C# 簡易異步日志類 [ C# | Log | TextWriterTraceListener ]

//=========================================

//

// 作 者:農民伯伯

// 郵 箱:[email protected]

// 博 客:http://over140.cnblogs.com/

// 時 間:2009-7-16

// 描 述:日志類,注意需要在日志記錄的目錄給使用者寫入權限!

using system;

using system.configuration;

using system.collections.generic;

using system.data.sqlclient;

using system.diagnostics;

using system.io;

using system.text;

using system.runtime.compilerservices;

using system.web;

namespace centralhousestest

{

    /// <summary>

    /// 日志類

    /// </summary>

    public sealed class logger

    {

        #region member variables

        /// <summary>

        /// 用于trace的組織輸出的類别名稱

        /// </summary>

        private const string trace_sql = "\r\n***********************trace_sql {0}*****************************\r\ntrace_sql";

        private const string trace_exception = "\r\n***********************trace_exception {0}***********************";

        /// 目前日志的日期

        private static datetime currentlogfiledate = datetime.now;

        /// 日志對象

        private static textwritertracelistener twtl;

        /// 日志根目錄

        private const string log_root_directory = @"d:\log";

        /// 日志子目錄

        private static string log_subdir;

        /// "      {0} = {1}"

        private const string format_trace_param = "      {0} = {1}";

        /// 1   僅控制台輸出

        /// 2   僅日志輸出

        /// 3   控制台+日志輸出

        private static readonly int flag = 2;         //可以修改成從配置檔案讀取

        #endregion

        #region constructor

        static logger()

        {

            system.diagnostics.trace.autoflush = true;

            switch (flag)

            {

                case 1:

                    system.diagnostics.trace.listeners.add(new consoletracelistener());

                    break;

                case 2:

                    system.diagnostics.trace.listeners.add(twtl);

                case 3:

            }

        }

        #region method

        #region trace

        /// 異步錯誤日志

        /// <param name="value"></param>

        public static void trace(exception ex)

            new asynclogexception(begintraceerror).begininvoke(ex, null, null);

        /// 異步sql日志

        /// <param name="cmd"></param>

        public static void trace(sqlcommand cmd)

            new asynclogsqlcommand(begintracesqlcommand).begininvoke(cmd, null, null);

        /// <param name="sql"></param>

        /// <param name="parameter"></param>

        public static void trace(string sql, params sqlparameter[] parameter)

            new asynclogsql(begintracesql).begininvoke(sql, parameter, null, null);

        #region delegate

        private delegate void asynclogexception(exception ex);

        private delegate void asynclogsqlcommand(sqlcommand cmd);

        private delegate void asynclogsql(string sql, params sqlparameter[] parameter);

        private static void begintraceerror(exception ex)

            if (null != ex)

                //檢測日志日期

                strategylog();

                //輸出日志頭

                system.diagnostics.trace.writeline(string.format(trace_exception, datetime.now));

                while (null != ex)

                {

                    system.diagnostics.trace.writeline(string.format("{0} {1}\r\n{2}\r\nsource:{3}", ex.gettype().name, ex.message, ex.stacktrace, ex.source));

                    ex = ex.innerexception;

                }

        private static void begintracesqlcommand(sqlcommand cmd)

            if (null != cmd)

                sqlparameter[] parameter = new sqlparameter[cmd.parameters.count];

                cmd.parameters.copyto(parameter, 0);

                begintracesql(cmd.commandtext, parameter);

        private static void begintracesql(string sql, params sqlparameter[] parameter)

            if (!string.isnullorempty(sql))

                system.diagnostics.trace.writeline(sql, string.format(trace_sql, datetime.now));

                if (parameter != null)

                    foreach (sqlparameter param in parameter)

                    {

                        system.diagnostics.trace.writeline(string.format(format_trace_param, param.parametername, param.value));

                    }

        #region helper

        /// 根據日志政策生成日志

        private static void strategylog()

            //判斷日志日期

            if (datetime.compare(datetime.now.date, currentlogfiledate.date) != 0)

                datetime currentdate = datetime.now.date;

                //生成子目錄

                buiderdir(currentdate);

                //更新目前日志日期

                currentlogfiledate = currentdate;

                system.diagnostics.trace.flush();

                //更改輸出

                if (twtl != null)

                    system.diagnostics.trace.listeners.remove(twtl);

                system.diagnostics.trace.listeners.add(twtl);

        /// 根據年月生成子目錄

        /// <param name="currentdate"></param>

        private static void buiderdir(datetime currentdate)

            int year = currentdate.year;

            int month = currentdate.month;

            //年/月

            string subdir = string.concat(year, '\\', month);

            string path = path.combine(log_root_directory, subdir);

            if (!directory.exists(path))

                directory.createdirectory(path);

            log_subdir = subdir;

        #region properties

        /// 日志檔案路徑

        /// <returns></returns>

        private static string getlogfullpath

            get

                return string.concat(log_root_directory, '\\', string.concat(log_subdir, @"\log", currentlogfiledate.toshortdatestring(), ".txt"));

        /// 跟蹤輸出日志檔案

        private static textwritertracelistener twtl

                if (twtl == null)

                    if (string.isnullorempty(log_subdir))

                        buiderdir(datetime.now);

                    else

                        string logpath = getlogfullpath;

                        if (!directory.exists(path.getdirectoryname(logpath)))

                            buiderdir(datetime.now);

                    twtl = new textwritertracelistener(getlogfullpath);

                return twtl;

    }

}

C# 簡易異步日志類 [ C# | Log | TextWriterTraceListener ]

  二、示例

    2.1  錯誤記錄

C# 簡易異步日志類 [ C# | Log | TextWriterTraceListener ]

        static void main(string[] args)

            ilist<string> list = null;

            try

                console.writeline(list.count);

            catch (exception ex)

                logger.trace(ex);

            console.readline();

C# 簡易異步日志類 [ C# | Log | TextWriterTraceListener ]

      代碼說明:錯誤很明顯,未執行個體化就使用count屬性。

      日志截圖:

      

C# 簡易異步日志類 [ C# | Log | TextWriterTraceListener ]

    2.2  資料庫記錄

C# 簡易異步日志類 [ C# | Log | TextWriterTraceListener ]

            using (sqlconnection con = new sqlconnection("data source=overa;initial catalog=northwind;user id=sa;password=sa;"))

                con.open();

                sqlcommand sqlcmd = new sqlcommand("select * from customers where companyname = @companyname", con);

                sqlcmd.parameters.add(new sqlparameter("@companyname", "alfreds futterkiste"));

                logger.trace(sqlcmd);

                sqldatareader sdr = sqlcmd.executereader();

                while (sdr.read())

                    console.write(sdr.getname(1));

                    console.write(" : ");

                    console.writeline( sdr[1]); 

                sdr.close();

C# 簡易異步日志類 [ C# | Log | TextWriterTraceListener ]
C# 簡易異步日志類 [ C# | Log | TextWriterTraceListener ]

       需要注意這裡日志政策改為了僅日志檔案輸出。

  三、注意事項

    3.1  進行日志檔案輸出的時候需要有寫的權限。

    3.2  實際使用中可能還會有一個變量控制是否進行日志記錄。

    3.3  錯誤記錄一般會在global.asax的application_error裡面加上。

結束語  

  對于一般的小項目這個日志類是夠用的了,日志的政策還可以根據自己的需求改變一下,合适就行: )  

轉載:http://www.cnblogs.com/over140/archive/2009/07/16/1524735.html