qing2005原文地址 C#实现自动化Log日志

在开发项目的时候,我们不免要使用Log记录日志,使用最多的是Log4Net和EntLib Log,在需要记录日志的代码处加入log.Write(日志信息),假设我需要跟踪业务方法,记录方法的传递参数,执行时间,返回数据等;或者我需要查 看方法的调用关系,希望进入方法的时候自动记录参数信息,出方法时记录结果和执行时间信息。这时就是一个典型的AOP运用,Java在AOP方面是很容易 实现的,因为java有类加载器。但是.Net在AOP方面就不怎么容易,严格意义上.Net没有真正的AOP。这话并不代表.Net不能实现AOP,比 如:PostSharp和Enterprise library就能实现。

先介绍一下PostSharp,我们知道.net代码将编译成MSIL(微软中间语言),然后CPU将MSIL的exe文件生成本地CPU的二进制文件格式,PostSharp就是在编译过程中加入IL代码,因而完成AOP功能。
缺点:编译器需要PostSharp组件,维护代码困难,因为IL代码不好识别;
优点:使用方便(PostSharp2是收费版,破解也比较方便,在此不介绍破解)

这里我重点介绍如何使用Enterprise Library实现自动化Log。

1.首先我们需要下载Enterprise Library,最新为5.0版本;

2.新建一个控制台项目,并添加以下程序集
Microsoft.Practices.EnterpriseLibrary.Common
Microsoft.Practices.EnterpriseLibrary.Logging
Microsoft.Practices.EnterpriseLibrary.PolicyInjection
Microsoft.Practices.ServiceLocation
Microsoft.Practices.Unity
Microsoft.Practices.Unity.Interception

3.添加AutoLogCallHandler类,实现ICallHandler接口
这个类是执行调用目标方法,在调用目标方法前获取方法的参数信息,并用EntLib Log记录日志;
方法结束后,再次记录日志,并统计执行时间和异常处理

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System.Diagnostics;
using System.Reflection; namespace AutoLog {
public class AutoLogCallHandler:ICallHandler { private LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>(); public AutoLogCallHandler() { } public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {
StringBuilder sb = null;
ParameterInfo pi = null; string methodName = input.MethodBase.Name;
logWriter.Write(string.Format("Enter method " + methodName)); if (input.Arguments != null && input.Arguments.Count > 0) {
sb = new StringBuilder();
for (int i = 0; i < input.Arguments.Count; i++) {
pi = input.Arguments.GetParameterInfo(i);
sb.Append(pi.Name).Append(" : ").Append(input.Arguments[i]).AppendLine();
}
logWriter.Write(sb.ToString());
} Stopwatch sw = new Stopwatch();
sw.Start(); IMethodReturn result = getNext()(input, getNext);
//如果发生异常则,result.Exception != null
if (result.Exception != null) {
logWriter.Write("Exception:" + result.Exception.Message);
//必须将异常处理掉,否则无法继续执行
result.Exception = null;
} sw.Stop();
logWriter.Write(string.Format("Exit method {0}, use {1}.",methodName, sw.Elapsed)); return result;
} public int Order { get; set; }
}
}

4.要自动化日志就需要创建一个标记属性,指定方法能自动进行日志
这里就创建AutoLogCallHandlerAttribute标记属性

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration; namespace AutoLog { public class AutoLogCallHandlerAttribute:HandlerAttribute { public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container) {
return new AutoLogCallHandler() { Order = this.Order };
}
}
}

5.创建实体类
注意:我在Work和ToString方法上方加上了AutoLogCallHandler属性,它是AutoLogCallHandlerAttribute的简写形式。用以指示这两个方法用AutoLogCallHandler的Invoke来处理。

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity; namespace AutoLog { public class Employee : MarshalByRefObject
{ public Employee() {} public string Name { get; set; } [AutoLogCallHandler()]
public void Work() {
Console.WriteLine("Now is {0},{1} is working hard!",DateTime.Now.ToShortTimeString(),Name);
throw new Exception("Customer Exception");
} [AutoLogCallHandler()]
public override string ToString() {
return string.Format("I'm {0}.",Name);
}
}
}

6.测试代码
注意:必须使用PolicyInjection.Create<Employee>()来创建对象,不然无法实现。

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;
using Microsoft.Practices.Unity;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration; namespace AutoLog {
class Program { private static LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>(); static void Main(string[] args) { Employee emp = PolicyInjection.Create<Employee>(); emp.Name = "Lele"; emp.Work();
Console.WriteLine(emp);
}
}
}

7.还需要用EntLib的配置工具完成Log配置,将Log信息写入Trace.log文件中

    <?xml version="1.0"?>
<configuration>
<configSections>
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
<listeners>
<add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
fileName="trace.log" formatter="Text Formatter" />
</listeners>
<formatters>
<add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
template="Timestamp: {timestamp}{newline}
Message: {message}{newline}
Category: {category}{newline}
Priority: {priority}{newline}
EventId: {eventid}{newline}
Severity: {severity}{newline}
Title:{title}{newline}
Machine: {localMachine}{newline}
App Domain: {localAppDomain}{newline}
ProcessId: {localProcessId}{newline}
Process Name: {localProcessName}{newline}
Thread Name: {threadName}{newline}
Win32 ThreadId:{win32ThreadId}{newline}
Extended Properties: {dictionary({key} - {value}{newline})}"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All" name="General">
<listeners>
<add name="Flat File Trace Listener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All" name="All Events" />
<notProcessed switchValue="All" name="Unprocessed Category" />
<errors switchValue="All" name="Logging Errors & Warnings">
<listeners>
<add name="Flat File Trace Listener" />
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

好了,测试一下,控制台输入:
Now is 14:03,Lele is working hard!
I'm Lele.
再看看Trace.log文件内容:

    ----------------------------------------
Timestamp: // :: Message: Enter method Work Category: General Priority: - EventId: Severity: Information Title: Machine: PC4 App Domain: AutoLog.exe ProcessId: Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe Thread Name: Win32 ThreadId: Extended Properties:
----------------------------------------
----------------------------------------
Timestamp: // :: Message: Exception:Customer Exception Category: General Priority: - EventId: Severity: Information Title: Machine: PC4 App Domain: AutoLog.exe ProcessId: Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe Thread Name: Win32 ThreadId: Extended Properties:
----------------------------------------
----------------------------------------
Timestamp: // :: Message: Exit method Work, use ::00.0024272. Category: General Priority: - EventId: Severity: Information Title: Machine: PC4 App Domain: AutoLog.exe ProcessId: Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe Thread Name: Win32 ThreadId: Extended Properties:
----------------------------------------
----------------------------------------
Timestamp: // :: Message: Enter method ToString Category: General Priority: - EventId: Severity: Information Title: Machine: PC4 App Domain: AutoLog.exe ProcessId: Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe Thread Name: Win32 ThreadId: Extended Properties:
----------------------------------------
----------------------------------------
Timestamp: // :: Message: Exit method ToString, use ::00.0001410. Category: General Priority: - EventId: Severity: Information Title: Machine: PC4 App Domain: AutoLog.exe ProcessId: Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe Thread Name: Win32 ThreadId: Extended Properties:
----------------------------------------

实现了自动化Log后,回过头来再看第5步,Employee继承了MarshalByRefObject,一般我们的业务类或数据访问类都有基类,那么我们就需要使用接口
这里我添加一个IEmployee接口,里面就Work方法(ToString是重写Object的)。

    using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity; namespace AutoLog { public interface IEmployee {
void Work();
} public class Employee : IEmployee
{ public Employee() {
//this.Name = "Lele";
} public string Name { get; set; } [AutoLogCallHandler()]
public void Work() {
Console.WriteLine("Now is {0},{1} is working hard!",DateTime.Now.ToShortTimeString(),Name);
throw new Exception("Customer Exception");
} [AutoLogCallHandler()]
public override string ToString() {
return string.Format("I'm {0}.",Name);
}
}
}

然后在测试类改动一下

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;
using Microsoft.Practices.Unity;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration; namespace AutoLog {
class Program { private static LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>(); static void Main(string[] args) { IEmployee emp = PolicyInjection.Create<Employee, IEmployee>(); emp.Work();
Console.WriteLine(emp);
}
}
}

[转] C#实现自动化Log日志的更多相关文章

  1. web自动化 -- HTMLreport(三)测试报告输出log日志

    一.需求痛点 1.HTMLreport没法看到log日志,经过封装的框架不可能走一步就print() 2. 希望可以在HTMLreport中输出log日志 3.痛点截图 二.解决办法 1.既然是HTM ...

  2. [日志分析] Access Log 日志分析

    0x00.前言: 如何知道自己所在的公司或单位是否被入侵了?是没人来“黑”,还是因自身感知能力不足,暂时还没发现?入侵检测是每个安全运维人员都要面临的严峻挑战.安全无小事,一旦入侵成功,后果不堪设想. ...

  3. Atitit.log日志技术的最佳实践attilax总结

    Atitit.log日志技术的最佳实践attilax总结 1. 日志的意义与作用1 1.1. 日志系统是一种不可或缺的单元测试,跟踪调试工具1 2. 俩种实现[1]日志系统作为一种服务进程存在 [2] ...

  4. mysql general log日志

    注:应一直出现http://www.cnblogs.com/hwaggLee/p/6030765.html文章中的问题 故mysql general log日志.查看具体是什么命令导致的. 打开 ge ...

  5. 使用触发器实现记录oracle用户登录失败信息到alert.log日志文件

    前面我们说了用oracle自带的审计功能可以实现记录用户登录失败日志到数据表中(链接:http://www.54ok.cn/6778.html).今天我们来分享一下如何把用户登录失败信息记录到aler ...

  6. Junit测试打印详细的log日志,可以看到sql

    Junit测试打印详细的log日志,可以看到sql 在log4j.xml的日志配置文件中,把日志级别从info级别调整到debug级别: <?xml version="1.0" ...

  7. iOS及时log日志查看工具 (iConsole)

    github下载地址:https://github.com/nicklockwood/iConsole 偶然看到的一个iOS及时log日志查看工具,通过该工具,我们可以在任何想看日志的时候,通过手势呼 ...

  8. svn update -r m path 代码还原到某个版本(这样之前的log日志也就没了,也就是清空log日志)

    [root@ok 资料库]# svn log 简历 ------------------------------------------------------------------------ r ...

  9. 【个人使用.Net类库】(2)Log日志记录类

    开发接口程序时,要保证程序稳定运行就要时刻监控接口程序发送和接收的数据,这就需要一个日志记录的类将需要的信息记录在日志文件中,便于自己维护接口程序.(Web系统也是如此,只是对应的日志实现比这个要复杂 ...

随机推荐

  1. 【redis】04set类型和zset类型

    sets类型   sets类型及操作   Set类型是一个集合,他是string类型的无序集合,也就是说咱们的set是没有顺序的, Set是通过hash table实现的,添加.删除和查找的复杂度都是 ...

  2. Chpater 10: Sorting

    Internal Sort: Bubble  O(n2) Selection O(n2) Insertion O(n2) Shell O(nlogn) Merge O(nlogn) Heap O(nl ...

  3. C#和Javascript中 正则表达式使用的总结

    说明:本文并非原创,而是从网站上搜集了一些资料整理的!如有雷同,纯属巧合 1.js中正则表达式的使用 在js中定义正则表达式很简单,有两种方式,一种是通过构造函数,一种是通过//,也就是两个斜杠.例如 ...

  4. SDUT2241计算组合数C(n,m)(组合数)

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2241 这个题的代码适应性也挺强,但这个题倒不适 ...

  5. POJ 2253 Frogger(floyd)

    http://poj.org/problem?id=2253 题意 : 题目是说,有这样一只青蛙Freddy,他在一块石头上,他呢注意到青蛙Fiona在另一块石头上,想去拜访,但是两块石头太远了,所以 ...

  6. 0环境设置 - SQLPLUS设置

    define _editor=vi - SQL*PLUS默认编辑器set serveroutput on size 1000000 - 默认打开DBMS_OUTPUT, 不用每次使用都执行这个命令来启 ...

  7. Spring 3.0: Unable to locate Spring NamespaceHandler for XML schema namespace

    被这个问题折磨着很久:参考: http://have23.iteye.com/blog/1340777 (cfx 与 spring 整合的时候出现的问题: org.springframework.be ...

  8. 如何查看linux是32位还是64位

    可以用命令“getconf LONG_BIT”查看,如果返回的结果是32则说明是32位,返回的结果是64则说明是64位. 此外还可以使用命令“uname -a”查看,输出的结果中,如果有x86_64就 ...

  9. Wince 中如何实现注册表恢复原厂设置

    理论: 使用HIVE注册表,系统在完成了第一阶段也就是加载完了boot.hv+binfs之后和加载系统HIVE注册表之前,filesys.exe都会调用OEMIoControl来查询是否需要清除保存在 ...

  10. firebug的使用方法和技巧(web开发调试工具)

    Firebug是firefox下的一个插件,能够调试所有网站语言,如Html,Css等,但FireBug最吸引我的就是javascript调试功 能,使用起来非常方便,而且在各种浏览器下都能使用(IE ...