(二)Apache log4net™ 手册 - 配置
0、引言
在上一篇文章中我们简单介绍了 Log4Net 及其核心的三大组件。本文将在上一篇文章的基础上继续探讨与 Log4Net 配置相关的内容。
1、配置
将日志请求插入到应用程序代码中需要进行大量的计划和工作。观察表明,大约4%的代码专门用于日志记录。因此,即使是中等规模的应用程序也会在其代码中嵌入数千条日志记录语句。考虑到它们的数量,必须管理这些日志语句,而不需要手动修改它们。
log4net 环境是完全可编程配置的。但是,使用配置文件配置 log4net 要灵活得多。目前,配置文件是用 XML 编写的。
让我们在使用 log4net 的虚拟应用程序 MyApp 的帮助下,体验一下如何实现这一点。
using Com.Foo;// 导入 log4net 类。
using log4net;
using log4net.Config;public class MyApp
{// 定义一个静态 logger 变量,其引用名为 "MyApp" 的 Logger 实例private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));static void Main(string[] args) {// 设置一个简单的配置,在控制台进行日志记录。BasicConfigurator.Configure();log.Info("Entering application.");Bar bar = new Bar();bar.DoIt();log.Info("Exiting application.");}
}
MyApp 首先导入 log4net 相关的类。然后,它定义了一个名为 MyApp 的静态 logger 变量,该变量恰好是类的完全限定名。
MyApp 使用了下面的 Bar 类:
// 导入 log4net 类。
using log4net;namespace Com.Foo
{public class Bar {private static readonly ILog log = LogManager.GetLogger(typeof(Bar));public void DoIt(){log.Debug("Did it again!");}}
}
调用 BasicConfigurator.Configure()
方法创建一个相当简单的 log4net 设置。这个方法被硬编码为向 root
logger 中添加一个 ConsoleAppender。输出将使用设置为模式 “%-4timestamp [%thread] %-5level %logger %ndc - %message%newline” 的 PatternLayout 来格式化。
注意,默认情况下,
root
logger 被分配给Level.DEBUG
。
MyApp 的输出为:
0 [main] INFO MyApp - Entering application.
36 [main] DEBUG Com.Foo.Bar - Did it again!
51 [main] INFO MyApp - Exiting application.
顺便提一下,在 log4net 中,子 loggers 只链接到它们现有的祖先。特别的,名为 Com.foo.bar 的 logger 直接链接到 root
logger,从而绕过了未使用的 Com 或 Com.Foo loggers。这将显著提高性能并减少 log4net 的内存占用。
MyApp 类通过调用 BasicConfigurator.Configure()
方法配置 log4net。其他类只需要导入 log4net 命名空间,检索它们希望使用的 loggers,然后记录日志即可。
前面的示例始终输出相同的日志信息。幸运的是,我们可以很容易地修改 MyApp,以便在运行时控制日志输出。下面一个稍微修改过的版本。
using Com.Foo;// 导入 log4net 类。
using log4net;
using log4net.Config;public class MyApp
{private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));static void Main(string[] args) {// BasicConfigurator 被 XmlConfigurator 取代。XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));log.Info("Entering application.");Bar bar = new Bar();bar.DoIt();log.Info("Exiting application.");}
}
这个版本的 MyApp 指示 XmlConfigurator 解析配置文件并相应地设置日志记录。配置文件的路径在命令行中指定。
下面是一个示例配置文件,其输出与前面基于 BasicConfigurator 的示例完全相同。
<log4net><!-- A1 被设置为 ConsoleAppender --><appender name="A1" type="log4net.Appender.ConsoleAppender"><!-- A1 使用 PatternLayout --><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" /></layout></appender><!-- 将 root logger 级别设置为 DEBUG,并将其唯一的 appender 设置为 A1 --><root><level value="DEBUG" /><appender-ref ref="A1" /></root>
</log4net>
假设我们不再对查看属于 Com.Foo 包的任何组件的输出感兴趣。下面的配置文件展示了实现这一目标的一种可能方法。
<log4net><!-- A1 被设置为 ConsoleAppender --><appender name="A1" type="log4net.Appender.ConsoleAppender"><!-- A1 使用 PatternLayout --><layout type="log4net.Layout.PatternLayout"><!-- 以 ISO 8601 格式打印日期 --><conversionPattern value="%date [%thread] %-5level %logger %ndc - %message%newline" /></layout></appender><!-- 将 root logger 级别设置为 DEBUG,并将其唯一的 appender 设置为 A1 --><root><level value="DEBUG" /><appender-ref ref="A1" /></root><!-- 只打印 Com.Foo 包中 WARN 或更高级别的消息 --><logger name="Com.Foo"><level value="WARN" /></logger>
</log4net>
使用该文件配置的 MyApp 的输出如下所示。
2000-09-07 14:07:41,508 [main] INFO MyApp - Entering application.
2000-09-07 14:07:41,529 [main] INFO MyApp - Exiting application.
由于 logger Com.Foo.Bar 没有指定的级别,因此它从 Com.Foo 处继承其级别,Com.Foo 的级别在配置文件中被设置为 WARN。来自 Bar.DoIt
方法的日志语句的级别是 DEBUG,低于 logger 的级别 WARN。因此,DoIt()
方法的日志请求被抑制。
下面是另一个使用多个 appenders 的配置文件。
<log4net><appender name="Console" type="log4net.Appender.ConsoleAppender"><layout type="log4net.Layout.PatternLayout"><!-- 输出调用者的文件名和行号的模式 --><conversionPattern value="%5level [%thread] (%file:%line) - %message%newline" /></layout></appender><appender name="RollingFile" type="log4net.Appender.RollingFileAppender"><file value="example.log" /><appendToFile value="true" /><maximumFileSize value="100KB" /><maxSizeRollBackups value="2" /><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%level %thread %logger - %message%newline" /></layout></appender><root><level value="DEBUG" /><appender-ref ref="Console" /><appender-ref ref="RollingFile" /></root>
</log4net>
使用此配置文件调用增强的 MyApp 将在控制台上输出以下内容。
INFO [main] (MyApp.cs:16) - Entering application.
DEBUG [main] (Bar.cs:12) - Doing it again!INFO [main] (MyApp.cs:19) - Exiting application.
此外,由于 root
logger 已经分配了第二个 appender,因此输出也将定向到 example.log 文件。该文件将在达到 100KB 时进行滚动覆盖。当滚动覆盖发生时,旧版本的 example.log 会自动移动到 example.log.1。
注意,要获得这些不同的日志记录行为,我们不需要重新编译代码。我们同样可以轻松地将日志记录到电子邮件地址,将所有 Com.Foo 的输出重定向到 NT 事件记录器,或者将日志事件转发到远程 log4net 服务器,该服务器会根据本地服务器策略进行日志记录。
有关使用 XmlConfigurator 配置 Appender 的更多示例,请参阅示例 Appender 配置文档。
2、配置属性
可以使用程序集级别(assembly-level)的属性来配置 log4net,而不是以编程方式指定。
-
XmlConfiguratorAttribute
log4net.Config.XmlConfiguratorAttribute
允许使用以下的属性配置 XmlConfigurator:-
ConfigFile
如果指定了该属性,这是要与 XmlConfigurator 一起使用的配置文件的文件名。该文件路径相对于应用程序基目录(
AppDomain.CurrentDomain.BaseDirectory
)。此属性不能与 ConfigFileExtension 属性一起使用。
-
ConfigFileExtension
如果指定了该属性,这是配置文件的扩展名。使用程序集文件名作为基本名,然后附加这个扩展名。例如,如果程序集是从 TestApp.exe 文件加载的,并且 ConfigFileExtension 属性设置为 log4net,那么配置文件名就是 TestApp.exe.log4net。这等同于将 ConfigFile 属性设置为 TestApp.exe.log4net。
配置文件的路径是通过使用应用程序基目录(
AppDomain.CurrentDomain.BaseDirectory
)、程序集文件名和配置文件扩展名来构建的。此属性不能与 ConfigFile 属性一起使用。
-
Watch
如果指定了该标志并将其设置为
true
,则框架将监视配置文件,并在每次修改配置文件时重新加载配置。
如果没有指定 ConfigFile 或 ConfigFileExtension 属性,则应用程序配置文件(例如 TestApp.exe.config)将被用作 log4net 配置文件。
使用示例:
// 使用 .config 文件配置 log4net [assembly: log4net.Config.XmlConfigurator(Watch=true)] // 这将导致 log4net 在应用程序基目录 //(即包含 TestApp.exe 的目录)中查找一个 // 名为 TestApp.exe.config 的配置文件。 // 该配置文件将被监视以查看更改。
// 使用 .log4net 文件配置 log4net [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)] // 这将导致 log4net 在应用程序基目录 //(即包含 TestApp.exe 的目录)中查找一个 // 名为 TestApp.exe.log4net 的配置文件。 // 该配置文件将被监视以查看更改。
每个程序集只能使用此属性一次。
-
使用属性可以更清晰地定义应用程序的配置将从何处加载。然而,值得注意的是,属性是纯粹被动的。它们只是信息。因此,如果你使用配置属性,你必须调用 log4net 以便它读取属性。一个简单的对 LogManager.GetLogger
的调用将导致读取和处理调用程序集上的属性。因此,在应用程序启动的尽可能早的阶段进行日志记录调用是至关重要的,当然在加载和调用任何外部程序集之前就更是如此。
3、appSettings
如果你使用属性来配置 log4net,则可以使用应用程序配置文件的 appSettings
节的两个设置来覆盖程序集属性中给定的值。
带有 “log4net.Config” 键的设置会覆盖配置文件名(并被认为是相对于您的应用程序的基目录),带有 “log4net.Config.Watch” 键的设置决定是否应监视文件的更改。
即便程序集属性
[assembly: log4net.Config.XmlConfigurator(Watch=false)]
将应用程序配置为使用配置文件 “TestApp.exe.config” 并且不监视它的更改。但您可以通过在应用程序的配置文件中添加
<appSettings><add key="log4net.Config" value="log4net.config"/><add key="log4net.Config.Watch" value="True"/>
</appSettings>
来覆盖此设置,以使用文件 “log4net.config” 并监视它。
4、配置文件
通常使用文件指定 log4net 配置。该文件可以通过以下两种方式读取:
- 使用 .NET
System.Configuration
API - 直接读取文件内容
4.1、.config 文件
System.Configuration
API 只有当配置数据在应用程序的配置文件中才可用;也就是名为 MyApp.exe.config 或 Web.config 的文件。由于 System.Configuration
API 不支持重新加载配置文件,因此无法使用 log4net.Config.XmlConfigurator.ConfigureAndWatch
方法来监视配置设置。使用 System.Configuration
API 读取配置数据的主要优点是,它比直接访问配置文件需要的权限更少。
使用 System.Configuration
API 配置应用程序的唯一方法是调用 log4net.Config.XmlConfigurator.Configure()
方法或 log4net.Config.XmlConfigurator.Configure(ILoggerRepository)
方法。
为了在 .config 文件中嵌入配置数据,必须使用 configSections 元素将节名称标识给 .NET 配置文件解析器。该节必须指定将用于解析配置节的 log4net.Config.Log4NetConfigurationSectionHandler。这种类型必须完全由程序集限定,因为它是由 .NET 配置文件解析器加载的,而不是由 log4net 加载的。必须指定 log4net 程序集的正确程序集名称。以下是一个简单的配置文件示例,它指定了用于 log4net 节的正确节处理程序。
<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /></configSections><log4net><appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout></appender><root><level value="INFO" /><appender-ref ref="ConsoleAppender" /></root></log4net>
</configuration>
在上述示例中,指定了 log4net 程序集。该程序集必须位于 .NET 运行时可以找到的位置。例如,它可以位于与应用程序相同的目录中。如果 log4net 程序集存储在 GAC 中,则必须指定完全限定的程序集名称,包括文化、版本和公钥。
当使用 .config 文件指定配置时,节名和 XML 元素名必须是 log4net。
4.2、直接读取文件
XmlConfigurator 可以直接读取任何 XML 文件并使用它来配置 log4net。这包括应用程序的 .config 文件;也就是名为 MyApp.exe.config 或 Web.config 的文件。不直接读取配置文件的唯一原因是,如果应用程序没有足够的权限来读取该文件,那么必须使用 .NET 配置 APIs(见上文)来加载配置。
可以使用接受 System.IO.FileInfo
对象的任何 log4net.Config.XmlConfigurator
方法来指定读取配置的文件。因为可以监视文件系统以获取文件更改通知,所以可以使用 ConfigureAndWatch
方法来监视配置文件的修改,并自动重新配置 log4net。
此外,还可以使用 log4net.Config.XmlConfiguratorAttribute
来指定读取配置的文件。
配置是从文件中的 log4net 元素中读取的。文件中只能指定一个 log4net 元素,但它可以位于 XML 层次结构的任何位置。例如,它可以是根元素:
<?xml version="1.0" encoding="utf-8" ?>
<log4net><appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout></appender><root><level value="INFO" /><appender-ref ref="ConsoleAppender" /></root>
</log4net>
或者它可以嵌套在其他元素中:
<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><section name="log4net" type="System.Configuration.IgnoreSectionHandler" /></configSections><log4net><appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout></appender><root><level value="INFO" /><appender-ref ref="ConsoleAppender" /></root></log4net>
</configuration>
上述示例展示了如何将配置数据嵌入到 .config 文件中,即使该文件是由 log4net 直接读取的。一个重要的注意事项是,如果 .NET 配置文件解析器找到了一个没有使用 configSections 元素注册的元素,它将抛出一个异常。因此,在上述示例中,注册了 log4net 节的名称,但指定来处理该节的类型是 System.Configuration.IgnoreSectionHandler
。这是一个内置类,表示将采用另一种方法来读取配置节。
5、配置语法
log4net 包含一个解析 XML DOM 的配置读取器,即 log4net.Config.XmlConfigurator
。本节定义了配置器接受的语法。
下面是一个有效的 XML 配置示例。根元素必须是 <log4net>。注意,这并不意味着这个元素不能嵌入到另一个 XML 文档中。有关如何在配置文件中嵌入 XmlConfigurator XML 的更多信息,请参见上面的配置文件部分。
<log4net><appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout></appender><root><level value="INFO" /><appender-ref ref="ConsoleAppender" /></root>
</log4net>
<log4net> 元素支持以下属性:
属性 | 描述 |
---|---|
debug | 可选属性。值必须为 true 或者 false 。默认值为 false 。将此属性设置为 true 以启用此配置的内部 log4net 调试。 |
update | 可选属性。值必须为 “Merge”(合并) 或者 “Overwrite”(覆盖)。默认值为 “Merge”。将此属性设置为 “Overwrite”,以便在应用此配置之前重置正在配置的存储库的配置。 |
threshold | 可选属性。值必须是在存储库上注册的级别的名称。默认值为 ALL。设置此属性以限制在整个存储库中记录的消息,而不管消息被记录到哪个 logger。 |
<log4net> 元素支持以下子元素:
元素 | 描述 |
---|---|
appender | 允许 0 个或多个元素。定义一个 appender。 |
logger | 允许 0 个或多个元素。定义一个 logger 的配置。 |
renderer | 允许 0 个或多个元素。定义一个 object renderer。 |
root | 可选元素,最多允许一个。定义 root logger 的配置。 |
param | 允许 0 个或多个元素。存储库特定参数。 |
6、Appenders
Appender 只能被定义为 <log4net> 元素的子元素。每个 Appender 必须具有唯一的名称。必须指定 Appender 的实现类型。
下面这个例子展示了一个类型为 log4net.Appender.ConsoleAppender
的 Appender 被定义。这个 Appender 将被称为 ConsoleAppender。
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout>
</appender>
<appender> 元素支持以下属性:
属性 | 描述 |
---|---|
name | 必要属性。值必须是此 appender 的字符串名称。在此配置文件中定义的所有 appender 中,名称必须是唯一的。logger 的 <appender-ref> 元素使用此名称来引用 appender。 |
type | 必要属性。值必须是此 appender 的类型名称。如果 appender 没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。 |
<appender> 元素支持以下子元素:
元素 | 描述 |
---|---|
appender-ref | 允许 0 个或多个元素。允许 appender 引用另外的 appenders。并非所有的 appenders 都支持。 |
filter | 允许 0 个或多个元素。定义此 appender 使用的 filters。 |
layout | 可选元素,最多允许一个。定义此 appender 使用的 layout。 |
param | 允许 0 个或多个元素。appender 特定参数。 |
有关配置 appender 的示例,请参见示例 Appender 配置文档。
7、Filters
Filters 元素只能定义为 <appender> 元素的子元素
<filter> 元素支持以下属性:
属性 | 描述 |
---|---|
type | 必要属性。值必须是此 filter 的类型名称。如果 filter 没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。 |
<filter> 元素支持以下子元素:
元素 | 描述 |
---|---|
param | 允许 0 个或多个元素。filter 特定参数。 |
filters 形成了一个事件必须通过的链条。沿途的任何 filter 都可以接受事件并停止(过滤)处理,拒绝事件并停止(过滤)处理,或者允许事件传递到下一个过滤器。如果事件在没有被拒绝的情况下到达过滤器链的末端,那么它将被隐式接受并将被记录。
<filter type="log4net.Filter.LevelRangeFilter"><levelMin value="INFO" /><levelMax value="FATAL" />
</filter>
上面这个过滤器将拒绝那些级别低于 INFO 或高于 FATAL 的事件。所有在 INFO 和 FATAL 之间的事件都将被记录。
如果我们只想让包含特定子字符串(例如 ‘database’)的消息通过,那么我们需要指定以下 filters:
<filter type="log4net.Filter.StringMatchFilter"><stringToMatch value="database" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
第一个过滤器将在事件的消息文本中查找子字符串 ‘database’。如果找到了文本,过滤器将接受消息并停止过滤处理,消息将被记录。如果没有找到子字符串,事件将被传递给下一个过滤器进行处理。如果没有下一个过滤器,事件将被隐式接受并将被记录。但是因为我们不希望记录不匹配的事件,我们需要使用 log4net.Filter.DenyAllFilter
,它将拒绝所有到达它的事件。这个过滤器只在过滤器链的末尾有用。
如果我们想允许消息文本中包含 ‘database’ 或 ‘ldap’ 的事件通过,我们可以使用以下 filters:
<filter type="log4net.Filter.StringMatchFilter"><stringToMatch value="database"/>
</filter>
<filter type="log4net.Filter.StringMatchFilter"><stringToMatch value="ldap"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
8、Layouts
Layout 元素只能定义为 <appender> 元素的子元素。
<layout> 元素支持以下属性:
属性 | 描述 |
---|---|
type | 必要属性。值必须是此 layout 的类型名称。如果 layout 没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。 |
<layout> 元素支持以下子元素:
元素 | 描述 |
---|---|
param | 允许 0 个或多个元素。layout 特定参数。 |
下例展示了如何配置一个使用 log4net.Layout.PatternLayout
的 layout。
<layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
</layout>
9、Root Logger
只能定义一个 root
logger 元素,它必须是 <log4net> 元素的子元素。root
logger 是 logger 层次结构的根。所有的 logger 最终都从这个 logger 继承。
一个 root
logger 示例:
<root><level value="INFO" /><appender-ref ref="ConsoleAppender" />
</root>
<root> 元素不支持任何属性。
<root> 元素支持以下子元素:
元素 | 描述 |
---|---|
appender-ref | 允许 0 个或多个元素。允许 logger 通过名称引用 appenders。 |
level | 可选元素,最多允许一个。定义此 logger 的日志级别。此 logger 只会接受此级别或以上的事件。 |
param | 允许 0 个或多个元素。logger 特定参数。 |
10、Loggers
Logger 元素只能定义为 <log4net> 元素的子元素。
一个 logger 示例:
<logger name="LoggerName"><level value="DEBUG" /><appender-ref ref="ConsoleAppender" />
</logger>
<logger> 元素支持以下属性:
属性 | 描述 |
---|---|
name | 必要属性。值必须是 logger 的名称。 |
additivity | 可选属性。值可以为 true 或者 false 。默认值为 true 。将此属性设置为 false 以防止此 logger 继承父 loggers 上定义的 appenders。 |
<logger> 元素支持以下子元素:
元素 | 描述 |
---|---|
appender-ref | 允许 0 个或多个元素。允许 logger 通过名称引用 appenders。 |
level | 可选元素,最多允许一个。定义此 logger 的日志级别。此 logger 只会接受此级别或以上的事件。 |
param | 允许 0 个或多个元素。logger 特定参数。 |
11、Renderers
Renderer 元素只能定义为 <log4net> 元素的子元素。
一个 renderer 示例:
<renderer renderingClass="MyClass.MyRenderer" renderedClass="MyClass.MyFunkyObject" />
<renderer> 元素支持以下属性:
属性 | 描述 |
---|---|
renderingClass | 必要属性。值必须是此 renderer 的类型名称。如果该类型没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。这是将负责渲染 renderedClass 的对象的类型。 |
renderedClass | 必要属性。值必须是此 renderer 的目标类型的类型名称。如果该类型没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。这是此 renderer 将渲染的类型的名称。 |
<renderer> 元素不支持任何子元素。
12、Parameters
Parameter 元素可以是许多元素的子元素。有关详细信息,请参阅上面的特定元素。
一个 param 示例:
<param name="ConversionPattern" value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
<param> 元素支持以下属性:
属性 | 描述 |
---|---|
name | 必要属性。值必须是要在父对象上设置的参数的名称。 |
value | 可选属性。必须指定 value 或 type 属性之一。该属性的值是一个字符串,可以转换为参数的值。 |
type | 可选属性。必须指定 value 或 type 属性之一。此属性的值是要创建并设置为参数值的类型名称。如果类型没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。 |
<param> 元素支持以下子元素:
元素 | 描述 |
---|---|
param | 允许 0 个或多个元素。Parameter 特定参数。 |
一个使用嵌套 param 元素的 param 示例:
<param name="evaluator" type="log4net.spi.LevelEvaluator"><param name="Threshold" value="WARN"/>
<param>
13、扩展参数
配置参数直接映射到对象上的可写属性。可用的属性取决于正在配置的对象的实际类型。log4net SDK 文档包含了 log4net 程序集中所有组件的 API 参考。
对于第三方组件,请参阅其相关 API 参考以获取可用属性的详细信息。
14、紧凑参数语法
所有参数也可以通过使用参数名称作为元素名称来指定,而不是使用 param 元素和 name 属性。
例如一个 param:
<param name="evaluator" type="log4net.spi.LevelEvaluator"><param name="Threshold" value="WARN"/>
<param>
也可以写成:
<evaluator type="log4net.spi.LevelEvaluator"><threshold value="WARN"/>
<evaluator>
下一篇
相关文章:

(二)Apache log4net™ 手册 - 配置
0、引言 在上一篇文章中我们简单介绍了 Log4Net 及其核心的三大组件。本文将在上一篇文章的基础上继续探讨与 Log4Net 配置相关的内容。 1、配置 将日志请求插入到应用程序代码中需要进行大量的计划和工作。观察表明,大约4%的代码专门用于日志记录。因此…...

Elasticsearch:时间点 API
Elasticsearch:时间点 API-CSDN博客 在今天的文章中,我将着重介绍 Point in time API。在接下来的文章中,我将介绍如何运用 PIT 来对搜索结果进行分页。这也是被推荐使用的方法。 Point in time API 默认情况下,搜索请求针对目标…...

hive数据表定义
分隔符 CREATE TABLE emp( userid bigint, emp_name array<string>, emp_date map<string,date>, other_info struct<deptname:string, gender:string>) ROW FORMAT DELIMITED FIELDS TERMINATED BY \t COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMINAT…...

OpenMesh 网格简化之顶点聚类
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 顶点聚类方法将落在给定大小体素中的所有顶点集中到单个顶点之上,其过程有点类似于点云体素下采样,之后再基于聚类之后的顶点重新连接面片,以达到网格简化的目的。 二、实现代码 #define _USE_MATH_DEFINES #in…...

C++ 类和对象篇(八) const成员函数和取地址运算符重载
目录 一、const成员函数 1. const成员函数是什么? 2. 为什么有const成员函数? 3. 什么时候需要使用const修饰成员函数? 二、取地址运算符重载 1. 为什么需要重载取地址运算符? 2. 默认取地址运算符重载函数 3. 默认const取地址运…...

k8s 集群安装(vagrant + virtualbox + CentOS8)
主机环境:windows 11 k8s版本:v1.25 dashboard版本:v2.7.0 calico版本: v3.26.1 CentOS8版本:4.18.0-348.7.1.el8_5.x86_64 用到的脚本: https://gitcode.net/sundongsdu/k8s_cluster 1. Vagrant创建…...

8、Docker数据卷与数据卷容器
一、数据卷(Data Volumes) 为了很好的实现数据保存和数据共享,Docker提出了Volume这个概念,简单的说就是绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷。 数据卷 是一个可供一个或多个容器使用的特殊目…...

大数据与Hadoop入门理论
一、大数据的3种数据类型 1、结构化数据 可定义,有类型、格式、结构的强制约束 如:RDBMS(关系型数据库管理系统) 2、非结构化数据 没有规律没有数据约束可言,很复杂难以解析 如:文本文件,视…...

持续集成部署-k8s-深入了解 Pod:探针
持续集成部署-k8s-深入了解 Pod:探针 1. 探针分类2. 探针探测方式3. 探针参数配置4. 启动探针的应用5. Liveness 探针的应用6. Readiness 探针的应用1. 探针分类 Kubernetes 中的探针是指容器内的进程用于告知 Kubernetes 组件其自身状态的机制; Readiness Probe:就绪探针用…...

来单提醒/客户催单 ----苍穹外卖day9
来单提醒 需求分析 代码开发 注意:前端请求的并不是8080端口;而是先请求Nginx,Nginx进行反向代理以后转发到8080端口 这段代码首先创建了一个orders类用于更新订单状态 并且在更新状态后使用websocket发送给后端提醒 将信息放在map后,使用json的string化方式传给一个接收对象,…...

【单片机】18-红外线遥控
一、红外遥控背景知识 1.人机界面 (1)当面操作:按键,旋转/触摸按键,触摸屏 (2)遥控操作:红外遥控,433M/2.4G无线通信【穿墙能力强】,蓝牙-WIFI-Zigbee-LoRa等…...

【Node.js】module 模块化
认识 node.js Node.js 是一个独立的 JavaScript 运行环境,能独立执行 JS 代码,可以用来编写服务器后端的应用程序。基于Chrome V8 引擎封装,但是没有 DOM 和 BOM。Node.js 没有图形化界面。node -v 检查是否安装成功。node index.js 执行该文…...

Vue中如何进行分布式日志收集与日志分析(如ELK Stack)
在Vue中实现分布式日志收集与日志分析(使用ELK Stack) 日志收集和分析在现代应用程序中是至关重要的,它们可以帮助开发人员监视和诊断应用程序的行为,从而提高应用程序的稳定性和性能。ELK Stack(Elasticsearch、Logs…...

java学习--day23(线程池)
1.线程池Pool 线程池一个容纳了多个线程的容器,其中的线程可以反复的使用。省去了频繁创建线程的对象的操作,无需反复创建线程而消耗更多的资源 在 Java 语言中,并发编程都是通过创建线程池来实现的,而线程池的创建方式也有很多种…...

Unity Golang教程-Shader编写一个流动的云效果
创建目录 一个友好的项目,项目目录结构是很重要的。我们先导入一个登录界面模型资源。 我们先创建Art表示是美术类的资源,资源是模型创建Model文件夹,由于是在登录界面所以创建Login文件夹,下面依次是模型对应的资源,…...

Python数据攻略-Pandas与地理空间数据分析
地理空间数据分析已经成为数据分析不可或缺的一部分。无论是在城市规划、交通分析,还是在环境科学中,地理空间数据都发挥着关键作用。 本文将为初学者和新手提供一个详细的指南,通过使用Python的Pandas库和Geopandas库,来进行地理空间数据分析。 文章目录 用Pandas处理地理…...

sourceTree无法启动
前几天win10系统自动更新后,sourceTree就无法打开了,双击只是图标闪一下,电脑重启后还是无法打开。找到了网上几种方法进行尝试: 方法一:修改配置信息 在自己的电脑路径下: C:\Users\你的用户名\AppData…...

【ARM Coresight 系列文章19 -- Performance Monitoring Unit(性能监测单元)
文章目录 1.1 PMU 介绍1.2 PMU 寄存器1.2.1 PMU 管理寄存器1.2.2 PMU 外设识别寄存器1.2.3 PMU 组件识别寄存器1.3 性能监控事件1.3.1 Cortex-A9 特定事件1.1 PMU 介绍 许多体系结构都包含 PMU(Performance Monitoring Unit)硬件,用于跟踪、计数系统内部的一些底层硬件事件…...

前端学习| 第二章
CSS学习|第一章 前言一、概述1. 语法规定2. 代码风格 二、选择器1. 基础选择器标签选择器类选择器id选择器通配符选择器 2. 复合选择器后代选择器子元素选择器并集选择器伪类选择器链接伪类选择器focus 伪类选择器 三、引入方式四、显示模式1. 块元素2. 行内元素3. 行内块元素4…...

Unity中Shader光强与环境色
文章目录 前言一、实现下图中的小球接受环境光照实现思路:1、在Pass中使用前向渲染模式2、使用系统变量 _LightColor0 获取场景中的主平行灯 二、返回环境中主环境光的rgb固定a(亮度),小球亮度还随之改变的原因三、获取Unity中的环境光的颜色1、Color模式…...

Android9 查看连接多个蓝牙耳机查看使用中的蓝牙耳机
#Android9 查看连接多个蓝牙耳机查看使用中的蓝牙耳机 文章目录 一、主要api:二、BluetoothA2dp 对象的获取三、获取 BluetoothDevice 对象,四、其他: Android 9.0之后,支持一台手机可以同时连接多个蓝牙设备。 但是判断那个蓝牙…...

【EF Core】如何忽略影响导航属性(级联)
文章目录 EF更新和插入时如何忽略更新导航属性级联删除删除主体/父实体断开关系配置级联行为 来源 EF更新和插入时如何忽略更新导航属性 使用Ignore方法: modelBuilder.Entity<Blog>().Ignore(b > b.Posts);使用HasNoKey方法: modelBuilder.…...

【苍穹外卖 | 项目日记】第一天
前言: 我打算用16天的时间写完黑马程序员的苍穹外卖项目,为了督促自己每天坚持写以及记录项目知识点,所以用这种项目日记的方式鞭策自己 目录 前言: 今日完结任务: 今日收获: 1.阅读代码框架…...

WuThreat身份安全云-TVD每日漏洞情报-2023-10-07
漏洞名称:迪普科技DPtech SSL VPN任意文件读取漏洞 漏洞级别:高危 漏洞编号:CNVD-2023-69478 相关涉及:杭州迪普科技股份有限公司 DPtech SSL VPN 漏洞状态:POC 参考链接:https://tvd.wuthreat.com/#/listDetail?TVD_IDTVD-2023-24924 漏洞名称:DTS监控SSL证书操作系统命令注…...

SpringBoot整合Druid配置yml文件
springboot中引入依赖注意,否则yml中配置不生效 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><group…...

如何保证 RabbitMQ 的消息可靠性?
项目开发中经常会使用消息队列来完成异步处理、应用解耦、流量控制等功能。虽然消息队列的出现解决了一些场景下的问题,但是同时也引出了一些问题,其中使用消息队列时如何保证消息的可靠性就是一个常见的问题。如果在项目中遇到需要保证消息一定被消费的…...

图像分类数据集划分(创建ImageNet格式的数据集)
原始数据文件夹如下: ├──data├── 0 类别1├── 1 类别2制作数据集格式如下所示: ├──datasets├── meta│ ├── test.txt # 测试数据集的标注文件│ ├── train.txt # 训练数据集的标注文件│ └── val.txt # 验证…...

ArcGIS Engine:报错无法嵌入互操作类型“ESRI.ArcGIS.Geometry.EnvelopeClass”。请改用适用的接口。
此错误是由于尝试直接实例化ArcGIS COM组件的某些互操作类引起的。这在.NET Framework 4及更高版本中是不被推荐的。 为了解决此问题,你需要确保在工程的引用中将ArcGIS的互操作类型设置为“不嵌入”。 按照以下步骤操作: 在解决方案资源管理器中找到…...

核货宝:服装店收银系统如何选择?收银系统选购指南!
对于各行各业而言,收银系统都是必备的工具。特别是对于像服装店这样的零售门店来说,选择一套适合的收银系统尤为重要。在选择收银系统时,有一些关键的技巧需要注意,以达到软硬件合理搭配、节省开支的目的。下面将分享四个选购服装…...

GB/T 7134-2008 浇筑型工业有机玻璃板材检测
非改性浇筑PMMA板材是指甲基丙烯酸甲酯均聚物板材,或者甲基丙烯酸甲酯与丙烯酸酯类或甲基丙烯酸酯类单体的共聚物板材,通过适当的引发剂本体聚合生产。 GB/T 7134-2008浇筑型工业有机玻璃板材测试项目: 测试项目 测试方法 拉伸强度 GB/T …...