天天看点

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