NLog configuration in appsettings.json instead of nlog.config in .NET Core
Asked Answered
D

4

34

The NLog documentation explains how to configure NLog for .NET Core applications by using an nlog.config XML file. However, I'd prefer to have just one configuration file for my application - appsettings.json. For .NET Framework apps, it's possible to put the NLog configuration in app.config or web.config. Is it possible to put the NLog config in appsettings.json in the same way?

For example, how could I put this configuration example from the NLog documentation for ASP.NET Core 2 into 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>
Discerning answered 21/5, 2019 at 21:10 Comment(0)
D
58

Yes, this is possible but has a minimum version requirement. You must be using NLog.Extensions.Logging >= 1.5.0. Note that for ASP.NET Core applications this will be installed as a dependency if you install NLog.Web.AspNetCore >= 4.8.2.

You can then create an NLog section in appsettings.json and load it with the following code:

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"));

For example, for an ASP.NET Core application, your Main() method in Program.cs should look something like this:

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

A configuration like the one in the question can be achieved with the following settings in 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"
        }
    ]
}

Edit: Thanks to Rolf Kristensen (who developed this functionality for NLog in the first place!) for pointing out this wiki page with more documentation on this feature: https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-configuration-with-appsettings.json

Discerning answered 21/5, 2019 at 21:10 Comment(4)
There is also a wiki-page: github.com/NLog/NLog.Extensions.Logging/wiki/Json-NLog-ConfigEffable
One addition for those using multiple environments - since the IWebHostingEnvironment DI is not available in Program, I ended up using 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();Towhaired
What if i want to use this for Console app, and do i still need to install the nuget - NLog.Web.AspNetCore >= 4.8.2 ? I wanted to use the NLog config on appsettings.json for my console app.Concent
@Concent No, so long as you are using NLog.Extensions.Logging >= 1.5.0 you should not need NLog.Web.AspNetCore.Discerning
O
9

Adding to Rolf Kristensen's response.

appsettings.json with database target.

"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"
      }
    ]
  }
Oxcart answered 12/9, 2019 at 2:8 Comment(1)
+1. I could not find a good example for JSON format outside of this answer. This is especially useful since XML to JSON conversion leads to a slightly incorrect structure.Latinity
P
5

All the answers above are correct, but in the modern ASP.NET Core apps, you are likely to have the Configuration loaded already when setting up the logging and therefore you don't need to add the appsettings file manually.

A single line, e.g in Startup.ConfigureServices is enough to switch from using the nlog.config file to a section NLog in appsettings.json or wherever else your application sources configuration at the moment:

NLog.LogManager.Configuration = new NLogLoggingConfiguration(
                                  Configuration.GetSection("NLog"));

Or even cleaner, in Program.cs:

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

The benefit of this method is also the fact that it supports loading configuration from e.g. environment specific config files (appsettings.Development.json etc.).

The format for json config is quite obvious if you know the xml one, and can be found in wiki: https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-configuration-with-appsettings.json

Protraction answered 11/10, 2022 at 9:9 Comment(3)
Great answer!! I tried this, but in my case I still no get something. My app with NLog and settings on appsettings, is using everything rigth away as documentation says, but still no create the file with logs. My console still logging. I was thinking if there is any variable to able NLog create file on app folder, when this file doesnt exist.Aeonian
try to turn on nlog debugging, maybe it doesnt have rights to create that file or its created in a different location than you expectProtraction
I discovered, that was a clause with "final=true", on the rule before my new rule. That answer was on documentation, but it was not so obvious. Thanks for the help.Aeonian
M
3

You can do it like this when you have a console application (I'm using 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();
Mississippian answered 22/7, 2021 at 14:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.