原文:Log4Net 之将日志记录到数据库的后台实现 (二)

大家下午好,昨天讲了配置,今天我们讲讲后台实现,在完成了后台实现后,我们才能真正意义上的解决把自定义属性字段值录入到数据库中。

  在开写之前我先着重强调一下,“日志”的概念非常广泛,有错误日志、操作日志、访问日志、事件日志等等。我们并不提倡把所有的日志都记录到数据库,因为这样做没有必要。同时如果日志数据表与业务表同在一个数据库的话,频繁的记录日志的操作会影响性能(Log4Net提供了缓存机制,可以在缓存日志数据达到设定值,比如200条时,Log4Net会批量将数据录入到数据库中。即便是这么好的机制,我还是建议大家一定要分清情况,一般错误日志和事件日志我们采用文件形式记录,相应的操作日志我们可以采用数据库记录)。

  “通用日志记录系统” 的重点是通用。能适应各种要求,比如要提供丰富的日志记录形式(如:文件、数据库等等),以及适应不同的业务需求,比如A业务希望记录A1,A2,A3字段,B业务希望记录B1,B2,B3字段。同时还要做到灵活性,能适应业务变更。Log4Net正是这样的一种开源框架,说了这么多,我想表述的是:数据库记录日志的方式并不是唯一的和最好的,大家一定在酌情而定。

  好了,言归正传,我们现在开始讲后台的处理代码:

  (1)、日志对象,就是在存放日志的载体:

  1. public class LogMessage
  2. {
  3. public int UserID { get; set; }
  4. }

  

  在项目中 LogMessage 充当日志对象,大家一定很奇怪,为什么我的只有一个属性UserID。原因是我在测试自定义属性能不能记录到日志数据库中,所以弄太多的属性也没必要。

  Log4Net在将日志记录到数据库时会提供一些缺省的属性,他们分别是:

[Id] [int] IDENTITY (1, 1) NOT NULL,       
[Date] [datetime]  NULL,        --异常记录时间
[Thread] [varchar] (255)  NULL, --线程ID(数字)
[Level] [varchar] (50)  NULL,   --日志级别(FALAT,ERROR,WARN,INFO,DEBUG)
[Logger] [varchar] (255)  NULL,  --记录的类
[Message] [varchar] (4000) NULL,   --消息

  这些缺省值我们最好在每个日志表里都加上,我测试的时候自行把 Message给删除了,结果怎么也记录不进去日志。所以我建议大家把这几个都带了。字段名字你可以自己改,比如,我就把Date改成了RecordTime,但是在配置文件中,RecordTime字段对应的值依然是@log_date,忘记了的同学回上一篇中去看配置去。

  

  (2)、CustomLayout 类

  CustomLayout 类继承至 log4net.Layout.PatternLayout

  关于Layout大家应该不陌生,“Layout 组件用于向用户显示最后经过格式化的输出信息。输出信息可以以多种格式显示,主要依赖于我们采用的Layout组件类型。可以是线性的或一个XML文件。Layout组件和一个Appender组件一起工作。API帮助手册中有关于不同Layout组件的列表。一个Appender对象,只能对应一个Layout对象。要实现你自己的Layout类,你需要从log4net.Layout.LayoutSkeleton类继承,它实现了ILayout接口。”

  因为我们要使用自定义属性UserID,所以我们要实现自己的Layout类,我们来看代码:

  1. public class CustomLayout : log4net.Layout.PatternLayout
  2. {
  3. public CustomLayout()
  4. {
  5. this.AddConverter("UserID", typeof(UserIDPatternConverter));
  6. }
  7. }

  typeof(UserIDPatternConverter)语句中的UserIDPatternConverter实现了格式化的输出信息。

  1. internal sealed class UserIDPatternConverter : PatternLayoutConverter
  2. {
  3. override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
  4. {
  5. LogMessage logMessage = loggingEvent.MessageObject as LogMessage;
  6.  
  7. if (logMessage != null)
  8. writer.Write(logMessage.UserID);
  9. }
  10. }

  (3)、对Log4Net的简单封装

  1.    public class LogHelper
  2. {
  3. public LogHelper()
  4. {
  5.  
  6. }
  7.  
  8. public static string LoggerName = string.Empty;
  9.  
  10. private static LogMessage message = null;
  11.  
  12. private static ILog _log;
  13.  
  14. public static ILog log
  15. {
  16. get
  17. {
  18. string path = @"C:\Log4Net.config";
  19. log4net.Config.XmlConfigurator.Configure(new FileInfo(path));
  20.  
  21. if (_log == null)
  22. {
  23. //从配置文件中读取Logger对象
  24. //WebLogger 里面的配置信息是用来将日志录入到数据库的
  25. //做为扩展 做判断来确定日志的记录形式,数据库也好,txt文档也好,控制台程序也好。
  26. _log = log4net.LogManager.GetLogger(LoggerName); //log4net.LogManager.GetLogger("WebLogger");
  27. }
  28. else
  29. {
  30. if (_log.Logger.Name != LoggerName)
  31. {
  32. _log = log4net.LogManager.GetLogger(LoggerName);
  33. }
  34. }
  35.  
  36. return _log;
  37. }
  38. }
  39.  
  40. /// <summary>
  41. /// 调试
  42. /// </summary>
  43. public static void debug()
  44. {
  45. if (log.IsDebugEnabled)
  46. {
  47. log.Debug(message);
  48. }
  49. }
  50.  
  51. /// <summary>
  52. /// 错误
  53. /// </summary>
  54. public static void error()
  55. {
  56. if (log.IsErrorEnabled)
  57. {
  58. log.Error(message);
  59. }
  60. }
  61.  
  62. /// <summary>
  63. /// 严重错误
  64. /// </summary>
  65. public static void fatal()
  66. {
  67. if (log.IsFatalEnabled)
  68. {
  69. log.Fatal(message);
  70. }
  71. }
  72.  
  73. /// <summary>
  74. /// 记录一般日志
  75. /// </summary>
  76. public static void info( )
  77. {
  78. if (log.IsInfoEnabled)
  79. {
  80. //log.Info("Jerry");
  81. log.Info(message);
  82. }
  83. }
  84.  
  85. /// <summary>
  86. /// 记录警告
  87. /// </summary>
  88. public static void warn()
  89. {
  90. if (log.IsWarnEnabled)
  91. {
  92. log.Warn(message);
  93. }
  94. }
  95.  
  96. /// <summary>
  97. /// 需要写日志的地方调用此方法
  98. /// </summary>
  99. /// <param name="level">自定义级别</param>
  100. public static void SaveMessage(LogMessage logMessage,int level)
  101. {
  102. message = logMessage;
  103.  
  104. switch (level)
  105. {
  106. case 1:
  107. info();
  108. break;
  109.  
  110. case 2:
  111. warn();
  112. break;
  113.  
  114. case 3:
  115. error();
  116. break;
  117.  
  118. case 4:
  119. fatal();
  120. break;
  121.  
  122. default: break;
  123. }
  124. }
  125.  
  126. }

  Log4Net根据不同的日志级别提供了不同的记录方法,对了,这里所说的日志级别就是对应的 Level 字段,我们来看一下 Log4Net的日志级别:

  这是我从别的网站上找到的图,用来说明一下级别。好了,到此为此,我们就已经把 Log4Net 底层这好了,注意,你可以把上页的这些类都统一写到一个类库中。这样做的好处是,当其它项目要用到日志记录功能的时候,直接引用你类库的 dll 就可以了,是不是很方便。同时这样做也实现了对Log4Net的简单封装,让其它项目组的人更易使用。

  重点强调一下,记得在这个类库中引用Log4Net.dll。毕竟我们是要用Log4Net来实现日志记录的,别写了半天都没引用,那就要出问题了。

  (4)、好了,让我们在Web展示层中调用他吧! Default.aspx

  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. LogHelper.LoggerName = "WebLogger";
  4. LogMessage logMessage = new LogMessage();
  5.  
  6. logMessage.UserID = 123456;
  7. LogHelper.SaveMessage(logMessage,1);
  8. }

  因为我们在配置文件中设定了缓存数,<bufferSize value="10"/> 所以你刷新十下,这时候数据就进入到数据库了。不过聪明的做法是,将bufferSize 的value值改为1

  (5)、数据库中的信息

  (6)、对不起,刚才自己看的时候发现没有建表的Sql语句,现在补上。

  1. USE [LogSys]
  2. GO
  3.  
  4. /****** Object: Table [dbo].[Log] Script Date: 08/29/2012 14:56:11 ******/
  5. SET ANSI_NULLS ON
  6. GO
  7.  
  8. SET QUOTED_IDENTIFIER ON
  9. GO
  10.  
  11. SET ANSI_PADDING ON
  12. GO
  13.  
  14. CREATE TABLE [dbo].[Log](
  15. [Id] [int] IDENTITY(1,1) NOT NULL,
  16. [LevelName] [varchar](50) NULL,
  17. [UserID] [int] NULL,
  18. [Message] [varchar](4000) NULL,
  19. [Exception] [varchar](2000) NULL,
  20. [RecordTime] [varchar](50) NULL,
  21. CONSTRAINT [PK_Log_1] PRIMARY KEY CLUSTERED
  22. (
  23. [Id] ASC
  24. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  25. ) ON [PRIMARY]
  26.  
  27. GO
  28.  
  29. SET ANSI_PADDING OFF
  30. GO

Log4Net 之将日志记录到数据库的后台实现 (二)的更多相关文章

  1. 也用 Log4Net 之将日志记录到数据库的后台实现 (二)

    也用 Log4Net 之将日志记录到数据库的后台实现 (二)  大家下午好,昨天讲了配置,今天我们讲讲后台实现,在完成了后台实现后,我们才能真正意义上的解决把自定义属性字段值录入到数据库中. 在开写之 ...

  2. 也用 Log4Net 之将日志记录到数据库的配置 (一)

    也用 Log4Net  之将日志记录到数据库的配置 (一) 前段时间我一直想做一个通用一点的日志记录系统,可以便于不同的业务组调用进行日志记录及分析.本来打算着自己下手写一个,后面发现各业务组可能会需 ...

  3. Log4Net 之将日志记录到数据库的配置 (一)

    原文:Log4Net 之将日志记录到数据库的配置 (一) 前段时间我一直想做一个通用一点的日志记录系统,可以便于不同的业务组调用进行日志记录及分析.本来打算着自己下手写一个,后面发现各业务组可能会需要 ...

  4. java注解日志记录到数据库

    1. pom添加依赖包 <!--添加aop依赖--><dependency> <groupId>org.springframework.boot</group ...

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

    写在前面 今天没事研究了下,将日志文件写入mysql数据库,因为新公司用的数据库也是mysql,项目中需要将日志信息写入数据库,没办法,就研究了下.在使用过程中遇到一个很蛋疼的问题.最后解决了,郁闷了 ...

  6. 通过代码配置 Log4net来实现日志记录

    通过代码来创建配置文件,优点看起来更为简洁,不过还得看需求吧,之前我博客也写了一篇通过读取不同的配置文件还实现配置不同日志类型. //记录异常日志数据库连接字符串 private const stri ...

  7. asp.net Web项目中使用Log4Net进行错误日志记录

      使用log4net可以很方便地为应用添加日志功能.应用Log4net,开发者可以很精确地控制日志信息的输出,减少了多余信息,提高了日志记录性能.同时,通过外部配置文件,用户可以不用重新编译程序就能 ...

  8. log4j教程 12、日志记录到数据库

    log4j API提供 org.apache.log4j.jdbc.JDBCAppender 对象,它能够将日志信息在指定的数据库. JDBCAppender 配置: Property 描述 buff ...

  9. Log4Net + Log4Mongo 将日志记录到MongoDb中

    实现: 将日志保存在MongoDb中: 自定义日志字段: 日志按照日期拆分集合: 第一部分:将日志保存在MongoDb中 新建控制台程序Log4MongoDemo 通过NuGet安装Log4Net ( ...

随机推荐

  1. 【leetcode】1138. Alphabet Board Path

    题目如下: On an alphabet board, we start at position (0, 0), corresponding to character board[0][0]. Her ...

  2. Day_03-函数和模块的使用

    使用函数求阶乘 使用while循环的代码: m = float(input('m = ')) n = float(input('n = ')) mn = m - n fm = 1 while m != ...

  3. layui jquery ajax,url,type,async,dataType,data

    $.ajax({ url: '/foensys/user/userDelete/'+data[0].id, type:"get", async:true, dataType:&qu ...

  4. mysql FOREIGN KEY约束 语法

    mysql FOREIGN KEY约束 语法 作用:一个表中的 FOREIGN KEY 指向另一个表中的 PRIMARY KEY. DD马达 说明:FOREIGN KEY 约束用于预防破坏表之间连接的 ...

  5. ASP.net 能写一个上传整个文件夹的东东

    IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头. 一. 两个必要响应头Accept-Ranges.ETag 客户端每次提交下载请求时,服务 ...

  6. BZOJ 1304: [CQOI2009]叶子的染色 树形DP + 结论

    Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) # ...

  7. POJ 2229 sumset ( 完全背包 || 规律递推DP )

    题意 : 给出一个数 n ,问如果使用 2 的幂的和来组成这个数 n 有多少种不同的方案? 分析 :  完全背包解法 将问题抽象==>有重量分别为 2^0.2^1.2^2…2^k 的物品且每种物 ...

  8. Internet History, Technology, and Security(week4)——History: Commercialization and Growth

    Explosive Growth of the Internet and Web: The Year of the Web 1994年后,由NCSA的老员工们构成的Netscape(网景)的成立.Ne ...

  9. 通过Hadoop jmx收集Namenode,Jobtracker相关信息

    经常会有一些Hadoop监控的需求,例如datanode节点掉线,Tasktracker blacklist的数量,以及Namenode,Jobtracker的内存GC信息等. 之前采用Hadoop ...

  10. ceph-pve英语

    adapted accordingly并相应地调整 silosn. 筒仓:粮仓:贮仓(silo的复数) saturatevt. 浸透,使湿透:使饱和,使充满While one HDD might no ...