也用 Log4Net 之将日志记录到数据库的后台实现 (二)
也用 Log4Net 之将日志记录到数据库的后台实现 (二)
大家下午好,昨天讲了配置,今天我们讲讲后台实现,在完成了后台实现后,我们才能真正意义上的解决把自定义属性字段值录入到数据库中。
在开写之前我先着重强调一下,“日志”的概念非常广泛,有错误日志、操作日志、访问日志、事件日志等等。我们并不提倡把所有的日志都记录到数据库,因为这样做没有必要。同时如果日志数据表与业务表同在一个数据库的话,频繁的记录日志的操作会影响性能(Log4Net提供了缓存机制,可以在缓存日志数据达到设定值,比如200条时,Log4Net会批量将数据录入到数据库中。即便是这么好的机制,我还是建议大家一定要分清情况,一般错误日志和事件日志我们采用文件形式记录,相应的操作日志我们可以采用数据库记录)。
“通用日志记录系统” 的重点是通用。能适应各种要求,比如要提供丰富的日志记录形式(如:文件、数据库等等),以及适应不同的业务需求,比如A业务希望记录A1,A2,A3字段,B业务希望记录B1,B2,B3字段。同时还要做到灵活性,能适应业务变更。Log4Net正是这样的一种开源框架,说了这么多,我想表述的是:数据库记录日志的方式并不是唯一的和最好的,大家一定在酌情而定。
好了,言归正传,我们现在开始讲后台的处理代码:
(1)、日志对象,就是在存放日志的载体:
public class LogMessage
{
public int UserID { get; set; }
}
在项目中 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类,我们来看代码:

public class CustomLayout : log4net.Layout.PatternLayout
{
public CustomLayout()
{
this.AddConverter("UserID", typeof(UserIDPatternConverter));
}
}

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

internal sealed class UserIDPatternConverter : PatternLayoutConverter
{
override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
{
LogMessage logMessage = loggingEvent.MessageObject as LogMessage; if (logMessage != null)
writer.Write(logMessage.UserID);
}
}

(3)、对Log4Net的简单封装

public class LogHelper
{
public LogHelper()
{ } public static string LoggerName = string.Empty; private static LogMessage message = null; private static ILog _log; public static ILog log
{
get
{
string path = @"C:\Log4Net.config";
log4net.Config.XmlConfigurator.Configure(new FileInfo(path)); if (_log == null)
{
//从配置文件中读取Logger对象
//WebLogger 里面的配置信息是用来将日志录入到数据库的
//做为扩展 做判断来确定日志的记录形式,数据库也好,txt文档也好,控制台程序也好。
_log = log4net.LogManager.GetLogger(LoggerName); //log4net.LogManager.GetLogger("WebLogger");
}
else
{
if (_log.Logger.Name != LoggerName)
{
_log = log4net.LogManager.GetLogger(LoggerName);
}
} return _log;
}
} /// <summary>
/// 调试
/// </summary>
public static void debug()
{
if (log.IsDebugEnabled)
{
log.Debug(message);
}
} /// <summary>
/// 错误
/// </summary>
public static void error()
{
if (log.IsErrorEnabled)
{
log.Error(message);
}
} /// <summary>
/// 严重错误
/// </summary>
public static void fatal()
{
if (log.IsFatalEnabled)
{
log.Fatal(message);
}
} /// <summary>
/// 记录一般日志
/// </summary>
public static void info( )
{
if (log.IsInfoEnabled)
{
//log.Info("Jerry");
log.Info(message);
}
} /// <summary>
/// 记录警告
/// </summary>
public static void warn()
{
if (log.IsWarnEnabled)
{
log.Warn(message);
}
} /// <summary>
/// 需要写日志的地方调用此方法
/// </summary>
/// <param name="level">自定义级别</param>
public static void SaveMessage(LogMessage logMessage,int level)
{
message = logMessage; switch (level)
{
case 1:
info();
break; case 2:
warn();
break; case 3:
error();
break; case 4:
fatal();
break; default: break;
}
} }

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

这是我从别的网站上找到的图,用来说明一下级别。好了,到此为此,我们就已经把 Log4Net 底层这好了,注意,你可以把上页的这些类都统一写到一个类库中。这样做的好处是,当其它项目要用到日志记录功能的时候,直接引用你类库的 dll 就可以了,是不是很方便。同时这样做也实现了对Log4Net的简单封装,让其它项目组的人更易使用。
重点强调一下,记得在这个类库中引用Log4Net.dll。毕竟我们是要用Log4Net来实现日志记录的,别写了半天都没引用,那就要出问题了。
(4)、好了,让我们在Web展示层中调用他吧! Default.aspx

protected void Page_Load(object sender, EventArgs e)
{
LogHelper.LoggerName = "WebLogger";
LogMessage logMessage = new LogMessage(); logMessage.UserID = 123456;
LogHelper.SaveMessage(logMessage,1);
}

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

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

USE [LogSys]
GO /****** Object: Table [dbo].[Log] Script Date: 08/29/2012 14:56:11 ******/
SET ANSI_NULLS ON
GO SET QUOTED_IDENTIFIER ON
GO SET ANSI_PADDING ON
GO CREATE TABLE [dbo].[Log](
[Id] [int] IDENTITY(1,1) NOT NULL,
[LevelName] [varchar](50) NULL,
[UserID] [int] NULL,
[Message] [varchar](4000) NULL,
[Exception] [varchar](2000) NULL,
[RecordTime] [varchar](50) NULL,
CONSTRAINT [PK_Log_1] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] GO SET ANSI_PADDING OFF
GO

好了,就写到这里,我是百灵,祝大家天天好心情,身体健康。
也用 Log4Net 之将日志记录到数据库的后台实现 (二)的更多相关文章
- Log4Net 之将日志记录到数据库的后台实现 (二)
原文:Log4Net 之将日志记录到数据库的后台实现 (二) 大家下午好,昨天讲了配置,今天我们讲讲后台实现,在完成了后台实现后,我们才能真正意义上的解决把自定义属性字段值录入到数据库中. 在开写之前 ...
- 也用 Log4Net 之将日志记录到数据库的配置 (一)
也用 Log4Net 之将日志记录到数据库的配置 (一) 前段时间我一直想做一个通用一点的日志记录系统,可以便于不同的业务组调用进行日志记录及分析.本来打算着自己下手写一个,后面发现各业务组可能会需 ...
- Log4Net 之将日志记录到数据库的配置 (一)
原文:Log4Net 之将日志记录到数据库的配置 (一) 前段时间我一直想做一个通用一点的日志记录系统,可以便于不同的业务组调用进行日志记录及分析.本来打算着自己下手写一个,后面发现各业务组可能会需要 ...
- java注解日志记录到数据库
1. pom添加依赖包 <!--添加aop依赖--><dependency> <groupId>org.springframework.boot</group ...
- 通过代码配置 Log4net来实现日志记录
通过代码来创建配置文件,优点看起来更为简洁,不过还得看需求吧,之前我博客也写了一篇通过读取不同的配置文件还实现配置不同日志类型. //记录异常日志数据库连接字符串 private const stri ...
- asp.net Web项目中使用Log4Net进行错误日志记录
使用log4net可以很方便地为应用添加日志功能.应用Log4net,开发者可以很精确地控制日志信息的输出,减少了多余信息,提高了日志记录性能.同时,通过外部配置文件,用户可以不用重新编译程序就能 ...
- 使用log4net无法将日志记录插入mysql数据库解决办法
写在前面 今天没事研究了下,将日志文件写入mysql数据库,因为新公司用的数据库也是mysql,项目中需要将日志信息写入数据库,没办法,就研究了下.在使用过程中遇到一个很蛋疼的问题.最后解决了,郁闷了 ...
- Log4Net + Log4Mongo 将日志记录到MongoDb中
实现: 将日志保存在MongoDb中: 自定义日志字段: 日志按照日期拆分集合: 第一部分:将日志保存在MongoDb中 新建控制台程序Log4MongoDemo 通过NuGet安装Log4Net ( ...
- log4j教程 12、日志记录到数据库
log4j API提供 org.apache.log4j.jdbc.JDBCAppender 对象,它能够将日志信息在指定的数据库. JDBCAppender 配置: Property 描述 buff ...
随机推荐
- C++中头文件相互包含与前置声明
一.类嵌套的疑问 C++头文件重复包含实在是一个令人头痛的问题,前一段时间在做一个简单的数据结构演示程序的时候,不只一次的遇到这种问题.假设我们有两个类A和B,分别定义在各自的有文件A.h和B.h中, ...
- 团队软件开发_基于windows下截屏软件关于NABC框架的特点
经过我们小组数次的激烈讨论,就自己的能力和时间而言,我们小组的初步的计划是开发一款基于windows下的截图软件. 关于这个软件的功能,我们初步的想法如下: 1.能在windows下后台运行,有相应的 ...
- wamp设置实现本机IP或者局域网访问 (转)
<Directory /> Options FollowSymLinks AllowOverride None Order deny,allow Allow from all #以前是De ...
- 团体程序设计天梯赛-练习集L1-011. A-B
L1-011. A-B 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 本题要求你计算A-B.不过麻烦的是,A和B都是字符串 — ...
- HZNU1015: 矩阵排序
http://acm.hznu.edu.cn/JudgeOnline/problem.php?id=1015 题意:把矩阵每一行都排序. (以前觉得很难的题目回头看看原来如此简单 ][]; ; i&l ...
- The 7th Zhejiang Provincial Collegiate Programming Contest->Problem B:B - Somali Pirates
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3323 题意:去掉字符串里面的数字然后按输入顺序输出 #include< ...
- PHP5 session 详解
http协议是WEB服务器与客户端(浏览器)相互通信的协议,它是一种无状态协议.所谓无状态,指的是不会维护http请求数据,http请求是独立的,非持久的.而越来越复杂的WEB应用,需要保存一些用户状 ...
- Navicat for mysql 远程连接 mySql数据库10061、1045错误问题 (转)
远程使用Navicat for mysql 客户端软件连接 mySql数据时,连接出现 2003-Can’t connect to MySQL on ’192.168.1.2’(10061)错误时,是 ...
- AppStore 沙箱环境的测试流程
1:请确保你打得版本是 沙箱环境的版本 2:请确保的手机序列号已经加入沙箱环境3:请确保你的手机Apple ID 账户已经退出 ------ 如果这些都准备好了,再进行测试吧,不然一堆的未知问题等着你 ...
- PHP基础语法2
数组 PHP有两种数组:索引数组.关联数组. 函数 自定义函数 自定义函数通过将一组代码封装起来,使代码进行复用,程序结构与逻辑更加清晰 返回值 使用return关键字可以使函数返回值,可以返回包括数 ...