转:使用log4net完成程序异常日志记录(使用SQLite数据库记录和普通文本记录)

http://www.cnblogs.com/kyo-yo/archive/2010/06/11/use-log4net-to-log-exception.html

在前端时间开发的时候由于需要将异常保存到数据库中,所以就到网上搜了下专门的日志记录工具,一搜果然很多,比如:log4net,NLog,EntLib Logging等等,但是还是log4net名气最大,所以就下载下来试用了一番,果然很方便,其涵盖了所有常用的日志记录方式具体的可以看下表:

AdoNetAppender 将日志记录到数据库中。可以采用SQL和存储过程两种方式。

AnsiColorTerminalAppender 将日志高亮输出到ANSI终端。

AspNetTraceAppender 能用asp.net中Trace的方式查看记录的日志。

BufferingForwardingAppender 在输出到子Appenders之前先缓存日志事件。

ConsoleAppender 将日志输出到应用程序控制台。

EventLogAppender 将日志写到Windows Event Log。

FileAppender 将日志输出到文件。

ForwardingAppender 发送日志事件到子Appenders。

LocalSyslogAppender 将日志写到local syslog service (仅用于UNIX环境下)。

MemoryAppender 将日志存到内存缓冲区。

NetSendAppender 将日志输出到Windows Messenger service.这些日志信息将在用户终端的对话框中显示。

OutputDebugStringAppender 将日志输出到Debuger,如果程序没有Debuger,就输出到系统Debuger。如果系统Debuger也不可用,将忽略消息。

RemoteSyslogAppender 通过UDP网络协议将日志写到Remote syslog service。

RemotingAppender 通过.NET Remoting将日志写到远程接收端。

RollingFileAppender 将日志以回滚文件的形式写到文件中。

SmtpAppender 将日志写到邮件中。

SmtpPickupDirAppender 将消息以文件的方式放入一个目录中,像IIS SMTP agent这样的SMTP代理就可以阅读或发送它们。

TelnetAppender 客户端通过Telnet来接受日志事件。

TraceAppender 将日志写到.NET trace 系统。

UdpAppender 将日志以无连接UDP数据报的形式送到远程宿主或用UdpClient的形式广播。

怎么样?看了是不是很心动?如果想学习log4net的话可以看下园子里这位兄弟写的文章:如何使用Log4net创建日志及简单扩展,里面详细介绍了如何使用log4net记录日志,本文呢仅仅就对异常出现后如何记录下来进行讨论,同时也是做个记录方便日后写微软企业库 学习之路有所引用。

在日常的项目开发过程中总会碰到各种各样的异常,我们总是希望异常能第1时间捕获,同时能清楚的知道异常信息、异常发生的时间、发生异常的位置,这样我们好立刻追踪到其发生点来具体解决问题,log4net就很好的帮我们解决了这个问题

现在我们就开始对如何进行异常日志的记录做个分析:

首先是具体的config配置文件,主要分为2个日志记录器,一个是LogToSqlite(记录到SQLite数据库),另外一个是LogToFile(记录到相应的文件),如果要更换到其他数据库也是一样的,值需要更改connectionTypeconnectionString就可以了:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <configSections>

    <section name="log4net" type="System.Configuration.IgnoreSectionHandler, log4net" />

  </configSections>

  <log4net>

    <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender,log4net">

      <!--BufferSize为缓冲区大小-->

      <bufferSize value="100" />

      <!--<param name="BufferSize" value="2" />-->

      <!--引用-->

      <connectionType value="System.Data.SQLite.SQLiteConnection, System.Data.SQLite, Version=1.0.65.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />

      <!--连接字符串-->

      <connectionString value="data source=F:\\项目开发\\log4netDemo\\WebApplication1\\bin\\log.db3" />

      <!--插入语句-->

      <commandText value="insert into [Log2] ([Author],[LogDate],[Log_Level],[Message],[Location],[Exception]) Values(@Author,@Date,@Level,@Message,@Location,@Exception);" />

      <commandType value="Text"/>

      <!--操作者,暂时没用到-->

      <parameter>

        <parameterName value="@Author" />

        <dbType value="String" />

        <layout type="log4net.Layout.PatternLayout">

          <conversionPattern value="%property{Operator}" />

        </layout>

      </parameter>

      <!--记录时间-->

      <parameter>

        <parameterName value="@Date" />

        <dbType value="DateTime" />

        <layout type="log4net.Layout.RawTimeStampLayout" />

      </parameter>

      <!--日志等级-->

      <parameter>

        <parameterName value="@Level" />

        <dbType value="String" />

        <layout type="log4net.Layout.PatternLayout">

          <conversionPattern value="%level" />

        </layout>

      </parameter>

      <!--异常消息-->

      <parameter>

        <parameterName value="@Message" />

        <dbType value="String" />

        <layout type="log4net.Layout.PatternLayout">

          <conversionPattern value="%message" />

        </layout>

      </parameter>

      <!--异常位置-->

      <parameter>

        <parameterName value="@Location" />

        <dbType value="String" />

        <layout type="log4net.Layout.PatternLayout">

          <conversionPattern value="%location" />

        </layout>

      </parameter>

      <!--错误-->

      <parameter>

        <parameterName value="@Exception" />

        <dbType value="String" />

        <layout type="log4net.Layout.PatternLayout">

          <conversionPattern value="%exception" />

        </layout>

      </parameter>

    </appender>

    <appender name="LogAllToFile" type="log4net.Appender.RollingFileAppender,log4net">

      <!--输出格式

                     每种转换符号都以%开始,后面跟着一个格式符号和换符号。

                     %-数字 :该项的最小长度,小于最小长度的用空格填充

                     %m(message):输出的日志消息

                     %n(new line):换行

                     %d(datetime):输出当前语句运行的时刻

                     %r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数

                     %t(thread id):当前语句所在的线程ID

                     %p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等

                     %c(class):当前日志对象的名称,

                     %L(line ):输出语句所在的行号

                     %F(file name):输出语句所在的文件名

                     %logger 日志名称

                 -->

      <param name="File" value="log\"/>

      <param name="AppendToFile" value="true"/>

      <param name="MaxSizeRollBackups" value="100"/>

      <param name="MaximumFileSize" value="1KB"/>

      <param name="StaticLogFileName" value="false"/>

      <param name="DatePattern" value="yyyyMMdd&quot;.log&quot;"/>

      <param name="RollingStyle" value="Date"/>

      <layout type="log4net.Layout.PatternLayout">

        <param name="ConversionPattern" value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 记录类:%logger 操作者ID:%property{Operator} 操作类型:%property{ActionType}%n当前机器名:%property%n当前机器名及登录用户:%username %n记录位置:%location%n消息描述:%property{Message}%n异常:%exception%n消息:%message%newline%n%n" />

      </layout>

    </appender>

    <logger name="LogToSqlite">

      <level value="ERROR"/>

      <appender-ref ref="ADONetAppender"/>

    </logger>

    <!--<logger name="LogToFile">

      <level value="ALL"/>

      <appender-ref ref="LogAllToFile"/>

    </logger>-->

    <!--所有logger的基础,root的设置在所有logger中都起作用。

        当在root和logger中重复设定相同的appender时,你会发现同一日志信息将被记录两次。-->

    <!--<root>

      <level value="ERROR"/>

      ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF

      <appender-ref ref="LogAllToFile"/>

      <appender-ref ref="ADONetAppender"/>

    </root>-->

  </log4net>

</configuration>

在普通的C/S系统下都会有个程序入口,我们可以在这个入口点做文章,在程序启动时添加2个事件来监听异常:


1

2

Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

这2个事件是当执行Application.Run方法的线程发生未捕获异常时,触发 Application.ThreadException和如果 handler 抛出异常,或者不在 UI 线程中发生异常,将触发 
AppDomain.UnhandledException事件。

其入口点代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

static class Program

    {

        /// <summary>

        /// 应用程序的主入口点。

        /// </summary>

        [STAThread]

        static void Main()

        {

            //若不在AssemblyInfo.cs配置[assembly: log4net.Config.XmlConfigurator(ConfigFile = "WindowsFormsApplication1.exe.config", Watch = true)]

            //可使用一下代码来读取log4net配置文件

            string assemblyFilePath = Assembly.GetExecutingAssembly().Location;

            string assemblyDirPath = Path.GetDirectoryName(assemblyFilePath);

            string configFilePath = assemblyDirPath + " \\log4net.xml";

            log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(configFilePath));

            //异常

            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            Application.EnableVisualStyles();

            Application.SetCompatibleTextRenderingDefault(false);

            Application.Run(new Form1());

        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)

        {

            if (e.ExceptionObject is System.Exception)

            {

                HandleException((System.Exception)e.ExceptionObject);

            }

        }

        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)

        {

            HandleException(e.Exception);

        }

        public static void HandleException(Exception ex)

        {

            log4net.ILog log = (log4net.ILog)log4net.LogManager.GetLogger("LogToSqlite");

            log.Error(ex.Message, ex);

        }

    }

而在B/S程序下面我们则可以利用页面级别的Page_Error事件或者整个应用程序级别的Application_Error事件(本例子中采用Page_Error处理),同时我们还要做一步处理就是在Global.asax中的Application_Start添加log4net的配置读取,或者也可以在AssemblyInfo.cs添加和WinFrom一样的配置,不过如果仅限于WebForm,而Web网站就只能在Global中配置,所以这边我们就采用通用配置:


1

2

3

4

protected void Application_Start(object sender, EventArgs e)

        {

            log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(Server.MapPath("~") + @"\log4net.xml"));

        }

为了方便每个页面进行异常捕获我们建立一个PageBase,让所有的页面都继承这个PageBase,这样只需在PageBase中写一个Page_Error就可以了,代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

public class PageBase : System.Web.UI.Page

    {

        protected void Page_Error(object sender, EventArgs args)

        {

            //获取最新的异常信息

            var ex = Server.GetLastError();

            //记录异常信息

            log4net.ILog log = (log4net.ILog)log4net.LogManager.GetLogger("LogToSqlite");

            log.Error(ex.Message, ex);

            //清空异常信息

            Server.ClearError();

        }

    }

这样在页面中就可以进行异常捕获及记录了。具体的代码可以下载查看。

下载地址:点我下载

作者:kyo-yo
出处:http://kyo-yo.cnblogs.com 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

时间: 2024-10-04 17:14:15

转:使用log4net完成程序异常日志记录(使用SQLite数据库记录和普通文本记录)的相关文章

在Android程序中使用已有的SQLite数据库

已经将这篇文章迁移至 Code问答,你也能够到这里查看这篇文章,请多多关注我的新技术博客CodeWenDa.com 在中文搜索中,没有找到一篇比較好的关于怎样在Android应用中使用自己事先创建好的数据库的文章,于是在谷歌上找到这篇英文文章,依照它的步骤,測试成功.决定把这篇文章大致的翻译一下,想看原文的能够点击这里:http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/ .

hibernate连接mysql,查询条件中有中文时,查询结果没有记录,而数据库有符合条件的记录(解决方法)

今天在另一台服务器上重新部署了网站,结果出现了以下问题: ——用hibernate做mysql的数据库连接时,当查询条件中有中文的时候,查询结果没有记录,而数据库中是存在符合条件的记录的. 测试了以下,发现不加条件查询可以查到,加上查询条件包含中文就无法找到记录. 百度发现,以下两篇文章很有帮助. http://gzxabcdefg.blog.163.com/blog/static/23451794201081554816892/ http://bbs.51cto.com/thread-1031

Android程序员必掌握的sqlite数据库连表查询

SQL查询的基本原理:两种情况介绍. 第一.   单表查询:根据WHERE条件过滤表中的记录,形成中间表(这个中间表对用户是不可见的):然后根据SELECT的选择列选择相应的列进行返回最终结果. 第二.   两表连接查询:对两表求积(笛卡尔积)并用ON条件和连接连接类型进行过滤形成中间表:然后根据WHERE条件过滤中间表的记录,并根据SELECT指定的列返回查询结果. 第三.   多表连接查询:先对第一个和第二个表按照两表连接做查询,然后用查询结果和第三个表做连接查询,以此类推,直到所有的表都连

Android程序猿必掌握的sqlite数据库连表查询

SQL查询的基本原理:两种情况介绍. 第一.   单表查询:依据WHERE条件过滤表中的记录,形成中间表(这个中间表对用户是不可见的):然后依据SELECT的选择列选择对应的列进行返回终于结果. 第二.   两表连接查询:对两表求积(笛卡尔积)并用ON条件和连接连接类型进行过滤形成中间表:然后依据WHERE条件过滤中间表的记录,并依据SELECT指定的列返回查询结果. 第三.   多表连接查询:先对第一个和第二个表依照两表连接做查询,然后用查询结果和第三个表做连接查询,以此类推,直到全部的表都连

Log4Net异常日志记录在asp.net mvc3.0的应用

前言 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.本文主要是简单的介绍如何在Visual Studio2010(Asp.Net Mvc3.0)中使用log4net快速创建系统日志,如何扩展以输出自定义字段. 用户可以从http://logging.apache.org/log4net/下载log4net的源代码.解压软件包后,在解压的src目录下将log4net.sln载入Visual

redis队列结合log4net实现异常日志记录

查看了一些关于mvc异常日志记录的文章,发现使用redis+log4net的最多,这里简单总结了使用这种方式实现日志记录的过程.直接上步骤: 第一步:配置redis服务器 参考redis的配置和在.net中的使用 第二步:添加自己的异常过滤器(Models文件夹添加一个MyExceptionAttribute类) 1 public class MyExceptionAttribute : HandleErrorAttribute 2 { 3 //----所有用户出现异常,向同一个静态队列添加数据

ASP.NET全局错误处理和异常日志记录以及IIS配置自定义错误页面

应用场景和使用目的 很多时候,我们在访问页面的时候,由于程序异常.系统崩溃会导致出现黄页.在通常的情况下,黄页对于我们来说,帮助是极大的,因为它可以帮助我们知道问题根源,甚至是哪一行代码出现了错误.但这对于用户是非常可怕的,因为用户不知道发生了什么,也无法了解黄页给出的内容.甚至,如果我们遇到一些不友好的人,他们会拿这些内容大做文章,对我们网站产生威胁. 那我们如何在程序异常.系统崩溃时,不会出现黄页,并且还可以给出一些更加友好的提示呢?甚至在我们需要的时候,可以收集这些异常信息,并加以分析,能

使用log4net无法将日志记录插入mysql数据库解决办法

写在前面 今天没事研究了下,将日志文件写入mysql数据库,因为新公司用的数据库也是mysql,项目中需要将日志信息写入数据库,没办法,就研究了下.在使用过程中遇到一个很蛋疼的问题.最后解决了,郁闷了半天.这里做一下记录,以免再犯. 之前写个这方面的文章,关于配置信息,可参考我的这篇文章:Log4Net日志记录两种方式 解决办法 问题就出在我直接将log4net写入数据库的配置文件log4net.config直接复制过来在项目中使用了,当然是修改了连接字符串,提供程序等与mysql相关的配置.配

IOS异常日志记录与展现功能

在平常的APP开发过程中经常碰到程序遇到异常闪退的问题,通过日志可以把相关的详细错误信息进行记录,本实例要记录不管在哪个页面出错都要进行记录,这边使用到的日志记录插件CocoaLumberjack,以文本的形式记录错误信息,然后再去读取各个文本的内容进行展示:当然现在有很多第三方的插件比如友盟也已经集成错误记录的功能: 效果图如下: 1:封装DDLogger的类 MyFileLogger.h文件 #import <Foundation/Foundation.h> #import <Coc