分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 技术分享

(转)非常完善的Log4net详细说明

发布时间:2023-09-06 01:10责任编辑:苏小强关键词:暂无标签

1、概述

log4net是.Net下一个非常优秀的开源日志记录组件。log4net记录日志的功能非常强大。它可以将日志分不同的等级,以不同的格式,输出到不同的媒介。本文主要是介绍如何在Visual Studio2008中使用log4net快速创建系统日志,如何扩展以输出自定义字段。

2、一个简单的使用实例

第一步:在项目中添加对log4net.dll的引用,这里引用版本是1.2.10.0。

第二步:程序启动时读取log4net的配置文件。

如果是CS程序,在根目录的Program.cs中的Main方法中添加:

log4net.Config.XmlConfigurator.Configure();

如果是BS程序,在根目录的Global.asax.cs(没有新建一个)中的Application_Start方法中添加:

log4net.Config.XmlConfigurator.Configure();

无论BS还是CS程序都可直接在项目的AssemblyInfo.cs文件里添加以下的语句:

[assembly: log4net.Config .XmlConfigurator()]

也可以使用自定义的配置文件,具体请参见4.4关联配置文件。

第三步:修改配置文件。如果是CS程序,则在默认的App.config文件(没有新建一个)中添加内容;如果是BS程序,则添加到Web.config文件中,添加内容一样,这里不再列出。

App.config文件添加内容如下:

<?xmlversion="1.0"encoding="utf-8"?>

<configuration>

<configSections>

<sectionname="log4net"

type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>

</configSections>

<log4net>

<root>

<levelvalue="WARN"/>

<appender-refref="LogFileAppender"/>

<appender-refref="ConsoleAppender"/>

</root>

<loggername="testApp.Logging">

<levelvalue="DEBUG"/>

</logger>

<appendername="LogFileAppender"type="log4net.Appender.FileAppender">

<paramname="File"value="log-file.txt"/>

<paramname="AppendToFile"value="true"/>

<layouttype="log4net.Layout.PatternLayout">

<paramname="Header"value="[Header]"/>

<paramname="Footer"value="[Footer]"/>

<paramname="ConversionPattern"value="%d [%t] %-5p %c [%x]- %m%n"/>

</layout>

<filtertype="log4net.Filter.LevelRangeFilter">

<paramname="LevelMin"value="DEBUG"/>

<paramname="LevelMax"value="WARN"/>

</filter>

</appender>

<appendername="ConsoleAppender"type="log4net.Appender.ConsoleAppender">

<layouttype="log4net.Layout.PatternLayout">

<paramname="ConversionPattern"value="%d [%t] %-5p %c [%x] - %m%n"/>

</layout>

</appender>

</log4net>

</configuration>

第四步:在程序使用。

log4net.ILoglog = log4net.LogManager.GetLogger("testApp.Logging");//获取一个日志记录器

log.Info(DateTime.Now.ToString() +": login success");//写入一条新log

这样就将信息同时输出到控制台和写入到文件名为“log-file.txt”的文件中,其中“log-file.txt”文件的路径是当前程序运行所在目录;也可以定义为绝对路径,配置如:

<paramname="File"value="C:/log-file.txt"/>就写入C盘根目录下log-file.txt文件中,具体使用技巧参见4.2.1。

本例的实现请参见8.6附件。

3、Log4net的主要组成部分

3.1 Appenders

Appenders用来定义日志的输出方式,即日志要写到那种介质上去。较常用的Log4net已经实现好了,直接在配置文件中调用即可,可参见上面配置文件例子;当然也可以自己写一个,需要从log4net.Appender.AppenderSkeleton类继承。它还可以通过配置Filters和Layout来实现日志的过滤和输出格式。

已经实现的输出方式有:

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

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

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

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

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

EventLogAppender将日志写到WindowsEventLog。

FileAppender将日志输出到文件。

ForwardingAppender发送日志事件到子Appenders。

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

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

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

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

RemoteSyslogAppender通过UDP网络协议将日志写到Remotesyslogservice。

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

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

SmtpAppender将日志写到邮件中。

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

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

TraceAppender将日志写到.NETtrace系统。

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

3.2 Filters

使用过滤器可以过滤掉Appender输出的内容。过滤器通常有以下几种:

DenyAllFilter阻止所有的日志事件被记录

LevelMatchFilter只有指定等级的日志事件才被记录

LevelRangeFilter日志等级在指定范围内的事件才被记录

LoggerMatchFilter与Logger名称匹配,才记录

PropertyFilter消息匹配指定的属性值时才被记录

StringMathFilter消息匹配指定的字符串才被记录

3.3 Layouts

Layout用于控制Appender的输出格式,可以是线性的也可以是XML。

一个Appender只能有一个Layout。

最常用的Layout应该是经典格式的PatternLayout,其次是SimpleLayout,RawTimeStampLayout和ExceptionLayout。然后还有IRawLayout,XMLLayout等几个,使用较少。Layout可以自己实现,需要从log4net.Layout.LayoutSkeleton类继承,来输出一些特殊需要的格式,在后面扩展时就重新实现了一个Layout。

SimpleLayout简单输出格式,只输出日志级别与消息内容。

RawTimeStampLayout用来格式化时间,在向数据库输出时会用到。

样式如“yyyy-MM-dd HH:mm:ss“

ExceptionLayout需要给Logger的方法传入Exception对象作为参数才起作用,否则就什么也不输出。输出的时候会包含Message和Trace。

PatterLayout使用最多的一个Layout,能输出的信息很多,使用方式可参见上面例子中的配置文件。PatterLayout的格式化字符串见文后附注8.1。

3.4 Loggers

Logger是直接和应用程序交互的组件。Logger只是产生日志,然后由它引用的Appender记录到指定的媒介,并由Layout控制输出格式。

Logger提供了多种方式来记录一个日志消息,也可以有多个Logger同时存在。每个实例化的Logger对象对被log4net作为命名实体(Named Entity)来维护。log4net使用继承体系,也就是说假如存在两个Logger,名字分别为a.b.c和a.b。那么a.b就是a.b.c的祖先。每个Logger都继承了它祖先的属性。所有的Logger都从Root继承,Root本身也是一个Logger。

日志的等级,它们由高到底分别为:

OFF>FATAL>ERROR>WARN>INFO>DEBUG >ALL

高于等级设定值方法(如何设置参见“配置文件详解”)都能写入日志,Off所有的写入方法都不写到日志里,ALL则相反。例如当我们设成Info时,logger.Debug就会被忽略而不写入文件,但是FATAL,ERROR,WARN,INFO会被写入,因为他们等级高于INFO。

在具体写日志时,一般可以这样理解日志等级:

FATAL(致命错误):记录系统中出现的能使用系统完全失去功能,服务停止,系统崩溃等使系统无法继续运行下去的错误。例如,数据库无法连接,系统出现死循环。

ERROR(一般错误):记录系统中出现的导致系统不稳定,部分功能出现混乱或部分功能失效一类的错误。例如,数据字段为空,数据操作不可完成,操作出现异常等。

WARN(警告):记录系统中不影响系统继续运行,但不符合系统运行正常条件,有可能引起系统错误的信息。例如,记录内容为空,数据内容不正确等。

INFO(一般信息):记录系统运行中应该让用户知道的基本信息。例如,服务开始运行,功能已经开户等。

DEBUG(调试信息):记录系统用于调试的一切信息,内容或者是一些关键数据内容的输出。

Logger实现的ILog接口,ILog定义了5个方法(Debug,Inof,Warn,Error,Fatal)分别对不同的日志等级记录日志。这5个方法还有5个重载。以Debug为例说明一下,其它的和它差不多。

ILog中对Debug方法的定义如下:

voidDebug(objectmessage);

voidDebug(objectmessage,Exceptionex);

还有一个布尔属性:

boolIsDebugEnabled {get; }

如果使用Debug(objectmessage,Exceptionex),则无论Layout中是否定义了%exception,默认配置下日志都会输出Exception。包括Exception的Message和Trace。如果使用Debug(object message),则日志是不会输出Exception。

最后还要说一个LogManager类,它用来管理所有的Logger。它的GetLogger静态方法,可以获得配置文件中相应的Logger:

log4net.ILoglog = log4net.LogManager.GetLogger("logger-name");

3.5 Object Renders

它将告诉logger如何把一个对象转化为一个字符串记录到日志里。(ILog中定义的接口接收的参数是Object,而不是String。)

例如你想把Orange对象记录到日志中,但此时logger只会调用Orange默认的ToString方法而已。所以要定义一个OrangeRender类实现log4net.ObjectRender.IObjectRender接口,然后注册它(我们在本文中的扩展不使用这种方法,而是直接实现一个自定义的Layout)。这时logger就会知道如何把Orange记录到日志中了。

3.6 Repository

Repository主要用于日志对象组织结构的维护。

4、配置文件详解

4.1配置文件构成

主要有两大部分,一是申明一个名为“log4net“的自定义配置节,如下所示:

<configSections>

<sectionname="log4net"

type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>

</configSections>

二是<log4net>节的具体配置,这是下面要重点说明的。

4.1.1<log4net>

所有的配置都要在<log4net>元素里定义。

支持的属性:

debug

可选,取值是true或false,默认是false。设置为true,开启log4net的内部调试。

update

可选,取值是Merge(合并)或Overwrite(覆盖),默认值是Merge。设置为Overwrite,在提交配置的时候会重置已经配置过的库。

threshold

可选,取值是repository(库)中注册的level,默认值是ALL。

支持的子元素:

appender

0或多个

logger

0或多个

renderer

0或多个

root

最多一个

param

0或多个

4.1.2<root>

实际上就是一个根logger,所有其它logger都默认继承它,如果配置文件里没有显式定义,则框架使用根日志中定义的属性。root元素没有属性。

支持的子元素:

appender-ref

0个或多个,要引用的appender的名字。

level

最多一个。只有在这个级别或之上的事件才会被记录。

param

0个或多个,设置一些参数。

4.1.3<logger>

支持的属性:

name

必须的,logger的名称

additivity

可选,取值是true或false,默认值是true。设置为false时将阻止父logger中的appender。

支持的子元素:

appender-ref

0个或多个,要引用的appender的名字。

level

最多一个。只有在这个级别或之上的事件才会被记录。

param

0个或多个,设置一些参数。

4.1.4<appender>

定义日志的输出方式,只能作为log4net的子元素。name属性必须唯一,type属性必须指定。

支持的属性:

name

必须的,Appender对象的名称

type

必须的,Appender对象的输出类型

支持的子元素:

appender-ref

0个或多个,允许此appender引用其他appender,并不是所以appender类型都支持。

filter

0个或多个,定义此app使用的过滤器。

layout

最多一个。定义appender使用的输出格式。

param

0个或多个,设置Appender类中对应的属性的值。

实际上<appender>所能包含的子元素远不止上面4个。

4.1.5<layout>

布局,只能作为<appender>的子元素。

支持的属性:

type

必须的,Layout的类型

支持的子元素:

param

0个或多个,设置一些参数。

4.1.6<filter>

过滤器,只能作为<appender>的子元素。

支持的属性:

type

必须的,Filter的类型

支持的子元素:

param

0个或多个,设置一些参数。

4.1.7<param>

<param>元素可以是任何元素的子元素。

支持的属性:

name

必须的,取值是父对象的参数名。

value

可选的,value和type中,必须有一个属性被指定。value是一个能被转化为参数值的字符串。

type

可选的,value和type中,必须有一个属性被指定。type是一个类型名,如果type不是在log4net程序集中定义的,就需要使用全名。

支持的子元素:

param

0个或多个,设置一些参数。

4.2 <appender>配置

<appender>在配置文件中至少有一个,也可以有多个,有些<appender>类型还可以引用其他<appender>类型,具体参数可参见上表。

下面只对写入回滚文件与输出到数据库(这里使用SQL数据库)配置体会说一下,其他配置可参考官方网站:http://logging.apache.org/log4net/release/config-examples.html

4.2.1写入回滚文件

<appendername="ReflectionLayout"type="log4net.Appender.RollingFileAppender,log4net">

<!--日志文件路径,“/”与“/”作用相同,到达的目录相同,文件夹不存在则新建-->

<!--按文件大小方式输出时在这里指定文件名,并且当天的日志在下一天时在文件名后自动追加当天日期形成新文件。-->

<!—按照日期形式输出时,直接连接元素DatePattern的value形成文件路径。此处使用这种方式-->

<!--param的名称,可以直接查对应的appender类的属性名即可,这里要查的就是RollingFileAppender类的属性-->

<paramname="File"value="D:/Log/"/>

<!--是否追加到文件-->

<paramname="AppendToFile"value="true"/>

<!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->

<lockingModeltype="log4net.Appender.FileAppender+MinimalLock"/>

<!—使用Unicode编码-->

<Encodingvalue="UTF-8"/>

<!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->

<paramname="MaxSizeRollBackups"value="10"/>

<!--是否只写到一个文件中-->

<paramname="StaticLogFileName"value="false"/>

<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->

<paramname="RollingStyle"value="Composite"/>

<!--按日期产生文件夹和文件名[在日期方式与混合方式下使用]-->

<!—此处按日期产生文件夹,文件名固定。注意&quot;的位置-->

<paramname="DatePattern"value="yyyy-MM-dd/&quot;ReflectionLayout.log&quot;"/>

<!—这是按日期产生文件夹,并在文件名前也加上日期-->

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

<!—这是先按日期产生文件夹,再形成下一级固定的文件夹—>

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

<!--每个文件的大小。只在混合方式与文件大小方式下使用。

超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。

可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志-->

<paramname="maximumFileSize"value="500KB"/>

<!--计数类型为1,2,3…-->
<paramname="CountDirection"value="1"/>

<!—过滤设置,LevelRangeFilter为使用的过滤器。-->

<filtertype="log4net.Filter.LevelRangeFilter">

<paramname="LevelMin"value="DEBUG"/>

<paramname="LevelMax"value="WARN"/>

</filter>

<!--记录的格式。一般用log4net.Layout.PatternLayout布局-->

<!—此处用继承了log4net.Layout.PatternLayout的自定义布局,TGLog.ExpandLayout2

为命名空间。%property{Operator}、%property{Action}是自定义的输出-->

<layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

<paramname="ConversionPattern"

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

</layout>

</appender>

注意这些配置属性有些是可选的,如果需要,一定要写正确,否则要么输出的不是自己想要的结果,要么干脆不输出任何信息。

4.2.1写入SQL数据库

需要在相应的数据库中准备好一张表,创建语句如下:

CREATE TABLE [Log] (

[ID] [int] IDENTITY (1, 1) NOT NULL ,

[Date] [datetime] NOT NULL ,

[Thread] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[Level] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[Logger] [varchar] (200) COLLATE Chinese_PRC_CI_AS NULL ,

[Operator] [int] NULL ,

[Message] [text] COLLATE Chinese_PRC_CI_AS NULL ,

[ActionType] [int] NULL ,

[Operand] [varchar] (300) COLLATE Chinese_PRC_CI_AS NULL ,

[IP] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,

[MachineName] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[Browser] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

[Location] [text] COLLATE Chinese_PRC_CI_AS NULL ,

[Exception] [text] COLLATE Chinese_PRC_CI_AS NULL

)

<appendername="ADONetAppender"type="log4net.Appender.ADONetAppender,log4net">

<!--BufferSize为缓冲区大小,只有日志记录超设定值才会一块写入到数据库-->

<bufferSizevalue="10"/><!—或写为<param name="BufferSize" value="10" />-->

<!--引用-->

<connectionTypevalue="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

<!--连接数据库字符串-->

<connectionStringvalue="data source=.;initial catalog=Test;integrated security=false;persist security info=True;User ID=sa;Password=;"/>

<!--插入到表Log-->

<commandTextvalue="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Operator],[Message],[ActionType],[Operand],[IP],[MachineName],[Browser],[Location],[Exception]) VALUES (@log_date, @thread, @log_level, @logger,@operator, @message,@action_type,@operand,@ip,@machineName,@browser,@location,@exception)"/>

<!—日志记录时间,RawTimeStampLayout为默认的时间输出格式-->

<parameter>

<parameterNamevalue="@log_date"/>

<dbTypevalue="DateTime"/>

<layouttype="log4net.Layout.RawTimeStampLayout"/>

</parameter>

<!--线程号-->

<parameter>

<parameterNamevalue="@thread"/>

<dbTypevalue="String"/>

<!—长度不可以省略,否则不会输出-->

<sizevalue="100"/>

<layouttype="log4net.Layout.PatternLayout">

<conversionPatternvalue="%thread"/>

</layout>

</parameter>

<!--日志等级-->

<parameter>

<parameterNamevalue="@log_level"/>

<dbTypevalue="String"/>

<sizevalue="100"/>

<layouttype="log4net.Layout.PatternLayout">

<conversionPatternvalue="%level"/>

</layout>

</parameter>

<!--日志记录类名称-->

<parameter>

<parameterNamevalue="@logger"/>

<dbTypevalue="String"/>

<sizevalue="200"/>

<layouttype="log4net.Layout.PatternLayout">

<conversionPatternvalue="%logger"/>

</layout>

</parameter>

<!--操作者。这个是自定义的输出字段,使用重新实现的布局器ReflectionLayout -->

<parameter>

<parameterNamevalue="@operator"/>

<!—设置为Int32时只有bufferSize的value<="1"才正确输出,没有找出原因。-->

<dbTypevalue="Int16"/>

<layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

<conversionPatternvalue="%property{Operator}"/>

</layout>

</parameter>

<!--操作对象-->

<parameter>

<parameterNamevalue="@operand"/>

<dbTypevalue="String"/>

<sizevalue="300"/>

<layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

<conversionPatternvalue="%property{Operand}"/>

</layout>

</parameter>

<!—IP地址-->

<parameter>

<parameterNamevalue="@ip"/>

<dbTypevalue="String"/>

<sizevalue="20"/>

<layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

<conversionPatternvalue="%property{IP}"/>

</layout>

</parameter>

<!--机器名-->

<parameter>

<parameterNamevalue="@machineName"/>

<dbTypevalue="String"/>

<sizevalue="100"/>

<layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

<conversionPatternvalue="%property{MachineName}"/>

</layout>

</parameter>

<!--浏览器-->

<parameter>

<parameterNamevalue="@browser"/>

<dbTypevalue="String"/>

<sizevalue="50"/>

<layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

<conversionPatternvalue="%property{Browser}"/>

</layout>

</parameter>

<!—日志消息-->

<parameter>

<parameterNamevalue="@message"/>

<dbTypevalue="String"/>

<sizevalue="3000"/>

<layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

<conversionPatternvalue="%property{Message}"/>

</layout>

</parameter>

<!--动作类型-->

<parameter>

<parameterNamevalue="@action_type"/>

<dbTypevalue="Int16"/>

<layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

<conversionPatternvalue="%property{ActionType}"/>

</layout>

</parameter>

<!—记录日志的位置-->

<parameter>

<parameterNamevalue="@location"/>

<dbTypevalue="String"/>

<sizevalue="2000"/>

<layouttype="log4net.Layout.PatternLayout">

<conversionPatternvalue="%location"/>

</layout>

</parameter>

<!—异常信息。ExceptionLayout为异常输出的默认格式-->

<parameter>

<parameterNamevalue="@exception"/>

<dbTypevalue="String"/>

&

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved