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

//=========================================
//
// 作 者:农民伯伯
// 邮 箱:[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;
}
}

二、示例
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();

需要注意这里日志策略改为了仅日志文件输出。
三、注意事项
3.1 进行日志文件输出的时候需要有写的权限。
3.2 实际使用中可能还会有一个变量控制是否进行日志记录。
3.3 错误记录一般会在global.asax的application_error里面加上。
结束语
对于一般的小项目这个日志类是够用的了,日志的策略还可以根据自己的需求改变一下,合适就行: )
转载:http://www.cnblogs.com/over140/archive/2009/07/16/1524735.html