log4net:在哪里放置静态 LogManger 对象? (在解决方案的不同项目中使用它,每个项目都有一个单独的配置文件)

log4net: Where to place static LogManger object? (using it in different projects of a solution, each having an individual config-file)

到目前为止我还没有接触过配置文件。因此,与此相关,我想我在第一次使用 log4net 时错过了一些要完全理解的基础知识。


这是我已经读过的内容:

https://stackify.com/log4net-guide-dotnet-logging

https://csharp.today/log4net-tutorial-great-library-for-logging

log4net configuration with [assembly:]


假设我们在一个解决方案中有三种不同类型的项目,每个项目都附加了 log4net:

1) 我应该把下面几行放在哪里?在每个 class 我要登录的地方?

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

2) 我想知道如何在我想使用它的任何地方获取静态对象。所以我在 LowLevel 项目中添加了如下所示的 class,希望 'using' 能有所帮助。

using System;
using System.Collections.Generic;
using System.Text;

using log4net;

namespace LowLevel.NuGet.Log4Net
{
    public class Log4Net
    {
        // Avoiding overhead by logging, reducing use of CPU via static LogManager object.
        private static readonly log4net.ILog _log
            = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        //
        // Properties
        //

        public static log4net.ILog Log { get => _log; }
    }
}

但我建议我不会工作,因为 .NET Standard 2.0 项目没有自己的配置文件。

非常感谢。

第 1 部分:LogManager.GetLogger

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

我真的不知道为什么马特会提出这种可憎的观点(恕我直言)。是的,您可以简单地将其复制并粘贴到您想要记录的每个 class 中,但反射是 .

尽管 LogManager 应该为相同的 class 提供相同的 Logger 实例,但 建议将其设为静态, 以避免调用 LogManager。这应该会提高性能,特别是如果您有经常实例化的日志记录 classes。

在 log4net 文档(以及我自然会做的)中,另一种方法是这样做:

private static readonly ILog log = LogManager.GetLogger(typeof(ClassName));

缺点:你有一个 classname 在那里,所以没有简单的 C&P。

如果您使用重构功能更改 class 名称,

BUT Visual Studio 将更改它,您可以定义 shortcut/templates 来填写class 名称自动。但即使你手动完成,我仍然更喜欢这个而不是反射。

供参考:typeof operator and lang-reference: typeof

第 2 部分:配置

使用库进行日志记录配置没有任何意义。他们不会被执行 "standalone"。您要做的是利用名称空间。

假设您有库 A 和 B,具有命名空间 "my.prj.A" 和 "my.prj.B" 以及一个 "Main" 应用程序 "my.prj.App",那么您将在应用程序。但是,您仍然可以应用不同的设置/附加程序:

log4net 跨越配置继承树(如他们的 "configuration" 和 "getting started" 文档中所述)。因此,您将始终 拥有根记录器。如果没有其他记录器适用,这是默认值或回退。

然后你可以定义子记录器(我的术语,不知道他们怎么称呼它们),例如:

  • logger "my.prj" 如果没有更具体的记录器适用,它将应用于从 typeof(my.prj.*.SomeClass) 创建的所有记录器。没有意义?是的,它会 - 它 不会 适用于例如第 3 方库。如果他们碰巧使用log4net,他们将回退到root。

  • logger "my.prj.A" 将应用于库 A 中的所有 classes。

  • logger "my.prj.B.SomeFeatureNamespace" 将应用于库 B 中 FeatureNamespace 的所有 classes。

...你明白要点了。

顺便说一句: 使用 ... = LogManager.GetLogger("MySuperSpecialLogger"); 你可以为 "MySuperSpecialLogger" 定义一个配置,这在调试时会派上用场,因为你可以 "follow" 一些流经 classes 并且可以通过记录器名称轻松过滤日志或将其写入不同的文件等
或者您可以聚合登录输入以获取文档。例如,您有 3 种登录方法,但您需要记录尝试和成功/失败的日志:您可以为此创建一个命名记录器并将其连接到自己的附加程序,在 3 种实现中获取它,写入日志登录输出 attempts/success/fail - 完成。


没有配置库也有一些其他影响:

  • 如果您真的重用它们,每个解决方案都可以为它们定义不同的日志记录配置。
  • 您可以关闭单元测试项目中的日志记录。
  • 如果您(或其他人)在使用不同日志框架的项目中使用它们,您可能仍然能够记录,但配置可能来自外观或适配器.