Come usare NLog in ASP.NET

Come usare NLog in ASP.NET

Quando si desidera utilizzare NLog in ASP.NET, il primo passaggio consiste nell'installare e configurare NLog. Quindi puoi utilizzare direttamente NLog o integrare completamente NLog e ASP.NET.

Usa direttamente NLog se preferisci avere proprietà ILogger statiche, invece di usare l'iniezione di dipendenza. Lo svantaggio di questo approccio è che avrai codice specifico per NLog dappertutto. Realisticamente, questo è un problema solo se pensi che cambierai mai i provider di registrazione nel tuo progetto. Se consideri questo problema o se desideri semplicemente utilizzare il Microsoft.Extensions.Logging.ILogger integrato, scegli l'opzione di integrazione completa.

In questo articolo, mostrerò come installare e configurare NLog, quindi mostrerò entrambe le opzioni di integrazione, utilizzando direttamente NLog o l'integrazione completa.

Installa e configura NLog

  • Installa il pacchetto nuget NLog.Web.AspNetCore. Nota:sta usando Package Console Manager (Visualizza> Altre finestre> Package Console Manager) .
Install-Package NLog.Web.AspNetCore
Code language: PowerShell (powershell)
  • Aggiungi nlog.config al tuo progetto. Configuralo come vuoi. Nota:questo esempio lo configura per registrare tutti i livelli di messaggi in un file di registro utilizzando un layout semplice e archivi in ​​base alle dimensioni del file.
<?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"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">


  <targets>
    <target xsi:type="File"
            name="mainLog"
            fileName="C:\logs\recipeapi-${shortdate}.log"
            layout="${longdate} level=${level} source=${callsite} message=${message}"
            keepFileOpen ="false"
            concurrentWrites ="true"
            archiveNumbering="DateAndSequence"
            archiveAboveSize="1000000"
            maxArchiveFiles="10"/>
  </targets>

  <rules>
    <logger name="*" minlevel="Trace" writeTo="mainLog" />
  </rules>

</nlog>
Code language: HTML, XML (xml)
  • Imposta la proprietà di nlog.config Copia nella directory di output =Copia se più recente .

Il tuo file .csproj dovrebbe assomigliare a questo:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="NLog.Web.AspNetCore" Version="4.13.0" />
  </ItemGroup>

  <ItemGroup>
    <Content Update="nlog.config">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>


</Project>

Code language: HTML, XML (xml)

Opzione 1 – Usa direttamente NLog

Non è necessario integrarsi completamente con ASP.NET per utilizzare NLog. Questa è l'opzione più semplice.

In ogni controller in cui si desidera un logger, aggiungere un NLog.ILogger statico e inizializzarlo su LogManager.GetCurrentClassLogger(). Il motivo per renderlo statico è perché gli oggetti controller vengono creati ogni volta che arriva una nuova richiesta e GetCurrentClassLogger() è lento.

Puoi renderlo un campo privato, come questo:

private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
Code language: C# (cs)

Se vuoi essere in grado di scambiare un logger fittizio durante lo unit test, rendilo invece una proprietà pubblica (o interna), come questa:

public static ILogger Logger { get; set; } = LogManager.GetCurrentClassLogger();
Code language: C# (cs)

Ecco un esempio di controller con una proprietà ILogger statica pubblica:

using NLog;

[ApiController]
[Route("[controller]")]
public class RecipesController : ControllerBase
{
	public static ILogger Logger { get; set; } = LogManager.GetCurrentClassLogger();

	[HttpGet("{id}")]
	public Recipe Get(int id)
	{
		Logger.Debug($"GET /recipes/id called with id={id}");

		return GetRecipeFromRepo(id); 
	}
}
Code language: C# (cs)

Quando arriva una richiesta, questo endpoint registra quanto segue in C:\logs\recipapi-2021-07-30.log:

2021-07-30 16:14:44.5658 level=Debug source=RecipesApi.Controllers.RecipesController.Get message=GET /recipes/id called with id=1Code language: plaintext (plaintext)

Nota:questo non registra i messaggi di registro della durata dell'hosting.

Opzione 2 – Integra completamente NLog con ASP.NET

La piena integrazione dei risultati in quanto segue:

  • Puoi utilizzare Microsoft.Extensions.Logging.ILogger invece di NLog.ILogger.
  • Puoi il costruttore iniettare ILogger nei tuoi controller.
  • Devi impostare il livello di registrazione in appsettings.json (o appsettings.development.json).
  • Registrerà i messaggi di durata dell'hosting utilizzando NLog.

Il vantaggio principale è che è un approccio generico e riduce al minimo il codice specifico di NLog. Ti consente di scambiare un provider di registrazione diverso (es:Serilog) con modifiche minime.

Passaggio 1:chiama UseNLog()

Per integrarsi completamente, nella classe Program in cui stai chiamando .ConfigureWebHostDefaults(), chiama webBuilder.ConfigureLogging() e UseNLog(), in questo modo:

using NLog.Web;

public class Program
{
	public static void Main(string[] args)
	{
		CreateHostBuilder(args).Build().Run();
	}

	public static IHostBuilder CreateHostBuilder(string[] args) =>
		Host.CreateDefaultBuilder(args)
			.ConfigureWebHostDefaults(webBuilder =>
			{
				webBuilder.UseStartup<Startup>();
				webBuilder.ConfigureLogging(loggerBuilder => 
				{ 
					//configure how you want
				})
				.UseNLog();
				
			});
}
Code language: C# (cs)

Cosa fa UseNLog()?

UseNLog() esegue principalmente lo scambio in NLogLoggerFactory, che il framework utilizzerà quando è necessario iniettare le dipendenze oggetti ILogger nei controller. Ecco la riga pertinente nel codice sorgente di NLog:

services.Replace(ServiceDescriptor.Singleton<ILoggerFactory, NLogLoggerFactory>(serviceProvider => new NLogLoggerFactory(sharedFactory(serviceProvider, configuration, options))));
Code language: C# (cs)

Rif:codice sorgente del metodo NLog.Web AddNLogLoggerProvider()

Fase 2:il costruttore inietta ILogger nei controller

In ogni controller in cui desideri un logger, aggiungi il parametro Microsoft.Extensions.Logging.ILogger appropriato al costruttore, in questo modo:

using Microsoft.Extensions.Logging;

[ApiController]
[Route("[controller]")]
public class RecipesController : ControllerBase
{
	private readonly ILogger<RecipesController> Logger;
	public RecipesController(ILogger<RecipesController> logger)
	{
		Logger = logger;
	}

	[HttpGet("{id}")]
	public Recipe Get(int id)
	{
		Logger.LogDebug($"GET /recipes/id called with id={id}");

		return GetRecipeFromRepo(id); 
	}
}
Code language: C# (cs)

Passaggio 3:imposta il livello di registrazione in appsettings.json

In appsettings.json (o appsettings.Development.json), imposta il livello di registro predefinito come desiderato:

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

Code language: JSON / JSON with Comments (json)

Quando arriva una richiesta, registrerà quanto segue in C:\logs\recipapi-2021-07-31.log

2021-07-31 08:45:38.4599 level=Info source=Microsoft.Extensions.Hosting.Internal.ConsoleLifetime.OnApplicationStarted message=Application started. Press Ctrl+C to shut down.
2021-07-31 08:45:38.5089 level=Info source=Microsoft.Extensions.Hosting.Internal.ConsoleLifetime.OnApplicationStarted message=Hosting environment: Development
2021-07-31 08:45:38.5089 level=Info source=Microsoft.Extensions.Hosting.Internal.ConsoleLifetime.OnApplicationStarted message=Content root path: C:\Projects\RecipesApi
2021-07-31 08:45:38.5510 level=Debug source=RecipesApi.Controllers.RecipesController.Get message=GET /recipes/id called with id=1
Code language: plaintext (plaintext)

Si noti che sta registrando i messaggi di durata dell'hosting (es:"Applicazione avviata"). Il livello di registrazione per l'hosting di messaggi a vita è controllato dalla proprietà Logging.LogLevel.Microsoft.Hosting.Lifetime in appsettings.json (o appsettings.Development.json).

Nota:UseNLog() collega l'instradamento dell'hosting dei messaggi di registro a vita a NLog.