log4net架构、配置、使用
架构说明
架构说明
上图是官方文档的提供的代码组织。
Log4net的核心组件有: Logger, Appender, Filter, Layout, Object Render,
Logger介绍
Logger是负责日志的记录者,假设我们需要记录一些正常的运行时日志和出现异常时的错误日志,那么我们可以通过在配置文件当中添加两个Logger实现。Logger主要用于记录日志的分类和控制日志的级别。它可以以多种格式输出日志信息,同时它也可以控制日志的输出级别。
log4net使用继承体系,也就是说假如存在两个Logger,名字分别为a.b.c和a.b。那么a.b就是a.b.c的祖先。每个Logger都继承了它祖先的属性。Log4net 的日志对象管理器LogManager:LogManager是用于来管理所有的Logger对象的,GetLogger() 可以用来查找已经存在的Logger对象,如果对象不存在它会自动创建一个Logger对象,并且管理它 。
Appender介绍
Appender提供记录的介质,可以翻译为附着器,logger记录的所有信息输出到Apender,Appender再输出到控制台,文本文件,windows 日志事件查看器等等。包括数据库,邮件等等位置。具体输出到哪里,我们可以通过Appender配置实现,而且Log4Net当中已经默认提供了一些常用的Appender,我们可以简单地修改一些配置文件就实现同时向数据库和同时向文件中写入的功能。
Log4net定义了多种附着器:
(1) AdoNetAppender 将日志记录到数据库中。可以采用SQL和存储过程两种方式
(2) AnsiColorTerminalAppender 在ANSI 窗口终端写下高亮度的日志事件
(3) AspNetTraceAppender 能用asp.net中Trace的方式查看记录的日志
(4) BufferingForwardingAppender 在输出到子Appenders之前先缓存日志事件
(5) ConsoleAppender 将日志输出到控制台
(6) EventLogAppender 将日志写到Windows Event Log
(7) FileAppender 将日志写到文件中
(8) MemoryAppender 将日志存到内存缓冲区
(9) NetSendAppender 将日志输出到Windows Messenger service.这些日志信息将在用户终端的对话框中显示
(10) RemoteSyslogAppender 通过UDP网络协议将日志写到Remote syslog service
(11) RemotingAppender 通过.NET Remoting将日志写到远程接收端
(12) RollingFileAppender 将日志以回滚文件的形式写到文件中
(13) SmtpAppender 将日志写到邮件中
(14) TraceAppender 将日志写到.NET trace 系统
(15) UdpAppender 将日志connectionless UDP datagrams的形式送到远程宿主或以UdpClient的形式广播
Filter介绍
Filter就是过滤器,使用过滤器可以过滤掉Appender输出的部分内容,只输出感兴趣的日志。
Layout介绍
Layout用于控制Appender的输出格式,可以使线性的也可以使XML。一个Appender只能有一个Layout配置。
Object Render介绍
Object Render将告诉logger如何把一个对象转化为一个字符串记录到日志里。ILog中定义的记录日志的方法接收的参数是Object,而不是String。例如你想把Orange对象记录到日志中,但此时logger只会调用Orange默认的ToString方法而已。所以要定义一个OrangeRender类实现log4net.ObjectRender.IObjectRender接口,然后注册它。这时logger就会知道如何把Orange记录到日志中了。
配置
logger
假设需要配置三个logger,一个负责记录debug信息,一个负责记录软件运行的一些信息,一个负责记录Error信息。
那么配置文件就可以这样写:
<logger name="logDebug">
<level value="DEBUG" />
<appender-ref ref="DebugAppender" />
</logger>
<logger name="loginfo">
<level value="INFO" />
<appender-ref ref="InfoAppender" />
</logger>
<logger name="logError">
<level value="ERROR" />
<appender-ref ref="ErrorAppender" />
</logger>
日志级别
高到底分别为:OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL
上面配置文件中定义了三个logger,每个logger都有一个level标签,指定好标签后就该logger就不会记录小于该级别的信息,比如记录error的ligger就被定义成ERROR,那么他就不会记录WARN 、 INFO 、 DEBUG级别的日志。
appender标签
指定该logger的appender
appender
每个logger都需要配置上appender,来指定该logger记录的日志输出到哪里,可以是控制台、文件、数据库等等。每个日志对象都可以使用多个appender,这样就可以同时使用文件输出和控制台输出。
上面指定了三个logger,那么为这三个logger添加上各自的appender后的配置文件,然后我还定义了一个控制台appender,让所有的信息都输出到控制台:
<logger name="logDebug">
<level value="DEBUG" />
<appender-ref ref="DebugAppender" />
<appender-ref ref="ConsoleAppender"></appender-ref>
</logger>
<appender name="DebugAppender" type="log4net.Appender.RollingFileAppender">
<file value="Log\\LogDebug\\" />
<appendToFile value="true" />
<maxFileSize value="10240" />
<maxSizeRollBackups value="100" />
<staticLogFileName value="false" />
<datePattern value="yyyyMMdd'.txt'" />
<rollingStyle value="Date" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" />
</layout>
</appender>
<logger name="loginfo">
<level value="INFO" />
<appender-ref ref="InfoAppender" />
<appender-ref ref="ConsoleAppender"></appender-ref>
</logger>
<appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
<file value="Log\\LogInfo\\" />
<appendToFile value="true" />
<maxFileSize value="10240" />
<maxSizeRollBackups value="100" />
<staticLogFileName value="false" />
<datePattern value="yyyyMMdd'.txt'" />
<rollingStyle value="Date" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" />
</layout>
</appender>
<logger name="logError">
<level value="ERROR" />
<appender-ref ref="ErrorAppender" />
<appender-ref ref="ConsoleAppender"></appender-ref>
</logger>
<appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
<file value="log\\LogError\\" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd'.txt'" />
<staticLogFileName value="false" />
<param name="MaxSizeRollBackups" value="100" />
<layout type="log4net.Layout.PatternLayout">
<!--每条日志末尾的文字说明-->
<!--输出格式-->
<!--样例:2019-01-28 13:42:32,111 [10] INFO Log4NetDemo.MainClass [(null)] - info-->
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n错误描述:%message%newline %n" />
</layout>
</appender>
<!--输入日志到控制台-->
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[时间]:%d%n[级别]:%p%n[内容]:%m%n%n"></conversionPattern>
</layout>
</appender>
每个appender都有一个name属性和type属性,type说明该appender是什么类型的,可以是(上一节中说过):
(1) AdoNetAppender 将日志记录到数据库中。可以采用SQL和存储过程两种方式
(2) AnsiColorTerminalAppender 在ANSI 窗口终端写下高亮度的日志事件
(3) AspNetTraceAppender 能用asp.net中Trace的方式查看记录的日志
(4) BufferingForwardingAppender 在输出到子Appenders之前先缓存日志事件
(5) ConsoleAppender 将日志输出到控制台
(6) EventLogAppender 将日志写到Windows Event Log
(7) FileAppender 将日志写到文件中
(8) MemoryAppender 将日志存到内存缓冲区
(9) NetSendAppender 将日志输出到Windows Messenger service.这些日志信息将在用户终端的对话框中显示
(10) RemoteSyslogAppender 通过UDP网络协议将日志写到Remote syslog service
(11) RemotingAppender 通过.NET Remoting将日志写到远程接收端
(12) RollingFileAppender 将日志以回滚文件的形式写到文件中
(13) SmtpAppender 将日志写到邮件中
(14) TraceAppender 将日志写到.NET trace 系统
(15) UdpAppender 将日志connectionless UDP datagrams的形式送到远程宿主或以UdpClient的形式广播
上面配置文件中我把Debug、Info、Error全部配置成文件类型。
<file value="log\\LogError\\" />
标签指定文件保存目录
其它节点的说明与配置
(1)param节点
元素可以是如何元素的子元素,包含的属性:name、value、type。name:必须的,取值是父对象的参数名。value:可选的,value是一个能被转化为参数值的字符串。type:可选的,value和type中,必须有一个属性被指定。type是一个类型名,如果type不是在log4net程序集中定义的,就需要使用全名。
param节点的主要作用是可以代替其他任何节点,例如:
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%5p %n"/>
<!--可以使用:<param name="ConversionPattern" value="%5p %n"/>-->
</layout>
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="FATAL"/>
<!--可以使用:<param name="LevelToMatch" value="FATAL"/>-->
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
(2)root节点
root节点的作用是所有其它logger都默认继承它。root元素没有属性。root节点的子元素与logger一样有appender-ref、level、param。
使用示例:
<root xmlns="">
<level value="WARN" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="ConsoleAppender" />
</root>
(3)log4net节点
Log4net节点是整个日志配置的根节点,包含的属性:debug、update、threshold。debug:可选,取值是true或false,默认是false。设置为true,开启log4net的内部调试。update:可选,取值是Merge(合并)或Overwrite(覆盖),默认值是Merge。设置为Overwrite,在提交配置的时候会重置已经配置过的库。threshold:可选,取值是repository(库)中注册的level,默认值是ALL。
Log4net节点支持的子元素:appender(0或多个)、logger (0或多个)、renderer (0或多个)、root(最多一个)、param(0或多个)。
使用
log4net的配置文件可以单独做一个,也可配置到App.config中
我是配置到单独的文件中了,注意我是在.net core2.2下做的,配置文件读取有点与.net framework不一样,具体不贴出来了。
首先创建一个config文件,右键工程,添加config文件,然后把本文下面的配置文件内容添加进去。
注意这里要选择拷贝到生成目录中,要不然容易导致找不到配置文件而无法创建logger。
注意,如果是net core的话,读取配置文件使用ConfigurationManager类,需要从nuget上安装system.configuration.ConfigurationManager。
using log4net;
using log4net.Config;
using log4net.Repository;
using System;
using System.Configuration;
using System.IO;
namespace TestLog4Net
{
class Program
{
static ILog LogDebug = null;
static ILog LogInfo = null;
static ILog LogError = null;
static void Main(string[] args)
{
InitLog4Net();
LogInfo.Info("first log");
Console.WriteLine("Hello World!");
ReadAllSettings();
Console.ReadKey();
}
//初始化log4net,创建logger
static void InitLog4Net()
{
ILoggerRepository repository = LogManager.CreateRepository("NETCoreRepository");
XmlConfigurator.Configure(repository, new FileInfo("log4net.config"));
LogDebug = LogManager.GetLogger(repository.Name, "logDebug");
LogInfo = LogManager.GetLogger(repository.Name, "loginfo");
LogError = LogManager.GetLogger(repository.Name, "logError");
}
static void ReadAllSettings()
{
LogDebug.Debug("logDebug");
LogInfo.Info("loginfo");
LogError.Error("error");
try
{
var appSettings = ConfigurationManager.AppSettings;
if (appSettings.Count == 0)
{
Console.WriteLine("AppSettings is empty.");
}
else
{
foreach (var key in appSettings.AllKeys)
{
Console.WriteLine("Key: {0} Value: {1}", key, appSettings[key]);
}
}
}
catch (ConfigurationErrorsException)
{
Console.WriteLine("Error reading app settings");
}
}
}
}
完整的配置文件:
<?xml version="1.0" encoding="utf-8"?>
<log4net>
<logger name="logDebug">
<level value="DEBUG" />
<appender-ref ref="DebugAppender" />
<appender-ref ref="ConsoleAppender"></appender-ref>
</logger>
<appender name="DebugAppender" type="log4net.Appender.RollingFileAppender">
<file value="Log\\LogDebug\\" />
<appendToFile value="true" />
<maxFileSize value="10240" />
<maxSizeRollBackups value="100" />
<staticLogFileName value="false" />
<datePattern value="yyyyMMdd'.txt'" />
<rollingStyle value="Date" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" />
</layout>
</appender>
<logger name="loginfo">
<level value="INFO" />
<appender-ref ref="InfoAppender" />
<appender-ref ref="ConsoleAppender"></appender-ref>
</logger>
<appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
<file value="Log\\LogInfo\\" />
<appendToFile value="true" />
<maxFileSize value="10240" />
<maxSizeRollBackups value="100" />
<staticLogFileName value="false" />
<datePattern value="yyyyMMdd'.txt'" />
<rollingStyle value="Date" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" />
</layout>
</appender>
<logger name="logError">
<level value="ERROR" />
<appender-ref ref="ErrorAppender" />
<appender-ref ref="ConsoleAppender"></appender-ref>
</logger>
<appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
<file value="log\\LogError\\" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd'.txt'" />
<staticLogFileName value="false" />
<param name="MaxSizeRollBackups" value="100" />
<layout type="log4net.Layout.PatternLayout">
<!--每条日志末尾的文字说明-->
<!--输出格式-->
<!--样例:2019-01-28 13:42:32,111 [10] INFO Log4NetDemo.MainClass [(null)] - info-->
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n错误描述:%message%newline %n" />
</layout>
</appender>
<!--输入日志到控制台-->
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[时间]:%d%n[级别]:%p%n[内容]:%m%n%n"></conversionPattern>
</layout>
</appender>
</log4net>
源代码:https://github.com/feipeng8848/TestLog4Net
参考:
https://www.cnblogs.com/LiZhiW/p/4317198.html
https://www.jianshu.com/p/6c9b26db6d6d
https://segmentfault.com/a/1190000010866959#articleHeader1
https://stackoverrun.com/cn/q/261563
https://yq.aliyun.com/articles/293129/
https://logging.apache.org/log4net/release/sdk/index.html#
https://www.cnblogs.com/linezero/p/log4net.html