Как правильно извлечь строку подключения к БД NLog из appsettings.json

#c# #nlog #asp.net-core-3.1

Вопрос:

У меня есть nlog.config настройка файла с целевой базой данных, и я хочу прочитать строку подключения из appsettings.json (и для всех, кому это интересно, значение in appsettings на самом деле хранится в Azure KeyVault). Как правильно это сделать? У меня есть ASP.NET основное приложение 3.1.

nlog.config

 <?xml version="1.0" encoding="utf-8" ?>
<!--The first nLog section internal log file logs the NLog configuration issues, Don't remove this-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="debug"
      internalLogFile="c:tempfoo.txt">


  <extensions>
    <add assembly="NLog.Extensions.Logging"/>
    <add assembly="NLog.Web.AspNetCore"/>
  </extensions>
  
    <variable name="defaultLayout" value="${date} ${threadid} ${uppercase:${level}} ${logger} ${ndc} - ${message}${newline}" />
    <variable name="logDirectory" value="./logs/${shortdate}"/>
    <variable name="apiFileLogPath" value="c:tempapi-nlog.txt"/>
    
    <!-- the targets to write to -->
    <targets>
        <target name="dbTarget"
                xsi:type="Database"
                commandText="..."
            connectionString="${configsetting:item=NLogConfiguration.ConnectionString}">
            <!--<connectionString></connectionString>-->
        </target>
        <!-- write to the void aka just remove -->
        <target xsi:type="Null" name="blackhole" />
    </targets>

    <!-- rules to map from logger name to target -->
    <rules>

        <!--Skip Microsoft logs and so log only own logs-->
        <!--<logger name="*" minlevel="Trace" writeTo="blackhole" final="true" />-->
        <logger name="*" minlevel="Debug" writeTo="dbTarget" />
    </rules>
</nlog>
 

Соответствующая часть appsettings.json файла:

 {
  "NLogConfiguration": {
    "ConnectionString": "..."
  }
}
 

У меня в коде есть точка останова для проверки целевого объекта базы данных, но значение строки подключения не устанавливается. он остается таким же ${configsetting:item=NLogConfiguration.ConnectionString}

У меня нет никакого кода NLog при запуске. У меня есть класс-оболочка вокруг NLog, и я инициализирую его таким образом. Этот класс показан ниже:

DBLogManager

 using System;
using System.Configuration;
using System.Globalization;
using System.Web;
using NLog;
using System.Xml;
using System.IO;
using System.Reflection;
using System.Text;
using Microsoft.Extensions.Configuration;

namespace DBLog.DBLogManager
{

    public class DBLogManager : IDBLogManager
    {
        static ILogger InitializeDBLogManager()
        {
            XmlDocument nLogConfig = new XmlDocument();
            var path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "nlog.config");

            NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(path);
            
            return LogManager.GetLogger("AppLogger");

        }
        private static readonly ILogger Logger = InitializeDBLogManager();
    }
}
 

Комментарии:

1. В вашей конфигурации есть ошибка XML internalLogFile="c:tempfoo.txt> . Это ошибка с копипастом? (отсутствует цитата)

2. @Julian да ошибка копирования-вставки. Спасибо. Я обновил его.

3. @Bmoe Может также включать код, который инициализирует Хост и фактически загружает настройки приложений, поскольку NLog нуждается в небольшой помощи для доступа к настройкам приложений с хоста.

Ответ №1:

Я бы изменил DBLogManager на это:

 namespace DBLog.DBLogManager
{
    public class DBLogManager : IDBLogManager
    {
        // NLog will automatically load NLog.config from AppDomain.BaseDirectory
        private static readonly NLog.Logger Logger = NLog.LogManager.GetLogger("AppLogger");
    }
}
 

И просто добавьте UseNLog() вот так:

 public static IHostBuilder CreateHostBuilder(string[] args) =>
   Host.CreateDefaultBuilder(args)
       .UseNLog();
 

Если вы хотите, чтобы регистратор NLog был создан до IHostBuilder, сделайте это (вместо NLogBuilder.ConfigureNLog ):

 var logger = LogManager.Setup()
                       .LoadConfigurationFromAppSettings()
                       .GetCurrentClassLogger();

 

Комментарии:

1. Ответ Джулиана действительно помог и был раньше вашего. Мне просто нужно было собрать все воедино. Спасибо.

2. @bmoe Да, никаких проблем. Я просто хотел подчеркнуть, что код, включенный в DBLogManager него, был ненужным.

3. Я думаю, что этот ответ лучше, так что не стесняйтесь отмечать как ответ 🙂

Ответ №2:

Для ${configsetting} вас нужен хотя бы пакет NLog.Расширения.Ведение журнала или один из зависимых пакетов, таких как NLog.Web.AspNetCore или NLog.Расширения.Принимающий.

Обычно вы использовали .UseNLog() бы на IHostBuilder , см. NLog — Начало работы с ASP.NET Ядро 3

Чтобы вручную зарегистрировать расширение Microsoft IConfiguration с помощью ${configsetting} :

 IConfigurationRoot config = new ConfigurationBuilder()
    .AddJsonFile(path: "AppSettings.json").Build();
NLog.Extensions.Logging.ConfigSettingLayoutRenderer.DefaultConfiguration = config;
 

См. раздел Визуализатор компоновки NLog — Настройка конфигурации

Комментарии:

1. AddJsonFile Требуется ли линия? У меня этого нет, но мое приложение все еще может считывать appsettings.json файлы.

2. Я не голосовал против, но предполагаю, что это потому, что вы просто повторно использовали существующую документацию, которую, по-видимому, люди не поняли в первую очередь. Я предполагаю, что было ожидание, что вы предоставите рабочий образец. Строки кода, которые вы опубликовали, я лично не знал бы, куда они ведут, если бы раньше не работал с кодом запуска.

3. Вам нужно назначить NLog.Extensions.Logging.ConfigSettingLayoutRenderer.DefaultConfiguration . Вы также можете разрешить конфигурацию в зависимости от остальной части вашего кода