正确使用log4net的方式(记录器命名)


83

有两种配置和使用log4net的方法。第一个是可以配置自己的附加程序和关联的记录器的时间:

<!-- language: xml -->

<appender name="myLogAppender" type="log4net.Appender.RollingFileAppender" >
    <file value="Logs\myLog.log" />
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %level - %message%n" />
    </layout>
</appender>

<logger name="myLog">
    <level value="All"></level>
    <appender-ref ref="myLogAppender" />
</logger>

然后,当我想在日志中写入内容时,可以执行以下操作:

ILog log = LogManager.GetLogger("myLog");
log.Info("message");

使用它的另一种方法是将root配置为我想要的详细信息:

<!-- language: xml -->

<root>
    <level value="Error" />
    <appender-ref ref="myLogAppender" />
</root>

在这种情况下,我可以记录以下消息:

ILog log = LogManager.GetLogger(typeof(Bar));
log.Info("message");

第二种方法的好处是您可以即时启用或禁用某些消息。但是问题是我正在EPiServer CMS中进行开发,并且它具有使用log4net的自己的日志记录系统,如果我在根级别启用信息日志记录,则会写入很多系统日志。

您如何使用log4net?系统的每个部分都在自己的记录器中编写,或者所有内容都在默认记录器中编写,配置决定下一步要做什么?

Answers:


96

关于如何在代码中记录消息,我将选择第二种方法:

ILog log = LogManager.GetLogger(typeof(Bar));
log.Info("message");

发送到上述日志的消息将使用完全限定的类型来“命名” Bar,例如

MyNamespace.Foo.Bar [INFO] message

这种方法的优点是它是组织日志记录的实际标准,它还允许您按名称空间过滤日志消息。例如,您可以指定要记录INFO级别的消息,但将记录级别Bar专门提高到DEBUG:

<log4net>
    <!-- appenders go here -->
    <root>
        <level value="INFO" />
        <appender-ref ref="myLogAppender" />
    </root>

    <logger name="MyNamespace.Foo.Bar">
        <level value="DEBUG" />
    </logger>
</log4net>

通过名称过滤日志记录的功能是log4net的强大功能,如果您仅将所有消息记录到"myLog",则将失去很多这种功能!

关于EPiServer CMS,您应该能够使用上述方法为CMS和您自己的代码指定不同的日志记录级别。

为了进一步阅读,这是我在日志记录中写的一个代码项目文章:


5
您甚至可以使用PatternLayout logging.apache.org/log4net/release/sdk/来从类名称空间的日志部分中排除,以减少日志中的噪音。 “例如,对于记录器名称“ abc”,模式%logger {2}将输出“ bc”。
2011年

7
私有静态只读ILog日志= LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod()。DeclaringType);
卡斯珀·莱昂·尼尔森

为什么第二种方法比第一种更好?类名是静态的,如果您更改它,则也必须在记录器中更新该名称,是否仅仅为了获取类名而引起反射调用就有意义了吗?
MeTitus '16

1
@CasperLeonNielsen您能解释一下这与您有什么不同this.GetType()吗?
ErikE

2
@ErikE在定义静态属性,在静态类中或在构造函数之外时,this.GetType()将不可用。
dhochee '16

11

我的答案可能来晚了,但我认为它可以帮助新手。除非进行如下更改,否则您将看不到日志已执行。

2在实现Log4net时必须更改文件。


  1. 在项目中添加log4net.dll的引用。
  2. app.config
  3. 将在其中实现日志的文件。

在[ app.config ]内部:

首先,在“ configSections”下,您需要添加以下代码;

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

然后,在``配置''块下,您需要编写以下代码(这部分代码根据我的需要进行了自定义,但它的作用就像魅力一样)。

<log4net debug="true">
    <logger name="log">
      <level value="All"></level>
      <appender-ref ref="RollingLogFileAppender" />
    </logger>

    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="log.txt" />
      <appendToFile value="true" />
      <rollingStyle value="Composite" />
      <maxSizeRollBackups value="1" />
      <maximumFileSize value="1MB" />
      <staticLogFileName value="true" />

      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %C.%M [%line] %-5level - %message %newline %exception %newline" />
      </layout>
    </appender>
</log4net>

内部通话类

在将要使用此log4net的类中,需要在下面的代码中声明。

 ILog log = LogManager.GetLogger("log");

现在,您可以在同一班级中的任何位置准备好通话记录。以下是进行操作时可以调用的方法之一。

log.Error("message");

您不需要ILog建立实例成员吗?我在这里已经详细询问了相同的问题,但是也许我可以得到您的意见?
胡志明市陈德良

5

我没有命名我的调用类,而是开始使用以下内容:

private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

这样,我可以在每个使用log4net的类中使用同一行代码,而不必在复制和粘贴时记住更改代码。另外,我可以创建一个日志记录类,并让其他所有类都从我的日志记录类继承。


0

第二种方法的缺点是创建了记录器的大型存储库。如果定义了root且未定义类记录器,则此记录器执行相同的操作。生产系统上的标准方案使用的是几个专门用于班级的记录器。对不起我的英语不好。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.