在.NET Core中,将NLog配置放在appsettings.json而不是nlog.config中。

28
NLog文档解释了如何使用一个nlog.config XML文件配置.NET Core应用程序的NLog。然而,我更喜欢为我的应用程序只有一个配置文件-appsettings.json。对于.NET Framework应用程序,可以将NLog配置放在app.configweb.config中。是否可以以同样的方式将NLog配置放在appsettings.json中?
例如,我如何将ASP.NET Core 2的NLog文档的此配置示例放入appsettings.json中?
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Info"
      internalLogFile="c:\temp\internal-nlog.txt">

  <!-- enable asp.net core layout renderers -->
  <extensions>
    <add assembly="NLog.Web.AspNetCore"/>
  </extensions>

  <!-- the targets to write to -->
  <targets>
    <!-- write logs to file  -->
    <target xsi:type="File" name="allfile" fileName="c:\temp\nlog-all-${shortdate}.log"
            layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />

    <!-- another file log, only own logs. Uses some ASP.NET core renderers -->
    <target xsi:type="File" name="ownFile-web" fileName="c:\temp\nlog-own-${shortdate}.log"
            layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
  </targets>

  <!-- rules to map from logger name to target -->
  <rules>
    <!--All logs, including from Microsoft-->
    <logger name="*" minlevel="Trace" writeTo="allfile" />

    <!--Skip non-critical Microsoft logs and so log only own logs-->
    <logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
    <logger name="*" minlevel="Trace" writeTo="ownFile-web" />
  </rules>
</nlog>
4个回答

50

是的,这是可能的,但需要最低版本要求。您必须使用NLog.Extensions.Logging >= 1.5.0。请注意,对于ASP.NET Core应用程序,如果您安装了NLog.Web.AspNetCore >= 4.8.2,它将作为依赖项安装。

然后,您可以在appsettings.json中创建一个NLog部分,并使用以下代码加载它:

var config = new ConfigurationBuilder()
  .SetBasePath(System.IO.Directory.GetCurrentDirectory())
  .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();
NLog.Config.LoggingConfiguration nlogConfig = new NLogLoggingConfiguration(config.GetSection("NLog"));

例如,对于一个ASP.NET Core 应用程序,你的 Program.cs 文件中的 Main() 方法应该像下面这样:
public static void Main(string[] args)
{
    var config = new ConfigurationBuilder()
        .SetBasePath(System.IO.Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();
    LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));

    var logger = NLog.Web.NLogBuilder.ConfigureNLog(LogManager.Configuration).GetCurrentClassLogger();
    try
    {
        logger.Debug("Init main");
        CreateWebHostBuilder(args).Build().Run();
    }
    catch (Exception ex)
    {
        logger.Error(ex, "Stopped program because of exception");
    }
    finally {
        LogManager.Shutdown();
    }
}

像问题中的配置可以通过以下在appsettings.json中的设置来实现:

"NLog":{
    "internalLogLevel":"Info",
    "internalLogFile":"c:\\temp\\internal-nlog.txt",
    "extensions": [
      { "assembly": "NLog.Extensions.Logging" },
      { "assembly": "NLog.Web.AspNetCore" }
    ],
    "targets":{
        "allfile":{
            "type":"File",
            "fileName":"c:\\temp\\nlog-all-${shortdate}.log",
            "layout":"${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}"
        },
        "ownFile-web":{
            "type":"File",
            "fileName":"c:\\temp\\nlog-own-${shortdate}.log",
            "layout":"${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}"
        }
    },
    "rules":[
        {
            "logger":"*",
            "minLevel":"Trace",
            "writeTo":"allfile"
        },
        {
            "logger":"Microsoft.*",
            "maxLevel":"Info",
            "final":"true"
        },
        {
            "logger":"*",
            "minLevel":"Trace",
            "writeTo":"ownFile-web"
        }
    ]
}

编辑:感谢Rolf Kristensen(最初为NLog开发此功能)指出了这个维基页面,其中有关于此功能的更多文档:https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-configuration-with-appsettings.json


6
这是一篇关于NLog.Extensions.Logging的Wiki页面:https://github.com/NLog/NLog.Extensions.Logging/wiki/Json-NLog-Config。 - Rolf Kristensen
5
对于使用多个环境的用户,有一个额外的补充 - 因为在 Program 中不可用 IWebHostingEnvironment 依赖注入,所以我最终使用了: var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env}.json", optional: true) .Build(); - dp.
如果我想在控制台应用程序中使用它,我是否仍然需要安装NuGet - NLog.Web.AspNetCore >= 4.8.2?我想在appsettings.json上使用NLog配置来为我的控制台应用程序进行配置。 - Ak777
1
@Ak777 不需要使用NLog.Web.AspNetCore,只要您使用的是NLog.Extensions.Logging >= 1.5.0。 - AlliterativeAlice

7

补充Rolf Kristensen的回答。

appsettings.json中包含数据库目标。

"NLog": {
    "autoReload": true,
    "throwConfigExceptions": true,
    "internalLogLevel": "info",
    "internalLogFile": "c:\\temp\\internal-nlog.txt",
    "extensions": [
       { "assembly": "NLog.Extensions.Logging" }
    ],
    "targets": {
      "database": {
        "type": "Database",
        "commandText": "INSERT INTO dbo.log (MachineName,Logged,Level,Message,Logger,Callsite,Exception) values (@MachineName,@Logged,@Level,@Message,@Logger,@Callsite,@Exception)",
        "parameters": [
          {
            "name": "@MachineName",
            "layout": "${machinename}"
          },
          {
            "name": "@Logged",
            "layout": "${date}"
          },
          {
            "name": "@Level",
            "layout": "${level}"
          },
          {
            "name": "@Message",
            "layout": "${message}"
          },
          {
            "name": "@Logger",
            "layout": "${logger}"
          },
          {
            "name": "@Callsite",
            "layout": "${callsite}"
          },
          {
            "name": "@Exception",
            "layout": "${exception:tostring}"
          }
        ],
        "dbProvider": "System.Data.SqlClient",
        "connectionString": "Data Source=database server;Initial Catalog=database ;Trusted_Connection=False; User Id=AppUser;Password=AppUserPassword;"
      }
    },

    "rules": [
      {
        "logger": "*",
        "minLevel": "Trace",
        "writeTo": "database"
      }
    ]
  }

+1. 我在这个答案之外找不到一个好的JSON格式示例。这尤其有用,因为XML转JSON会导致略微不正确的结构。 - Alexei - check Codidact

3
以上所有答案都是正确的,但在现代ASP.NET Core应用程序中,当设置日志记录时,您可能已经加载了配置,因此不需要手动添加appsettings文件。
一行代码即可完成切换,例如在Startup.ConfigureServices中,就可以从使用nlog.config文件切换到在appsettings.json或其他地方获取应用程序配置的NLog部分:
NLog.LogManager.Configuration = new NLogLoggingConfiguration(
                                  Configuration.GetSection("NLog"));

甚至更简洁的写法,在Program.cs中实现:

public static IHostBuilder CreateHostBuilder(string[] args) =>
       Host.CreateDefaultBuilder(args)
       .ConfigureWebHostDefaults(webBuilder =>
       {
           webBuilder.UseStartup<Startup>();
       }).UseNLog(new NLogAspNetCoreOptions(){
           LoggingConfigurationSectionName = "NLog"
       });

这种方法的好处还在于它支持从环境特定的配置文件(例如appsettings.Development.json等)中加载配置。如果你知道 XML 配置方式,那么 JSON 配置格式也很容易理解,相关信息可以在维基页面中找到:https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-configuration-with-appsettings.json

太棒了!我尝试过这个方法,但在我的情况下仍然没有得到结果。根据文档,我的应用程序使用NLog和appsettings中的设置,但仍然没有创建日志文件。我的控制台仍然在记录日志。我在想是否有任何变量可以让NLog在应用程序文件夹中创建文件,当该文件不存在时。 - Gabriel Silva
尝试打开NLog调试,可能它没有权限创建该文件,或者它被创建在你预期的不同位置。 - undefined
1
我发现,在我的新规则之前的规则中,有一个带有"final=true"的子句。这个答案在文档中有提到,但并不是那么明显。谢谢你的帮助。 - undefined

3
当你有一个控制台应用程序时,你可以像这样做(我正在使用Net 5):
public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
             ...
            }).ConfigureLogging((hostContext, logBuilder) =>
            {
                logBuilder.AddNLog(new NLogLoggingConfiguration(hostContext.Configuration.GetSection("NLog"))).SetMinimumLevel(LogLevel.Trace);
            })
            .UseConsoleLifetime();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接