Представим, что у меня два проекта.
Первый - это Проект 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
поймает их автоматически, но, похоже, это не так.
Вам не нужен отдельный файл конфигурации. Если в вашем основном проекте ASP.net MVC есть nlog.config и он успешно скопирован в процессе сборки, то та же конфигурация загрузится, когда
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
Убедитесь, что вы правильно скопировали файл. Также MinLevel правильно выставлен в конфигурации NLog.config.
Убедитесь, что у вас есть .NET Core ClassLibrary (просто чтобы убедиться, что он успешно загружается)
В вашем случае вы тоже можете использовать Dependency Injection, но это другая история.
Вот полный пример с NLog
Вам необходимо получить пакет NLog и NLog.Web.AspnetCore
В Program.cs
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
}).UseNLog()
.UseStartup<Startup>();
}
Теперь в проекте 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");
}
}
Теперь он тоже будет работать без проблем.
@dotnetstep, а если я тестирую Class1, и мне нужно вручную ввести ILogger <Class1>? Как я могу это сделать?
@rolando, если вы использовали правильный фреймворк для фиксации, вы можете имитировать ilogger <class1>. Что вы пробовали до сих пор?
к сожалению, я использую прямые экземпляры своих сервисов (с базой данных inmemory) в своих тестах. Я пытался передать прямую ссылку на фиктивный регистратор (я знаю, что это уродливо) ... что-то вроде: private ILogger <NetService> logg = new Logger <NetService> (- Но здесь мне нужна фабрика: () ... . любое быстрое решение? (причина, по которой я делаю это, заключается в том, что я получаю ошибку в моем производственном коде, и мне нужно получить зеленую сборку с этим добавленным регистратором: P)
Думаю, я последую вашему предложению об использовании фиктивного фреймворка :)
Библиотеки классов никогда не должны зависеть от конкретной реализации ведения журнала. Вместо этого вы должны использовать абстракцию, называемую фасад. Библиотека Microsoft.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");
}
}
Затем в вашем веб-приложении или любом другом конкретном приложении, использующем вашу библиотеку классов, вы фактически настраиваете свою реализацию ведения журнала и регистрируете ее через свой контейнер DI для внедрения в фасад ведения журнала.
Короче говоря, ваша библиотека классов зависит только от вашего фасада ведения журнала, что позволяет ей в общем случае вызывать такие вещи, как LogError
. Приложение, которое использует вашу библиотеку, устанавливает свою фактическую конкретную реализацию ведения журнала, которая затем будет использоваться фасадом под капотом для ведения журнала, выполняемого библиотекой.
Я покупаю ваш комментарий, но вы добавляете несколько фрагментов. Однако, спасибо!
Спасибо за Ваш ответ.
minlevel
был установлен слишком высоко ... Я слишком привык к странному поведению регистратора и подумал, что что-то еще могло быть не так. :)