Configuration Avancée et Journalisation Structurée avec NLog dans ASP.NET Core

Dans le développement d'applications monolithiques ou de microservices, la journalisation est indispensable pour le débogage et la surveillance. Parmi les solutions disponibles dans l'écosystème .NET, NLog se distingue par sa flexibilité et ses capacités d'extension. Il permet de configurer les sorties via des fichiers de configuration sans modifier le code source, supporte des formats variés (JSON, XML) et s'intègre à de nombreuses cibles (fichiers, bases de données, Elasticsearch, consoles).

Intégration de NLog dans un projet ASP.NET Core

Pour illustrer la mise en place de cette bibliothèque, nous allons configurer une application web ASP.NET Core.

Tout d'abord, initialisez un nouveau projet MVC :

dotnet new mvc -n TelemetryApp

Ensuite, ajoutez le package NuGet nécessaire pour l'intégration avec ASP.NET Core :

cd TelemetryApp
dotnet add package NLog.Web.AspNetCore

Configuration via appsettings.json

Bien qu'il soit possible d'utiliser un fichier nlog.config XML, l'approche JSON dans appsettings.json est souvent préférée pour maintenir une cohérence avec le système de configuration natif de .NET. Voici une configuration qui dirige les événements de niveau Information vers la console et ceux de niveau Debug vers un fichier.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "NLog": {
    "throwConfigExceptions": true,
    "variables": {
      "storagePath": "${basedir}/var/log/telemetry"
    },
    "extensions": [
      {
        "assembly": "NLog.Web.AspNetCore"
      }
    ],
    "targets": {
      "async": true,
      "fileTarget": {
        "type": "File",
        "encoding": "utf-8",
        "fileName": "${storagePath}/${shortdate}/app_${level}.log"
      },
      "consoleTarget": {
        "type": "Console"
      }
    },
    "rules": [
      {
        "logger": "*",
        "minLevel": "Info",
        "writeTo": "consoleTarget"
      },
      {
        "logger": "*",
        "minLevel": "Debug",
        "writeTo": "fileTarget"
      }
    ]
  }
}

Initialisation dans Program.cs

Modifiez le point d'entrée de l'application pour charger la configuration NLog et remplacer les fournisseurs de journaux par défaut.

using NLog.Extensions.Logging;
using NLog.Web;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();

// Extraction de la section NLog depuis la configuration
var nlogSection = builder.Configuration.GetSection("NLog");
NLog.LogManager.Configuration = new NLogLoggingConfiguration(nlogSection);

// Nettoyage des fournisseurs par défaut
builder.Logging.ClearProviders();

// Activation de NLog avec les filtres de l'usine de journalisation
var nlogOptions = new NLogAspNetCoreOptions { RemoveLoggerFactoryFilter = false };
builder.Host.UseNLog(nlogOptions);

var app = builder.Build();
// Configuration du pipeline HTTP...

Émission de journaux dans un contrôleur

Injectez l'interface ILogger dans vos contrôleurs pour émettre des événements. L'utilisation de modèles de message permet une meilleure structuration des données.

using Microsoft.AspNetCore.Mvc;

namespace TelemetryApp.Controllers;

public class DashboardController : Controller
{
    private readonly ILogger<dashboardcontroller> _appLogger;

    public DashboardController(ILogger<dashboardcontroller> appLogger)
    {
        _appLogger = appLogger;
    }

    public IActionResult Overview()
    {
        var clientProfile = new { clientId = 42, region = "EU-West" };
        _appLogger.LogInformation("Accès au tableau de bord pour le profil {ClientProfile}", clientProfile);
        return View();
    }
}</dashboardcontroller></dashboardcontroller>

Ajutsement par environnement

Pour obtenir plus de détails lors du développement, vous pouvez ajuster les niveaux de filtrage dans appsettings.Development.json. Cela permet de capturer les journaux internes du framework.

"Logging": {
  "LogLevel": {
    "Default": "Information",
    "Microsoft.AspNetCore": "Information"
  }
}

Avec cette modification, les journaux du framework s'affichent en console avec la mise en page textuelle par défaut, qui utilise des séparateurs verticaux :

2023-10-15 09:14:22.1145|INFO|Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker|Executed action TelemetryApp.Controllers.DashboardController.Overview (TelemetryApp) in 45.1203ms

Transition vers des journaux structurés en JSON

Le format textuel est lisible pour un développeur, mais difficile à analyser pour des outils d'agrégation comme Elasticsearch ou Splunk. Pour résoudre cela, transformez la sortie console en utilisant un JsonLayout.

"targets": {
  "async": true,
  "consoleTarget": {
    "type": "Console",
    "layout": {
      "type": "JsonLayout",
      "attributes": [
        { "name": "timestamp", "layout": "${date:universalTime=true}" },
        { "name": "application", "layout": "${processname}" },
        { "name": "environment", "layout": "${environment:ASPNETCORE_ENVIRONMENT}" },
        { "name": "severity", "layout": "${level}" },
        { "name": "source", "layout": "${logger}" },
        { "name": "message", "layout": "${message}" },
        { "name": "error_details", "layout": "${exception:format=toString}" },
        { "name": "http_method", "layout": "${aspnet-request-method}" },
        { "name": "http_url", "layout": "${aspnet-request-url}" },
        { "name": "mvc_controller", "layout": "${aspnet-mvc-controller}" },
        { "name": "mvc_action", "layout": "${aspnet-mvc-action}" }
      ]
    }
  }
}

Après redémarrage, la console affichera des documents JSON parfaitement structurés :

{
    "timestamp": "2023-10-15 09:25:11.912Z",
    "application": "TelemetryApp",
    "environment": "Development",
    "severity": "Info",
    "source": "TelemetryApp.Controllers.DashboardController",
    "message": "Accès au tableau de bord pour le profil { clientId = 42, region = EU-West }",
    "http_method": "GET",
    "http_url": "https://localhost:5001/",
    "mvc_controller": "Dashboard",
    "mvc_action": "Overview"
}

Les attributs tels que application et environment exploitent les renderers natifs de NLog. Les champs préfixés par http_ et mvc_ proviennent spécifiquement de l'extension NLog.Web.AspNetCore. C'est pourquoi la déclaration de l'assembly dans la section extensions de la configuration est stritcement nécessaire pour que ces variables soient résolues correctement au moment de l'exécution.

Étiquettes: NLog ASP.NET Core C# JSON logging

Publié le 21 juillet à 14h51