[转] C#实现自动化Log日志

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: 2012/3/19 6:03:00  

    Message: Enter method Work  

    Category: General  

    Priority: -1  

    EventId: 1  

    Severity: Information  

    Title:  

    Machine: PC4  

    App Domain: AutoLog.exe  

    ProcessId: 4200  

    Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe  

    Thread Name:   

    Win32 ThreadId:4000  

    Extended Properties:
    ----------------------------------------
    ----------------------------------------
    Timestamp: 2012/3/19 6:03:00  

    Message: Exception:Customer Exception  

    Category: General  

    Priority: -1  

    EventId: 1  

    Severity: Information  

    Title:  

    Machine: PC4  

    App Domain: AutoLog.exe  

    ProcessId: 4200  

    Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe  

    Thread Name:   

    Win32 ThreadId:4000  

    Extended Properties:
    ----------------------------------------
    ----------------------------------------
    Timestamp: 2012/3/19 6:03:00  

    Message: Exit method Work, use 00:00:00.0024272.  

    Category: General  

    Priority: -1  

    EventId: 1  

    Severity: Information  

    Title:  

    Machine: PC4  

    App Domain: AutoLog.exe  

    ProcessId: 4200  

    Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe  

    Thread Name:   

    Win32 ThreadId:4000  

    Extended Properties:
    ----------------------------------------
    ----------------------------------------
    Timestamp: 2012/3/19 6:03:00  

    Message: Enter method ToString  

    Category: General  

    Priority: -1  

    EventId: 1  

    Severity: Information  

    Title:  

    Machine: PC4  

    App Domain: AutoLog.exe  

    ProcessId: 4200  

    Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe  

    Thread Name:   

    Win32 ThreadId:4000  

    Extended Properties:
    ----------------------------------------
    ----------------------------------------
    Timestamp: 2012/3/19 6:03:00  

    Message: Exit method ToString, use 00:00:00.0001410.  

    Category: General  

    Priority: -1  

    EventId: 1  

    Severity: Information  

    Title:  

    Machine: PC4  

    App Domain: AutoLog.exe  

    ProcessId: 4200  

    Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe  

    Thread Name:   

    Win32 ThreadId:4000  

    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);
            }
        }
    }
时间: 2024-11-06 20:48:25

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

Android学习笔记——log无法输出的解决方法和命令行查看log日志

本人邮箱:[email protected],欢迎交流讨论. 欢迎转载,转载请注明网址:http://www.cnblogs.com/JohnTsai/p/3983936.html. 知识点 1.log无法输出的解决方法 2.通过命令行(command line)查看Android调试的log日志 log无法输出的解决方法 今天调试Android程序,发现Eclipse不输出log日志了.这让我很烦恼,程序调试的log都没法看到了.Google搜索了一些资料.发现stackoverflow上有很

解决Linux下Tomcat日志目录下的catalina.log日志文件过大的问题

本文摘自:(http://blog.csdn.net/stevencn76/article/details/6246162) 分类: Java技术专区2011-03-13 12:25 5017人阅读 评论(1) 收藏 举报 tomcatlinux工具任务web 由于Tomcat在默认情况下会将没有经过配置的web应用所产生的日志输出已经其本身的日志内容都输出到这个文件中,那么随着时间的推移,这个文件的尺寸将会越来越大,当需要检查日志内容时间会导致文件难以打开,而且同时tomcat依旧在不断的向文

捕获异常、存sd卡、封装请求头体、加密map值、网络工具类、生成Json、Https协议、传log日志到服务器、app崩溃友好重启

点击打开链接,免积分下载 在集成了统计SDK(友盟统计,百度统计等)之后,有一个非常有利于测试的功能:错误分析!此功能能够将程序在运行中碰到的崩溃(runtimeException)问题反馈到服务器,帮助开发者改善产品,多适配机器.然而在公司android开发中不集成这些SDK,那应该怎么实现这样的功能呢?下面让我们来看下如何使用UncaughtExceptionHandler来捕获异常. 在Android开发中,常常会出现uncheched Exception 导致程序的crash,为了提供良

LISTENER.LOG日志大小不能超过2GB

oracle 11G  windows 2008系统  造成了监听死锁 报TNS-00505: 操作超时 最后分析 发现 LISTENER.LOG日志大小超过2GB 解决方案: cd$ORACLE_HOME/network/log lsnrctlset log_status off mvlistener.log listener.bak lsnrctlset log_status on 以下是我在gdimall2上的一个操作记录: 首先改变监听的日志记录状态: $lsnrctlset log_s

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

开发接口程序时,要保证程序稳定运行就要时刻监控接口程序发送和接收的数据,这就需要一个日志记录的类将需要的信息记录在日志文件中,便于自己维护接口程序.(Web系统也是如此,只是对应的日志实现比这个要复杂一点). 刚开始考虑的比较少,没有加入控制日志文件数量的功能.运行了一段时间,文件夹内的Log文件如下所示: 如果是这样,那运行一年不就三百多个日志文件了,想一想这太可怕了.通过查找资料,发现.Net中的FileInfo存有文件的信息(包括名称,创建时间,文件大小等),那就自己定义一个文件比较器实现

Nginx Access Log日志统计分析常用命令

Nginx Access Log日志统计分析常用命令 Nginx Access Log日志统计分析常用命令 IP相关统计 统计IP访问量 awk '{print $1}' access.log | sort -n | uniq | wc -l 查看某一时间段的IP访问量(4-5点) grep "07/Apr/2017:0[4-5]" access.log | awk '{print $1}' | sort | uniq -c| sort -nr | wc -l 查看访问最频繁的前100

Arm开发板+Qt学习之路-论can网通讯受log日志的影响

日期:2016-05-25 最近开发过程中发现一个问题,使用两个开发板进行can网通讯,按照经验来说,通讯的速度应该是很快的,项目中将接口的超时时间设置为100ms,在某种情境下,会在短时间内发送多次请求,例如连续点击多次按钮,每次点击都发送一次can数据,此时就会出现超时的报告,纠结了很长时间,排除了各种问题,一直没解决. 今天偶然的一个念头,看见工程里面有许多测试用的log日志,使用了qdebug和str::cerr两种方式打印的,看着太多太烦,就挨个注释掉了,然后,奇迹发生了,竟然不在出现

spring aop 配置切面,记录系统异常存入log日志

1.spring.xml(这里主要配置了抛出异常后的操作after-throwing) 需要注意的地方以黄色标注,主要是几个切入点bean配置 <!-- 激活自动代理功能 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 系统服务组件的切面Bean --> <bean id="aspectService" class="com.test.http

Log日志打印集合类型

看到Logger可以打印json,当时就想能不能打印集合呢,现在通过学习了一些反射的东西,写了出来,仅供参考. public static <E> void list(List<E> list) { if (IS_DDEBUG) { if (list == null || list.size() == 0) { Logger.d("list为空"); } else { Field[] allFields = null; StringBuilder builder