【问题标题】:How to log NLog calls from a class library in my ASP.NET Core MVC app?如何在我的 ASP.NET Core MVC 应用程序中记录来自类库的 NLog 调用?
【发布时间】:2018-10-23 15:50:12
【问题描述】:

假设我有两个项目。

第一个是 ASP.NET Core MVC 项目,它依赖于 NLog.Extensions.Logging 进行日志记录。这很棒;我可以在我的控制器上使用依赖注入来获取ILogger 实例,并且nlog.config 文件包含我的NLog 配置。

第二个是 API 所依赖的类库,它直接依赖于 NLog 进行日志记录。它包含这样的调用:

public class SampleClass
{
    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

    public void DoStuff()
    {
        if (_failed) Logger.Error("oh no");
    }
}

这些类是用一些自反魔法实例化的,我不能使用依赖注入来替换它们的记录器。您也可以将它们视为某种模型,在启动时无法实例化。


如何让我的库的日志显示在 API 的日志输出中?我希望它们会被 nlog.config 自动捕获,但似乎没有。

【问题讨论】:

    标签: c# asp.net-core .net-core asp.net-core-mvc nlog


    【解决方案1】:
    1. 您不需要单独的配置文件。 如果你的 ASP.net MVC 核心项目有 nlog.config 并且在构建过程中被成功复制,那么当

      private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
      
    2. 确保您已正确复制文件。 MinLevel 也在配置 NLog.config 中正确设置。

    3. 确保你有 .NET Core ClassLibrary(只是为了确保它加载成功)

    4. 在你的情况下,你也可以使用依赖注入,但它是不同的故事。

    这是 NLog 的完整示例

    1. 需要获取NLog和NLog.Web.AspnetCore包

    2. 在 Program.cs 中

      public static IWebHostBuilder CreateWebHostBuilder(string[] args)
          {
           return  WebHost.CreateDefaultBuilder(args)
                      .ConfigureLogging(logging =>
                      {
                          logging.ClearProviders();
                          logging.SetMinimumLevel(LogLevel.Trace);
                      }).UseNLog()
                  .UseStartup<Startup>();
          }
      
    3. 现在在 ClassLibrary 项目中只需添加 NLog 的引用。 注意:这里确保 ILogger 来自 Microsoft.Extensions.Logging 而不是来自 NLog。

      public class Class1
      {
          //private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
          private ILogger<Class1> _logger = null;
          public Class1(ILogger<Class1> logger)
          {
              this._logger = logger;
          }
      
          public void DoStuff()
          {
              var _failed = true;
              if (_failed) _logger.LogError("oh no");
          }
      }
      

    现在它也可以正常工作了。

    【讨论】:

    • 感谢您的回答。 minlevel 设置得太高了……我已经习惯了奇怪的记录器行为,我认为可能还有其他问题。 :)
    • @dotnetstep 如果我正在测试 Class1 并且我需要手动注入 ILogger 怎么办?我该怎么做?
    • @rolando 如果您使用了适当的模拟框架,那么您可以模拟 ilogger 。到目前为止你尝试过什么?
    • 遗憾的是,我在测试中使用了我的服务的直接实例(带有内存数据库)。我试图传递一个虚拟记录器的直接引用(我知道它很丑)......类似于:private ILogger logg= new Logger(--但这里我需要一个工厂:()...... . 任何快速的解决方案?(因为我这样做是因为我的生产代码中有一个错误,我需要使用这个添加的记录器获得一个绿色构建:P)
    • 我想我会听从你关于使用模拟框架的建议:)
    【解决方案2】:

    类库不应该依赖于特定的日志实现。相反,您应该使用抽象,称为 facadeMicrosoft.Extensions.Logging 库就是您可以使用的一种外观,但还有其他类似 Common.Logging 的外观。无论如何,需要使用日志的类应该被注入这个抽象的日志外观。例如:

    public class SampleClass
    {
        private readonly ILogger _logger;
    
        public SampleClass(ILogger<SampleClass> logger)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }
    
        public void DoStuff()
        {
            if (_failed) _logger.LogError("oh no");
        }
    }
    

    然后,在您的 Web 应用程序或任何其他使用您的类库的具体应用程序中,您实际设置日志记录实现,并通过您的 DI 容器将其注册以注入到您的日志记录外观中。

    总而言之,你的类库只依赖于你的日志外观,它允许它一般地调用像LogError 这样的东西。使用您的库的应用程序会设置其实际的具体日志记录实现,然后外观将在后台使用该实现来记录库所做的日志记录。

    【讨论】:

    • 我买了你的评论,但我添加了一些 sn-ps。不过谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    相关资源
    最近更新 更多