Microsoft.Extensions.Logging与NLog比较

28

我看到很多帖子提到了使用Microsoft.Extensions.Logging以及NLog。

我想更好地了解Microsoft.Extensions.Logging的用途?

具体而言,为什么需要它或者与NLog一起使用的好处是什么?


2
Microsoft AspNetCore引擎只会记录到Microsoft-Extension-Logging(MEL)。如果您想要监视/诊断该引擎的问题,并且喜欢NLog。那么您可以注册NLog成为MEL-LoggingProvider。此外,Microsoft Dependency-Injection默认情况下会自动提供其自己的MEL-ILogger实例作为构造函数参数。 - Rolf Kristensen
2个回答

28

使用 NLog,您可以执行以下操作:

var logger = NLog.LogManager.GetCurrentClassLogger();
logger.Info("Hello {Name}", "Earth");

这适用于所有平台和所有框架。

Microsoft.Extensions.Logging

在.NET Core中,微软引入了来自Microsoft.Extensions.Logging的ILogger抽象。您可以在项目中使用该日志记录抽象,并将其与NLog集成。

例如,在ASP.NET Core中,您可以注入Microsoft.Extensions.Logging.ILogger<HomeController>,并将其发送到NLog日志记录器(参见Getting started with ASP.NET Core 2 · NLog/NLog Wiki)。

using Microsoft.Extensions.Logging;

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
    }

    public IActionResult Index()
    {
        _logger.LogInformation("Index page says hello {Name}", "Universe");
        return View();
    }

软件包

对于NLog和Microsoft.Extensions.Logging,有以下软件包:

比较

NLog优点

直接使用NLog的优点

  • 最佳性能
  • 使用记录器API有更多选项,例如 Logger.WithProperty(..)
  • 适用于所有平台
  • 无需依赖注入,节省复杂性。

Microsoft.Extensions.Logging优点

通过Microsoft.Extensions.Logging使用NLog的优点:

  • 与ASP.NET Core完全集成,例如Microsoft也会写入记录器API,并且NLog也会捕获(并可能被过滤)。
  • 使用日志记录抽象将使您的代码与日志库无关。
  • 与.NET Core依赖注入很好地配合使用
  • 新功能: 您可以使用appsettings.json配置NLog,因此使用JSON而不是XML

更新:添加 - 使用appsettings.json的NLog


5
NLog 的另一个优点在于其 API 简洁易写,例如使用 log.Info(...) 代替 logger.LogInformation(...)。尽管可以创建扩展方法来解决这个问题,但直接使用更加方便。 - Sedat Kapanoglu
1
在我看来,当 LogInformation 表示它将记录信息时,logger.LogInformation(...) 似乎比 log.Info(...) 更清晰。但是当我看到 Info 方法时,它会让我感到困惑。它是要显示信息还是发送到某个地方? - Timur Vafin
1
@TimurVafin 是的,但有时候,拥有一个惯用的API比冗长的API更可取。一旦你习惯了它,它就是自洽的,不会让你感到惊讶,并且你会变得更加高效。一个完美的例子就是Linq扩展方法,比如WhereSelect,它们本身并不具有描述性,但在Linq的上下文中,它们是非常合理的。我认为这也是在日志记录的上下文中的一个例子。 - Sedat Kapanoglu
1
我猜这取决于个人对于方法名称哪种更好。这就是为什么它没有列在答案中的原因。 - Julian

1

Microsoft.Extensions.Logging用于依赖注入,这对于单元测试非常方便:您可以实现一个带有LoggedText属性的记录器,以支持Assert.IsTrue(_logger.LoggedText.Contains("expected value"))。下面的示例说明了一个实现Microsoft.Extensions.Logging.ILogger<T>并(为了好玩)还使用Julian的建议将消息发送到NLog的类:

using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
    
namespace MyDomain.Tests
{
   internal class WrappedNLogger<T> : ILogger<T>
    {
       private StringBuilder _sb = new StringBuilder(); //Support Assert.IsTrue(_logger.LoggedText == "expected value")
        private NLog.Logger _nlog = NLog.LogManager.GetCurrentClassLogger(); //support use of NLog

        public IDisposable BeginScope<TState>(TState state) => default;

        public bool IsEnabled(LogLevel logLevel) => true;

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            var jsonLine = JsonConvert.SerializeObject(new
            {
                timestamp = DateTime.Now.ToLongTimeString(),
                logLevel,
                eventId,
                parameters = (state as IEnumerable<KeyValuePair<string, object>>)?.ToDictionary(i => i.Key, i => i.Value),
                message = formatter(state, exception),
                exception = exception?.GetType().Name
            });

            _sb.AppendLine(jsonLine);
            NLog.LogLevel nloglevel = logLevel == LogLevel.Debug ? NLog.LogLevel.Debug
                                    : logLevel == LogLevel.Information ? NLog.LogLevel.Info
                                    : logLevel == LogLevel.Warning ? NLog.LogLevel.Warn
                                    : logLevel == LogLevel.Error ? NLog.LogLevel.Error
                                    : logLevel == LogLevel.Critical ? NLog.LogLevel.Fatal : NLog.LogLevel.Trace;
            _nlog.Log(nloglevel, jsonLine);
        }

        public string LoggedText { get => _sb.ToString(); }
           
    }
}

1
这与Logger应该对输出格式保持不可知的理念相悖。考虑使用NLog.Extensions.Logging与LoggerFactory,然后配置一个带有JsonLayout的NLog目标将是更好的选择。 - Rolf Kristensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接