如何正确地从 appsettings.json 中提取 NLog DB ConnectionString

How to Properly Pull NLog DB ConnectionString from appsettings.json

我的 nlog.config 文件设置有一个数据库目标,想从 appsettings.json 读取连接字符串(对于任何感兴趣的人,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:\temp\foo.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:\temp\api-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": "..."
  }
}

我的代码中有一个断点来检查数据库目标,但未设置 connectionString 值。它保持 ${configsetting:item=NLogConfiguration.ConnectionString}

我在启动时没有任何 NLog 代码。我在 NLog 周围有一个包装器 class 并以这种方式对其进行初始化。即class如下所示:

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();
    }
}

对于 ${configsetting},您至少需要软件包 NLog.Extensions.Logging 或依赖软件包之一,例如 NLog.Web.AspNetCore 或 NLog.Extensions.Hosting.

通常您会在 IHostBuilder 上使用 .UseNLog(),请参阅 NLog - Getting started with ASP.NET Core 3

要使用 ${configsetting} 手动注册 Microsoft 扩展 IConfiguration

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

参见 NLog - ConfigSetting 布局渲染器

我会将 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();

如果您想在 IHostBuilder 之前创建 NLog Logger,请执行此操作(而不是 NLogBuilder.ConfigureNLog):

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