Microsoft.Extensions.Logging Vs. NLog
Я вижу много сообщений, в которых упоминается использование Microsoft.Extensions.Logging вместе с NLog.
Хотелось бы лучше понять, для чего используется Microsoft.Extensions.Logging?
А конкретно, зачем это нужно или в чем польза от использования вместе с NLog?
2 ответа
С помощью NLog вы могли:
var logger = NLog.LogManager.GetCurrentClassLogger();
logger.Info("Hello {Name}", "Earth");
Это работает для всех платформ и всех фреймворков.
Microsoft.Extensions.Logging
С появлением.NET Core корпорация Microsoft представила абстракцию журналирования - Microsoft.Extensions.Logging. Вы можете использовать эту абстракцию журналирования в своем проекте и интегрировать ее с NLog.
Например, в ASP.NET Core вы можете ввести Microsoft.Extensions.Logging.ILogger<HomeController>
и это может отправить журналы в NLog. (см. Начало работы с 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 есть следующие пакеты:
- Абстракции ведения журнала ядра.NET находятся в пакете https://www.nuget.org/packages/Microsoft.Extensions.Logging.Abstractions/.
- Интеграция NLog для этих абстракций находится в пакете https://www.nuget.org/packages/NLog.Extensions.Logging/. Вы можете использовать этот пакет для консольных приложений.NET Core.
- Для ASP.NET Core существует оптимизированный пакет NLog.Web.AspNetCore, который использует NLog.Extensions.Logging.
Сравнение
NLog Плюсы
Плюсы использования NLog напрямую
- Лучшее представление
- Больше возможностей с API логгера, например
Logger.WithProperty(..)
- Работает на всех платформах
- Не требуется внедрение зависимостей, что снижает сложность.
Плюсы Microsoft.Extensions.Logging
Плюсы использования NLog через Microsoft.Extensions.Logging:
- Полностью интегрирован с ASP.NET Core, например, Microsoft также записывает в API регистратора, и это также будет захвачено (и, возможно, отфильтровано) NLog
- Запись в абстракцию журналирования сделает вашу библиотеку журнала кода независимой.
- Хорошо работает с внедрением зависимостей.NET Core
- новое: вы можете настроить NLog с помощью appsettings.json - поэтому с JSON вместо XML
Обновление: добавлено - Использование NLog с appsettings.json
Microsoft.Extensions.Logging
используется для внедрения зависимостей, что удобно для модульного тестирования: вы можете реализовать регистратор со свойством LoggedText для поддержки
Assert.IsTrue(_logger.LoggedText.Contains("expected value"))
. В следующем примере показан такой класс, который реализует
Microsoft.Extensions.Logging.ILogger<T>
а также (для развлечения) использует предложение Джулиана отправить сообщение в 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(); }
}
}