相信很多coder都有这样的癖好:“自恋”!!对自己编写的code总是那么的自信,自豪,Always believe it to be so perfect!!

不喜欢做单元测试(总觉得它就那样了能出什么错?),不喜欢做日志(总觉得他没有什么用!),不做日志也就算了还把异常给“吃”了(只是为了让别人看不到那又黄又红的像坨屎一样的页面),最终只能独自一人默默的抓狂,累的像那什么一样,自作孽不可活!!

其实......饿......我就是这样的啦(ˉ▽ˉ;)...

为了让生活的幸福美满,为了工作的轻松快乐,我决定虔诚的忏悔,痛定思痛,写一个简单日志!(◎﹏◎)...

基于TraceSource的系统日志

TraceSource官方给出的描述是这样的:“提供一组方法和属性,利用这些方法和属性,应用程序可以跟踪代码的执行并将跟踪消息和它们的源关联起来”。总觉得这描述跟系统日志挂不上勾额,但事实它是用来做系统日志的一个不错的东西;

首先为了迎合当今编程思想,先来建2个接口:

1.ILogger:用于实现日志的写入源

  /// <summary>
/// 系统日志接口
/// </summary>
public interface ILogger
{
/// <summary>
/// 系统崩溃错误日志
/// </summary>
/// <param name="message">错误信息</param>
/// <param name="args">设置格式的对象的数组</param>
void Fatal(string message, params object[] args); /// <summary>
/// 系统崩溃错误日志
/// </summary>
/// <param name="message">错误信息</param>
/// <param name="exception">异常对象</param>
/// <param name="args">设置格式的对象的数组</param>
void Fatal(string message, Exception exception, params object[] args); /// <summary>
/// 系统消息日志
/// </summary>
/// <param name="message">要记录的信息</param>
/// <param name="args">设置格式的对象的数组</param>
void Infomation(string message, params object[] args); /// <summary>
/// 系统警告日志
/// </summary>
/// <param name="message">警告信息</param>
/// <param name="args">设置格式的对象的数组</param>
void Warning(string message, params object[] args); /// <summary>
/// 系统错误日志
/// </summary>
/// <param name="message">错误信息</param>
/// <param name="args">设置格式的对象的数组</param>
void Error(string message, params object[] args); /// <summary>
/// 系统错误日志
/// </summary>
/// <param name="message">错误信息</param>
/// <param name="exception">异常对象</param>
/// <param name="args">设置格式的对象的数组</param>
void Error(string message, Exception exception, params object[] args);
}

2.ILoggerFactory:用于生产指定的日志写入源

  /// <summary>
/// 系统日志工厂
/// </summary>
public interface ILoggerFactory
{
/// <summary>
/// 创建一个系统日志
/// </summary>
ILogger Create();
}

为了方便编码和保持日志的统一性,我们再建一个日志上下文

  /// <summary>
/// 系统日志上下文.
/// </summary>
public static class LoggerContext
{
static ILoggerFactory _currentLogFactory = null; /// <summary>
/// 设置当然上下文使用的日志工厂
/// <remarks>
/// 该上下文始终使用一个日志工厂进行创建日志,建议在系统启动时进行设置,设置后将无法再进行设置
/// </remarks>
/// </summary>
/// <param name="factory">日志工厂</param>
public static void SetCurrent(ILoggerFactory factory)
{
if (_currentLogFactory != null)
throw new ArgumentException("该日志上下文已经设置使用的日志工厂,无法进行再次设置,如需使用其他日志工厂,请直接实例日志工厂进行操作。", "factory"); _currentLogFactory = factory;
} /// <summary>
/// 创建一个日志
/// </summary>
public static ILogger CreateLog()
{
if (_currentLogFactory == null)
throw new NullReferenceException("该日志上下文尚未设置日志工厂,请使用SetCurrent方法进行设置。"); return _currentLogFactory.Create();
}
}

好的,现在我们进入正题,使用TraceSource进行日志记录,不要介意哈,进入正题前总要有些前奏, 目的你懂得o(^▽^)o.....

TraceSource 位于命名空间System.Diagnostics下,该命名空间在System.dll中,所以无需添加引用,比较方便。

下面是基于TraceSource的ILogger实现:

    public sealed class TraceSourceLogger
:ILogger
{
private const string EXCEPTION_FORMAT = "{0} 捕获异常信息:{1}"; TraceSource _source; public TraceSourceLogger()
{
_source = new TraceSource("Bulrush");
} public void Fatal(string message, params object[] args)
{
if (String.IsNullOrWhiteSpace(message))
return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
Trace(TraceEventType.Critical, messageToTrace);
} public void Fatal(string message, Exception exception, params object[] args)
{
if (String.IsNullOrWhiteSpace(message) || exception == null)
return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
string exceptionString = exception.ToString();
Trace(TraceEventType.Critical, String.Format(CultureInfo.InvariantCulture, EXCEPTION_FORMAT, messageToTrace, exceptionString));
} public void Infomation(string message, params object[] args)
{
if (String.IsNullOrWhiteSpace(message))
return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
Trace(TraceEventType.Information, messageToTrace);
} public void Warning(string message, params object[] args)
{
if (String.IsNullOrWhiteSpace(message))
return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
Trace(TraceEventType.Warning, messageToTrace);
} public void Error(string message, params object[] args)
{
if (String.IsNullOrWhiteSpace(message))
return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
Trace(TraceEventType.Error, messageToTrace);
} public void Error(string message, Exception exception, params object[] args)
{
if (String.IsNullOrWhiteSpace(message) || exception == null)
return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
string exceptionString = exception.ToString();
Trace(TraceEventType.Error, String.Format(CultureInfo.InvariantCulture, EXCEPTION_FORMAT, messageToTrace, exceptionString));
} void Trace(TraceEventType eventType, string message)
{
if (_source != null)
{
try
{
_source.TraceEvent(eventType, (int)eventType, message);
}
catch (SecurityException)
{
//这里处理写入是出现的安全问题,如文件没有写入权限。
}
}
}
}

这个实现比较简单,但是这里有一个很好的哦,那是什么呢?嘻嘻就TraceSource里的Listeners倾听器,微软给我们提供了几个常用的倾听器,我觉得基本已经够用了,

1.DefaultTraceListener:默认使用这个,这个倾听器会输出在调试器的输出窗口。

2.EventLogTraceListener: 这个是操作系统日志的倾听器,会把日志记录在操作系统的事件里,我还是比较喜欢这个,毕竟比较完善,安全性也比较好。

3.TextWriterTraceListener:这个是文本编辑器的倾听器,简单点就是以文件流的形式进行记录,当然了文件路径是自己定义的,这个也比较常用。

4.XmlWriterTraceListener:这个Xml文件的倾听器,用法和TextWriterTraceListener差不多,只是使用Xml流格式进行记录。

等等,当然还有几个倾听器,这里就不一一列出了,有兴趣的可以查看MSDN的System.Diagnostics

如果你想拓展也可以,如记录在数据库,或者使用Log4net等等,只要继承TraceListener基类进行重写就可以了。

下面是一个最简单的自定义倾听器:

    public class CustomeTraceListener
: TraceListener
{
public override void Write(string message)
{
File.AppendAllText(@"d:\log.txt", message);
} public override void WriteLine(string message)
{
File.AppendAllText(@"d:\log.txt", message+ Environment.NewLine);
}
}

下面我们在写一个TraceSourceLogger工厂就可以了,代码如下:

    public class TraceSourceLoggerFactory
: ILoggerFactory
{
public ILogger Create()
{
var logger = new TraceSourceLogger();
return logger;
}
}

OK,代码已经写好了,那又的同学就要问了倾听器在哪里设置呢?

这个问题很简单,当然是在配置文件里配置了;

<configuration>
<system.diagnostics>
<sources>
<source name="Bulrush" switchName="SourceSwitch" switchType="System.Diagnostics.SourceSwitch">
<listeners>
<clear/>
<add name="eventLog"></add>
</listeners>
</source>
</sources>
<switches>
<!--这里设置TraceSource的写入开关,默认为Off关闭,不进行写入,具体值可以查看SourceLevels枚举-->
<add name="SourceSwitch" value="All"/>
</switches>
<sharedListeners>
<!--
这里使用操作系统的事件倾听器,initializeData属性是事件源,false为默认。
不同的倾听器initalizeData有不同的意义,如TextWriterTraceListnener倾听器,可以设置为“d:\log.txt”,意思就是保存的路径。
-->
<add name="eventLog"
type="System.Diagnostics.EventLogTraceListener"
initializeData="false"/>
</sharedListeners>
</system.diagnostics>
</configuration>

到这里就结束了,下面做个简单的测试,是使用EventLogTraceListener倾听器:

        [ClassInitialize()]
public static void ClassInitialze(TestContext context)
{
LoggerContext.SetCurrent(new TraceSourceLoggerFactory());
} [TestMethod]
public void TestTraceSourceLogger()
{
//LoggerContext.CreateLog().Error("错误日志"); var logger = LoggerContext.CreateLog(); try
{
logger.Error("错误日志");
logger.Fatal("系统崩溃日志");
logger.Infomation("普通消息日志");
logger.Warning("非关键性,警告日志");
}
catch
{
Assert.Fail();
}
}

结果为:

太晚了,该睡觉了哦!!

轻松背后的N+疲惫——系统日志的更多相关文章

  1. 使用StackTrace堆栈跟踪记录详细日志(可获取行号)

    上一篇我们提到使用.NET自带的TraceSource实现简单的日志,具体请看<轻松背后的N+疲惫——系统日志>,这一篇注意想讲的是日志的详细记录,包含请求开始到结束的过程中调用的方法链以 ...

  2. StackTrace堆栈跟踪记录详细日志

    使用StackTrace堆栈跟踪记录详细日志(可获取行号) 2014-04-25 22:30 by 螺丝钉想要螺丝帽, 350 阅读, 3 评论, 收藏, 编辑 上一篇我们提到使用.NET自带的Tra ...

  3. words2

    餐具:coffee pot 咖啡壶coffee cup 咖啡杯paper towel 纸巾napkin 餐巾table cloth 桌布tea -pot 茶壶tea set 茶具tea tray 茶盘 ...

  4. Mac OS X 背后的故事

    Mac OS X 背后的故事 作者: 王越  来源: <程序员>  发布时间: 2013-01-22 10:55  阅读: 25840 次  推荐: 49   原文链接   [收藏]   ...

  5. 成功的背后!(给所有IT人)

    转载:来自CSDN第一名博主:http://blog.csdn.net/phphot/article/details/2187505 成功的背后,有着许多不为人知的故事,而正是这些夹杂着泪水和汗水的过 ...

  6. RDIFramework.NET ━ 9.13 系统日志与系统异常管理 ━ Web部分

    RDIFramework.NET ━ .NET快速信息化系统开发框架 9.13  系统日志与系统异常管理 -Web部分  一个软件在投入运行时不可能没有任何异常,在软件发生异常时及时的记录下来,也好我 ...

  7. [转]行者,一念一生,成功的背后!(给所有IT人)

    成功的背后,有着许多不为人知的故事,而正是这些夹杂着泪水和汗水的过去,才成就了一个个走向成功的普通人. 凌晨两点半,早 已习惯了一个人坐在电脑前的我,望着屏幕,任思绪在暗夜的包容下静静流淌,时光仿佛又 ...

  8. C++ STL轻松导学

    作为C++标准不可缺少的一部分,STL应该是渗透在C++程序的角角落落里的.STL不是实验室里的宠儿,也不是程序员桌上的摆设,她的激动人心并非昙花一现.本教程旨在传播和普及STL的基础知识,若能借此机 ...

  9. 使用Let’s Encrypt轻松配置https站点

    使用Let's Encrypt轻松配置https站点 https不仅能提高网站安全,更是被搜索引擎纳入排名的因素之一. 2015年10月份,微博上偶然看到Let's Encrypt 推出了beta版, ...

随机推荐

  1. [汇编语言]-第十章 ret,retf,call指令

    1- ret 相当于 pop IP;用栈中数据,修改IP内容.从而实现近转移. 执行后(IP)=0, CS:IP指向代码段的第一条指令. assume cs:code stack segment db ...

  2. Ecstore中的微信支付怎么样配置

    要在Ecstore中开启微信支付,需要先在后台/应用中心中安装“移动商城”和“微信商城管理”这两个App移动商城App是ecstore的手机wap版,可在手机浏览器中实现商城的B2c购物功能.“微信商 ...

  3. haproxy之负载均衡算法

    backend     blance 算法 动态hash的特点     服务器运行时就可进行权重调整,即只需要重新载入配置文件即可,不需要重新启动haproxy     支持慢速启动,即重新恢复的后端 ...

  4. Django学习(六) 模板

    下面是一个新闻的模板:mysite/news/templates/news/year_archive.html mysite/news/templates/news/year_archive.html ...

  5. 从客户端(******)中检测到有潜在危险的 Request.Form 值。

    在 提交表单时候,asp.net 提示:"从客户端(......)中检测到有潜在危险的 Request.Form 值" .asp.net中的请求验证特性提供了某一等级的保护措施防止 ...

  6. Java 学习 第四篇;面向对象(1)

    1:关于继承为了保证父类的良好封装性,不会被子类随意改变,设计父类时通常隐藏父类的内部数据,把父类属性改为private如果父类中可以被重写,但不希望被其他类自由访问可用protected修饰;2:什 ...

  7. NOI十连测 第四测 T1

    思路:首先每个蚂蚁移速相同,而且碰到就转头,这其实等价于擦肩而过! 看到2n个数互不相同就觉得方便多了:枚举每个数字往左或者往右作为最慢,然后考虑其他蚂蚁有多少种走路方向. (1),走的距离大于m/2 ...

  8. USB系列之八:透过ASPI执行SCSI命令

    在<USB系列之七>里我们介绍了ASPI的规范,并对一系列ASPI的命令做了测试,其中的02号命令是执行SCSI命令,我们专门在这篇文章中介绍,在<USB系列七>中,我们已经了 ...

  9. 处理事件的方式:两种类的覆盖处理(自己管理,覆盖专用事件函数;自己统一管理,覆盖QWidget::Event通用函数),一种对象的处理(父控件统一管理,即安装过滤器),两种全局处理(QCoreApplication安装过滤器;覆盖notify方法)

    虽然只有一句话,但却是我自己的心得. 特别注意,bool QCoreApplication::notify(QObject *receiver, QEvent *event) 明确指明了要发送的对象, ...

  10. Wap touch flispan demo

    直接上代码了 仔细看看例子就会明白 简单实用 <!DOCTYPE HTML> <html> <head> <meta charset="utf-8& ...