MaxLevs
@MaxLevs

Как сконфигурировать Worker Service для логгирования запросов Entity Framework через NLog?

Пишу тестовое Working Service приложение на C#, использующее базу данных.
Для логирования использую NLog.

При конфигурации контекста базы данных для включения логирования процесса работы с базой есть возможность использовать метод UseLoggerFactory(ILoggerFactory).

Проблема в том, что NLog.LogFactory не наследует ILoggerFactory.
Если бы писал не Working Service, а ASP.NET Core приложение, то мог бы использовать для этих целей библиотеку NLog.Web.AspNetCore. Мой же тип проекта эта библиотека не поддерживает.

Процесс конфигурации хоста у этих двух типов проектов практически идентичный, однако прямой подход к решению этого вопроса есть только для ASP.NET Core приложений.

Может быть, кто-то сталкивался с такой проблемой?
Есть ли обходной путь?

UPD1: Прикладываю листинг конфигурирования хоста
Program.cs

var logger = LogManager.GetCurrentClassLogger();

try
{
    logger.Info($"Начинаю запуск приожения {AppDomain.CurrentDomain.FriendlyName}...");

    IHost host = Host.CreateDefaultBuilder(args)
        .ConfigureLogging((hostContext, logging) =>
        {
            logging.ClearProviders();
            logging.SetMinimumLevel(LogLevel.Trace);

            logger.Info("Логгирование сконфигурировано");
        })
        .UseNLog()
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<Worker>();
            services.AddDbContext<MariaDbContext>(options =>
            {
                Version version = new(10, 3, 34);
                ServerVersion serverVersion = ServerVersion.Create(version, ServerType.MariaDb);

                // options.UseLoggerFactory();

                string connectionString = hostContext.Configuration.GetConnectionString("MariaDataBase");
                options.UseMySql(connectionString, serverVersion);

                logger.Info("Контекст базы данных добвален");
            }, ServiceLifetime.Transient, ServiceLifetime.Transient);

            logger.Info("Сервисы сконфигурированы");
        })
        .Build();

    logger.Info($"Запускаю");
    await host.RunAsync();
}

catch (Exception ex)
{
    if (ex is OperationCanceledException)
    {
        logger.Info("Запрошена остановка приложения");
    }

    else
    {
        logger.Fatal(ex, "Приложение остановлено из-за непридвиденной ошибки");
    }
}

finally
{
    logger.Info("Завершаю работу приложения");
    LogManager.Shutdown();
}

  • Вопрос задан
  • 295 просмотров
Решения вопроса 2
vabka
@vabka Куратор тега .NET
Токсичный шарпист
Тебе нужен пакет NLog.Extensions.Logging:
https://github.com/NLog/NLog.Extensions.Logging

Но вообще советую перейти на serilog.
Ответ написан
Комментировать
MaxLevs
@MaxLevs Автор вопроса
Как верно заметил Василий Банников, для решения проблемы потребуется пакет NLog.Extensions.Logging.

Для логирования скомпилированных запросов к базе используется метод UseLoggerFactory(ILoggerFactory). Фабрику можно создать вручную, и передаём в неё в качестве аргумента NLog.Extensions.Logging.NLogLoggerProvider для того, чтобы логирование подхватывалось NLog.

LoggerFactory dbLoggerFactory = new LoggerFactory(new[] { new NLogLoggerProvider() });
options.UseLoggerFactory(dbLoggerFactory);


Стоит также отметить, что для того, чтобы NLog в этом случае использовал нужную конфигурацию (из файла NLog.conf), требуется ему на это указать в Program.cs.

LogManager.LoadConfiguration("NLog.config");
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
hekkaaa
@hekkaaa
C#/.NET Developer
Привет!
Вот мой вариант подключения Nlog к такому сервису на .NET 6
Сам процесс подключения и использования его через DI дальше брал вот с этого примера

Возможно я пропустил пару "скобочек", но вот так выглядитProgram.cs:
IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureHostConfiguration(builder =>
    {
        builder.SetBasePath(System.IO.Directory.GetCurrentDirectory());
    
    })

    .ConfigureServices(services =>
    {
        services.AddHostedService<Worker>();
      var config = new ConfigurationBuilder()
              .SetBasePath(System.IO.Directory.GetCurrentDirectory())
              .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
              .AddEnvironmentVariables()
              .Build();
     
        services.AddSingleton<IRunner, Runner>()
        .AddLogging(loggingBuilder =>
        {
            // configure Logging with NLog
            loggingBuilder.ClearProviders();
            loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug);
            loggingBuilder.AddNLog(config);
        });
        services.AddSingleton<IEmailService, EmailService>();
        services.AddSingleton<IClientSmtp, SmtpClientGoogleAsync>();
        services.AddSingleton<ICheckingSubEmailService, CheckingSubEmailService>();
    })
    .UseWindowsService()
    .Build();


После в такого инстанса в документации есть часть где создается class Running, там ты просто закинь POST запрос в свою базу. Все это делается на DI не сильно сложно.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы