Как регистрировать вызовы NLog из библиотеки классов в моем приложении ASP.NET Core MVC?

Представим, что у меня два проекта.

Первый - это Проект 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 поймает их автоматически, но, похоже, это не так.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
5 540
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
  1. Вам не нужен отдельный файл конфигурации. Если в вашем основном проекте ASP.net MVC есть nlog.config и он успешно скопирован в процессе сборки, то та же конфигурация загрузится, когда

    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
    
  2. Убедитесь, что вы правильно скопировали файл. Также MinLevel правильно выставлен в конфигурации NLog.config.

  3. Убедитесь, что у вас есть .NET Core ClassLibrary (просто чтобы убедиться, что он успешно загружается)

  4. В вашем случае вы тоже можете использовать Dependency Injection, но это другая история.

Вот полный пример с 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 был установлен слишком высоко ... Я слишком привык к странному поведению регистратора и подумал, что что-то еще могло быть не так. :)

Baptiste Candellier 24.10.2018 10:11

@dotnetstep, а если я тестирую Class1, и мне нужно вручную ввести ILogger <Class1>? Как я могу это сделать?

Rolando 23.07.2020 04:54

@rolando, если вы использовали правильный фреймворк для фиксации, вы можете имитировать ilogger <class1>. Что вы пробовали до сих пор?

dotnetstep 23.07.2020 05:03

к сожалению, я использую прямые экземпляры своих сервисов (с базой данных inmemory) в своих тестах. Я пытался передать прямую ссылку на фиктивный регистратор (я знаю, что это уродливо) ... что-то вроде: private ILogger <NetService> logg = new Logger <NetService> (- Но здесь мне нужна фабрика: () ... . любое быстрое решение? (причина, по которой я делаю это, заключается в том, что я получаю ошибку в моем производственном коде, и мне нужно получить зеленую сборку с этим добавленным регистратором: P)

Rolando 23.07.2020 05:11

Думаю, я последую вашему предложению об использовании фиктивного фреймворка :)

Rolando 23.07.2020 05:15

Библиотеки классов никогда не должны зависеть от конкретной реализации ведения журнала. Вместо этого вы должны использовать абстракцию, называемую фасад. Библиотека 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. Приложение, которое использует вашу библиотеку, устанавливает свою фактическую конкретную реализацию ведения журнала, которая затем будет использоваться фасадом под капотом для ведения журнала, выполняемого библиотекой.

Я покупаю ваш комментарий, но вы добавляете несколько фрагментов. Однако, спасибо!

Victor Callegari 05.06.2021 03:39

Другие вопросы по теме