C# 简易异步日志类 [ C# | Log | TextWriterTraceListener ]


前言

  即使是小型项目,也需要日志的功能,这里就不讨论Log4Net之类的框架,提供一个异步的、控制台输出+日志文件输出的简易日志帮助类。

正文

  一、帮助类文件Logger.cs

//=========================================
//
// 作 者:农民伯伯
// 邮 箱:over140@gmail.com
// 博 客: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";

        
/// <summary>
        
/// 用于Trace的组织输出的类别名称
        
/// </summary>
        private const string trace_exception = "\r\n***********************TRACE_EXCEPTION {0}***********************";

        
/// <summary>
        
/// 当前日志的日期
        
/// </summary>
        private static DateTime CurrentLogFileDate = DateTime.Now;

        
/// <summary>
        
/// 日志对象
        
/// </summary>
        private static TextWriterTraceListener twtl;

        
/// <summary>
        
/// 日志根目录
        
/// </summary>
        private const string log_root_directory = @"D:\log";

        
/// <summary>
        
/// 日志子目录
        
/// </summary>
        private static string log_subdir;


        
/// <summary>
        
/// "      {0} = {1}"
        
/// </summary>
        private const string FORMAT_TRACE_PARAM = "      {0} = {1}";

        
/// <summary>
        
/// 1   仅控制台输出
        
/// 2   仅日志输出
        
/// 3   控制台+日志输出
        
/// </summary>
        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);
                    
break;
                
case 3:
                    System.Diagnostics.Trace.Listeners.Add(
new ConsoleTraceListener());
                    System.Diagnostics.Trace.Listeners.Add(TWTL);
                    
break;
            }
        }

        
#endregion

        
#region Method

        
#region trace

        
/// <summary>
        
/// 异步错误日志
        
/// </summary>
        
/// <param name="value"></param>
        public static void Trace(Exception ex)
        {
            
new AsyncLogException(BeginTraceError).BeginInvoke(ex, nullnull);
        }

        
/// <summary>
        
/// 异步SQL日志
        
/// </summary>
        
/// <param name="cmd"></param>
        public static void Trace(SqlCommand cmd)
        {
            
new AsyncLogSqlCommand(BeginTraceSqlCommand).BeginInvoke(cmd, nullnull);
        }

        
/// <summary>
        
/// 异步SQL日志
        
/// </summary>
        
/// <param name="sql"></param>
        
/// <param name="parameter"></param>
        public static void Trace(string sql, params SqlParameter[] parameter)
        {
            
new AsyncLogSql(BeginTraceSql).BeginInvoke(sql, parameter, nullnull);
        }

        
#endregion

        
#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))
            {
                
//检测日志日期
                StrategyLog();

                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));
                    }
                }
            }
        }

        
#endregion

        
#region helper

        
/// <summary>
        
/// 根据日志策略生成日志
        
/// </summary>
        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);
            }
        }

        
/// <summary>
        
/// 根据年月生成子目录
        
/// </summary>
        
/// <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;
        }

        
#endregion

        
#endregion

        
#region Properties

        
/// <summary>
        
/// 日志文件路径
        
/// </summary>
        
/// <returns></returns>
        private static string GetLogFullPath
        {
            
get
            {
                
return string.Concat(log_root_directory, '\\'string.Concat(log_subdir, @"\log", CurrentLogFileDate.ToShortDateString(), ".txt"));
            }
        }

        
/// <summary>
        
/// 跟踪输出日志文件
        
/// </summary>
        private static TextWriterTraceListener TWTL
        {
            
get
            {
                
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;
            }
        }

        
#endregion

    }
}

  二、示例

    2.1  错误记录

        static void Main(string[] args)
        {
            IList
<string> list = null;

            
try
            {
                Console.WriteLine(list.Count);
            }
            
catch (Exception ex)
            {
                Logger.Trace(ex);
            }

            Console.ReadLine();
        }

      代码说明:错误很明显,未实例化就使用Count属性。

      日志截图:

       

    2.2  数据库记录

            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();
            }

            Console.ReadLine();
        }

      日志截图:

      

       需要注意这里日志策略改为了仅日志文件输出。


  三、注意事项

    3.1  进行日志文件输出的时候需要有写的权限。

    3.2  实际使用中可能还会有一个变量控制是否进行日志记录。

    3.3  错误记录一般会在Global.asax的Application_Error里面加上。

结束语  

  对于一般的小项目这个日志类是够用的了,日志的策略还可以根据自己的需求改变一下,合适就行: )  

本博你可能感兴趣的文章

      1.      .Net Validator验证框架 [ .Net | Validator Framework | Attribute ]

      2.      C# DLL资源文件打包(图片、JS、CSS)[WebResource]

      3.      C# 键盘监视+剪切板编程(每次复制都不一样哦!*v*)



原文地址:https://www.cnblogs.com/over140/p/1524735.html