Journalisation dans .NET Core et ASP.NET Core

Par Kirk Larkin, Juergen Gutsch et Rick Anderson

Cette rubrique décrit la journalisation dans .NET, telle qu’elle s’applique aux applications ASP.NET Core. Pour plus d’informations sur la journalisation dans .NET, consultez Journalisation dans .NET. Pour plus d’informations sur la journalisation dans les applications Blazor, consultez Journalisation Blazor ASP.NET Core.

Fournisseurs de journalisation

Les fournisseurs de journalisation permettent de stocker les journaux, à l’exception du fournisseur Console qui permet d’afficher les journaux. Par exemple, le fournisseur Azure Application Insights stocke les journaux dans Azure Application Insights. Plusieurs fournisseurs peuvent être activés.

Les modèles d’application web ASP.NET Core par défaut appellent WebApplication.CreateBuilder, qui ajoute les fournisseurs de journalisation suivants :

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Le code précédent montre le fichier Program.cs créé à l’aide des modèles d’application web ASP.NET Core. Les sections suivantes fournissent des exemples basés sur les modèles d’application web ASP.NET Core.

Le code suivant remplace l’ensemble de fournisseurs de journalisation par défaut ajouté par WebApplication.CreateBuilder :

var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Vous pouvez également écrire le code de journalisation précédent de la façon suivante :

var builder = WebApplication.CreateBuilder();
builder.Host.ConfigureLogging(logging =>
{
    logging.ClearProviders();
    logging.AddConsole();
});

Pour connaître les autres fournisseurs, consultez :

Créer des journaux

Pour créer des journaux, utilisez un objet ILogger<TCategoryName> issu d’une injection de dépendances.

L’exemple suivant :

  • Crée un enregistreur d’événements (ILogger<AboutModel>) qui utilise une catégorie de journal pour le nom complet du type AboutModel. La catégorie du journal est une chaîne associée à chaque journal.
  • Appelle LogInformation pour journaliser au niveau Information. Le niveau du journal indique la gravité de l’événement consigné.
public class AboutModel : PageModel
{
    private readonly ILogger _logger;

    public AboutModel(ILogger<AboutModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        _logger.LogInformation("About page visited at {DT}", 
            DateTime.UtcNow.ToLongTimeString());
    }
}

Les niveaux et les catégories sont expliqués en détail plus loin dans ce document.

Pour plus d’informations sur Blazor, consultez Journalisation Blazor ASP.NET Core.

Configuration de la journalisation

La configuration de la journalisation est généralement fournie par la section Logging des fichiers appsettings.{ENVIRONMENT}.json, où l’espace réservé {ENVIRONMENT} correspond à l’environnement. Le fichier appsettings.Development.json suivant est généré par les modèles d’application web ASP.NET Core :

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

Dans le code JSON précédent :

  • Les catégories "Default" et "Microsoft.AspNetCore" sont spécifiées.
  • La catégorie "Microsoft.AspNetCore" s’applique à toutes les catégories qui commencent par "Microsoft.AspNetCore". Par exemple, ce paramètre s’applique à la catégorie "Microsoft.AspNetCore.Routing.EndpointMiddleware".
  • La catégorie "Microsoft.AspNetCore" journalise au niveau de journalisation Warning et aux niveaux supérieurs.
  • Aucun fournisseur de journaux n’est spécifié. LogLevel s’applique donc à tous les fournisseurs de journalisation activés, à l’exception de Windows EventLog.

La propriété Logging peut avoir des propriétés LogLevel et des propriétés de fournisseur de journaux. La propriété LogLevel spécifie le niveau de journalisation minimal pour les catégories sélectionnées. Dans le code JSON précédent, les niveaux de journalisation Information et Warning sont spécifiés. LogLevel indique le niveau de gravité du journal, qui peut varier de 0 à 6 :

Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5 et None = 6.

Quand LogLevel est spécifié, la journalisation est activée pour les messages au niveau spécifié et aux niveaux supérieurs. Dans le code JSON précédent, la catégorie Default est journalisée pour Information et niveaux supérieurs. Par exemple, les messages Information, Warning, Error et Critical sont journalisés. Si aucun n’est LogLevel spécifié, la journalisation est définie par défaut sur le niveau Information. Pour plus d’informations, consultez Niveaux de journalisation.

Une propriété de fournisseur peut spécifier une propriété LogLevel. Le LogLevel indiqué sous un fournisseur spécifie les niveaux à journaliser pour ce fournisseur, et remplace les paramètres de journalisation ne concernant pas le fournisseur. Examinons le fichier appsettings.json suivant :

{
  "Logging": {
    "LogLevel": { // All providers, LogLevel applies to all the enabled providers.
      "Default": "Error", // Default logging, Error and higher.
      "Microsoft": "Warning" // All Microsoft* categories, Warning and higher.
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information", // Overrides preceding LogLevel:Default setting.
        "Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category.
      }
    },
    "EventSource": { // EventSource provider
      "LogLevel": {
        "Default": "Warning" // All categories of EventSource provider.
      }
    }
  }
}

Les paramètres de Logging.{PROVIDER NAME}.LogLevel remplacent les paramètres de Logging.LogLevel, où l’espace réservé {PROVIDER NAME} correspond au nom du fournisseur. Dans le code JSON précédent, le niveau de journalisation par défaut du fournisseur Debug est défini sur Information :

Logging:Debug:LogLevel:Default:Information

Le paramètre précédent spécifie le niveau de journalisation Information pour chaque catégorie Logging:Debug:, sauf Microsoft.Hosting. Lorsqu’une catégorie spécifique est listée, celle-ci remplace la catégorie par défaut. Dans le code JSON précédent, les catégories Logging:Debug:LogLevel"Microsoft.Hosting" et "Default" remplacent les paramètres de Logging:LogLevel.

Le niveau de journalisation minimal peut être spécifié pour tous les éléments suivants :

  • Certains fournisseurs : par exemple, Logging:EventSource:LogLevel:Default:Information
  • Certaines catégories : par exemple, Logging:LogLevel:Microsoft:Warning
  • Tous les fournisseurs et toutes les catégories : Logging:LogLevel:Default:Warning

Les journaux situés en dessous du niveau minimal ne seront pas :

  • Passés au fournisseur.
  • Journalisés ou affichés.

Pour empêcher la génération de tous les journaux, spécifiez LogLevel.None. LogLevel.None a une valeur de 6, ce qui est supérieur à LogLevel.Critical (5).

Lorsqu’un fournisseur prend en charge les étendues de journal, IncludeScopes indique si elles sont activées. Pour plus d’informations, consultez Étendues de journalisation.

Le fichier appsettings.json suivant contient tous les fournisseurs activés par défaut :

{
  "Logging": {
    "LogLevel": { // No provider, LogLevel applies to all the enabled providers.
      "Default": "Error",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Warning"
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information" // Overrides preceding LogLevel:Default setting.
      }
    },
    "Console": {
      "IncludeScopes": true,
      "LogLevel": {
        "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
        "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
        "Microsoft.AspNetCore.Mvc.Razor": "Error",
        "Default": "Information"
      }
    },
    "EventSource": {
      "LogLevel": {
        "Microsoft": "Information"
      }
    },
    "EventLog": {
      "LogLevel": {
        "Microsoft": "Information"
      }
    },
    "AzureAppServicesFile": {
      "IncludeScopes": true,
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "AzureAppServicesBlob": {
      "IncludeScopes": true,
      "LogLevel": {
        "Microsoft": "Information"
      }
    },
    "ApplicationInsights": {
      "LogLevel": {
        "Default": "Information"
      }
    }
  }
}

Dans l’exemple précédent :

  • Les catégories et les niveaux ne sont pas des valeurs suggérées. L’exemple est fourni pour afficher la totalité des fournisseurs par défaut.
  • Les paramètres de Logging.{PROVIDER NAME}.LogLevel remplacent les paramètres de Logging.LogLevel, où l’espace réservé {PROVIDER NAME} correspond au nom du fournisseur. Par exemple, le niveau dans Debug.LogLevel.Default remplace le niveau dans LogLevel.Default.
  • Chaque alias de fournisseur par défaut est utilisé. Chaque fournisseur définit un alias qui peut être utilisé dans la configuration à la place du nom de type complet. Les alias de fournisseurs intégrés sont les suivants :
    • Console
    • Debug
    • EventSource
    • EventLog
    • AzureAppServicesFile
    • AzureAppServicesBlob
    • ApplicationInsights

Journal dans Program.cs

L’exemple suivant appelle Builder.WebApplication.Logger dans Program.cs et journalise les messages d’information :

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Logger.LogInformation("Adding Routes");
app.MapGet("/", () => "Hello World!");
app.Logger.LogInformation("Starting the app");
app.Run();

L’exemple suivant appelle AddConsole dans Program.cs et journalise le point de terminaison /Test :

var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddConsole();

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.MapGet("/Test", async (ILogger<Program> logger, HttpResponse response) =>
{
    logger.LogInformation("Testing logging in Program.cs");
    await response.WriteAsync("Testing");
});

app.Run();

L’exemple suivant appelle AddSimpleConsole dans Program.cs, désactive la sortie couleur et journalise le point de terminaison /Test :

using Microsoft.Extensions.Logging.Console;

var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddSimpleConsole(i => i.ColorBehavior = LoggerColorBehavior.Disabled);

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.MapGet("/Test", async (ILogger<Program> logger, HttpResponse response) =>
{
    logger.LogInformation("Testing logging in Program.cs");
    await response.WriteAsync("Testing");
});

app.Run();

Définir le niveau de journalisation à l’aide de la ligne de commande, de variables d’environnement et d’autres méthodes de configuration

Le niveau de journalisation peut être défini par l’un des fournisseurs de configuration.

Le séparateur : ne fonctionne pas avec les clés hiérarchiques des variables d’environnement sur toutes les plateformes. Le double trait de soulignement __ est :

  • Pris en charge par toutes les plateformes. Par exemple, le séparateur : n’est pas pris en charge par Bash, mais __ est pris en charge.
  • Remplacé automatiquement par :

Les commandes suivantes permettent de :

  • Définissez la clé d’environnement Logging:LogLevel:Microsoft sur la valeur Information dans Windows.
  • Testez les paramètres lorsque vous utilisez une application créée avec les modèles d’application web ASP.NET Core. La commande dotnet run doit être exécutée dans le répertoire du projet après l’utilisation de set.
set Logging__LogLevel__Microsoft=Information
dotnet run

Le paramètre d’environnement précédent :

  • Est uniquement défini dans les processus lancés à partir de la fenêtre de commande dans laquelle il a été défini.
  • Ne sera pas lu par les navigateurs lancés avec Visual Studio.

La commande setx suivante définit également la clé et la valeur d’environnement dans Windows. Contrairement à set, les paramètres setx sont persistants. Le commutateur /M définit la variable dans l’environnement système. Si /M n’est pas utilisé, une variable d’environnement utilisateur est définie.

setx Logging__LogLevel__Microsoft Information /M

Examinons le fichier appsettings.json suivant :

"Logging": {
  "Console": {
    "LogLevel": {
      "Microsoft.Hosting.Lifetime": "Trace"
    }
  }
}

La commande suivante définit la configuration précédente dans l’environnement :

setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M

Remarque

Quand vous configurez des variables d’environnement avec des noms qui contiennent . (des points) dans macOS et Linux, prenez en compte la question « Exporter une variable avec un point (.) » sur Stack Exchange et sa réponse acceptée correspondante.

Dans Azure App Service, sélectionnez Nouveau paramètre d’application dans la page Paramètres > Configuration. Les paramètres d’application Azure App Service sont :

  • Chiffrés au repos et transmis sur un canal chiffré.
  • Exposés en tant que variables d’environnement.

Pour plus d’informations, consultez Azure Apps : remplacer la configuration de l’application à l’aide du Portail Azure.

Pour plus d’informations sur la définition de valeurs de configuration ASP.NET Core à l’aide de variables d’environnement, consultez Variables d’environnement. Pour plus d’informations sur l’utilisation d’autres sources de configuration, notamment la ligne de commande, Azure Key Vault, Azure App Configuration, d’autres formats de fichiers, etc. consultez Configuration dans ASP.NET Core.

Mode d’application des règles de filtre

À la création d’un objet ILogger<TCategoryName>, l’objet ILoggerFactory sélectionne une seule règle à appliquer à cet enregistrement d’événements par fournisseur. Tous les messages écrits par une instance ILogger sont filtrés selon les règles sélectionnées. La règle la plus précise qui peut être appliquée à chaque paire catégorie/fournisseur est sélectionnée parmi les règles disponibles.

L’algorithme suivant est utilisé pour chaque fournisseur quand un objet ILogger est créé pour une catégorie donnée :

  • Sélectionnez toutes les règles qui correspondent au fournisseur ou à son alias. Si aucune correspondance n’est trouvée, sélectionnez toutes les règles avec un fournisseur vide.
  • À partir du résultat de l’étape précédente, sélectionnez les règles ayant le plus long préfixe de catégorie correspondant. Si aucune correspondance n’est trouvée, sélectionnez toutes les règles qui ne spécifient pas de catégorie.
  • Si plusieurs règles sont sélectionnées, prenez la dernière.
  • Si aucune règle n’est sélectionnée, utilisez MinimumLevel.

Journalisation de la sortie de l’exécution dotnet et Visual Studio

Les journaux créés à l’aide des fournisseurs de journalisation par défaut sont affichés :

  • Dans Visual Studio
    • Dans la fenêtre de sortie Débogage lors du débogage.
    • Dans la fenêtre ASP.NET Core Web Server.
  • Dans la fenêtre de console lorsque l’application est exécutée avec dotnet run.

Les journaux qui commencent par les catégories « Microsoft » proviennent du code du framework ASP.NET Core. ASP.NET Core et le code d’application utilisent la même API de journalisation et les mêmes fournisseurs.

Catégorie de journal

Quand un objet ILogger est créé, une catégorie est spécifiée. Cette catégorie est incluse dans tous les messages de journal créés par cette instance de ILogger. La chaîne de la catégorie est arbitraire, mais la convention est d’utiliser le nom complet de la classe. Par exemple, dans un contrôleur, le nom peut être "TodoApi.Controllers.TodoController". Les applications web ASP.NET Core utilisent ILogger<T> pour obtenir automatiquement une instance ILogger qui utilise le nom de type complet de T en tant que catégorie :

public class PrivacyModel : PageModel
{
    private readonly ILogger<PrivacyModel> _logger;

    public PrivacyModel(ILogger<PrivacyModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.PrivacyModel called.");
    }
}

SSi une catégorisation plus poussée est souhaitée, la convention consiste à utiliser un nom hiérarchique en ajoutant une sous-catégorie au nom de classe complet, et à spécifier explicitement la catégorie à l’aide de ILoggerFactory.CreateLogger :

public class ContactModel : PageModel
{
    private readonly ILogger _logger;

    public ContactModel(ILoggerFactory logger)
    {
        _logger = logger.CreateLogger("TodoApi.Pages.ContactModel.MyCategory");
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.ContactModel called.");
    }

L’appel de CreateLogger avec un nom fixe peut être utile si vous l’utilisez dans plusieurs méthodes afin que les événements puissent être organisés par catégorie.

ILogger<T> équivaut à appeler CreateLogger avec le nom de type complet T.

Log level

Le tableau suivant liste les valeurs LogLevel, la méthode d’extension de commodité Log{LogLevel}, ainsi que des suggestions d’utilisation :

LogLevel Valeur Méthode Description
Trace 0 LogTrace Contiennent les messages les plus détaillés. Ces messages peuvent contenir des données d’application sensibles. Ils sont désactivés par défaut et ne doivent pas être activés dans un environnement de production.
Debug 1 LogDebug Pour le débogage et le développement. À utiliser avec prudence dans un environnement de production en raison du volume élevé de messages.
Information 2 LogInformation Effectue le suivi du flux général de l’application. Peut avoir une valeur à long terme.
Warning 3 LogWarning Pour les événements anormaux ou inattendus. Comprend généralement des erreurs ou des conditions qui n’entraînent pas l’échec de l’application.
Error 4 LogError Fournit des informations sur des erreurs et des exceptions qui ne peuvent pas être gérées. Ces messages indiquent un échec de l’opération ou de la demande en cours, et non l’échec de l’application.
Critical 5 LogCritical Fournit des informations sur des échecs qui nécessitent un examen immédiat. Exemples : perte de données, espace disque insuffisant.
None 6 Spécifie qu’une catégorie de journalisation ne doit écrire aucun message.

Dans le tableau précédent, LogLevel est listé du plus faible niveau de gravité au plus élevé.

Le premier paramètre de la méthode Log (LogLevel) indique le niveau de gravité du journal. Au lieu d’appeler Log(LogLevel, ...), la plupart des développeurs appellent les méthodes d’extension Log{LOG LEVEL}, où l’espace réservé {LOG LEVEL} correspond au niveau de journalisation. Par exemple, les deux appels de journalisation suivants ont un fonctionnement équivalent et produisent le même journal :

[HttpGet]
public IActionResult Test1(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);

    _logger.Log(LogLevel.Information, MyLogEvents.TestItem, routeInfo);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    return ControllerContext.MyDisplayRouteInfo();
}

MyLogEvents.TestItem est l’ID de l’événement. MyLogEvents fait partie de l’exemple d’application et s’affiche dans la section ID d’événement du journal.

MyDisplayRouteInfo et ToCtxString sont fournis par le package NuGet Rick.Docs.Samples.RouteInfo. Les méthodes affichent les informations de routage Controller et Razor Page.

Le code suivant crée des journaux Information et Warning :

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

Dans le code précédent, le premier paramètre Log{LOG LEVEL} (MyLogEvents.GetItem) est l’ID de l’événement de journal. Le deuxième paramètre est un modèle de message contenant des espaces réservés pour les valeurs d’argument fournies par les autres paramètres de méthode. Les paramètres de méthode sont expliqués dans la section Modèle de message plus loin dans ce document.

Appelez la méthode Log{LOG LEVEL} appropriée pour contrôler le volume de la sortie de journal pouvant être écrite sur un support de stockage spécifique. Exemple :

  • En production :
    • La journalisation aux niveaux Trace, Debugou Information produit un volume élevé de messages de journal détaillés. Pour contrôler les coûts et ne pas dépasser les limites de stockage des données, journaliser Trace, Debugou Information messages de niveau vers un magasin de données à faible coût et à volume élevé. Envisagez de limiter Trace, Debugou Information à des catégories spécifiques.
    • La journalisation aux niveaux allant de Warning à Critical doivent produire moins de messages de journal.
      • Les coûts et les limites de stockage ne posent généralement pas problème.
      • Peu de journaux permettent une plus grande flexibilité au niveau du choix du magasin de données.
  • Lors du développement :
    • Réglez sur Warning.
    • Ajoutez Trace, Debugou Information messages lors de la résolution des problèmes. Pour limiter la sortie, définissez Trace, Debugou Information uniquement pour les catégories en cours d’examen.

ASP.NET Core écrit des journaux pour les événements de framework. Par exemple, tenez compte de la sortie du journal pour :

  • Une application Razor Pages créée avec les modèles ASP.NET Core.
  • Journalisation définie sur Logging:Console:LogLevel:Microsoft:Information.
  • Navigation vers la page Privacy :
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/Privacy
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/Privacy'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
      Route matched with {page = "/Privacy"}. Executing page /Privacy
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
      Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
      Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
      Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
      Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
      Executed page /Privacy in 74.5188ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/Privacy'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 149.3023ms 200 text/html; charset=utf-8

Le code JSON suivant définit Logging:Console:LogLevel:Microsoft:Information :

{
  "Logging": {      // Default, all providers.
    "LogLevel": {
      "Microsoft": "Warning"
    },
    "Console": { // Console provider.
      "LogLevel": {
        "Microsoft": "Information"
      }
    }
  }
}

ID d’événement de log

Chaque journal peut spécifier un ID d’événement. L’exemple d’application utilise la classe MyLogEvents pour définir les ID d’événement :

public class MyLogEvents
{
    public const int GenerateItems = 1000;
    public const int ListItems     = 1001;
    public const int GetItem       = 1002;
    public const int InsertItem    = 1003;
    public const int UpdateItem    = 1004;
    public const int DeleteItem    = 1005;

    public const int TestItem      = 3000;

    public const int GetItemNotFound    = 4000;
    public const int UpdateItemNotFound = 4001;
}
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

Un ID d’événement associe un jeu d’événements. Par exemple, tous les journaux liés à l’affichage d’une liste d’éléments sur une page peuvent être 1001.

Le fournisseur de journalisation peut stocker l’ID d’événement dans un champ ID, dans le message de journalisation, ou pas du tout. Le fournisseur Debug n’affiche pas les ID d’événements. Le fournisseur Console affiche les ID d’événements entre crochets après la catégorie :

info: TodoApi.Controllers.TodoItemsController[1002]
      Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
      Get(1) NOT FOUND

Certains fournisseurs de journalisation stockent l’ID d’événement dans un champ, ce qui permet de filtrer en fonction de l’ID.

Modèle de message de journal

Chaque API de journalisation utilise un modèle de message. Ce dernier peut contenir des espaces réservés pour lesquels les arguments sont fournis. Utilisez des noms et non des nombres pour les espaces réservés.

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

C’est l’ordre des paramètres, et non leur nom d’espace réservé, qui détermine les paramètres utilisés pour fournir des valeurs d’espace réservé dans les messages de journal. Dans le code suivant, les noms de paramètres ne sont pas dans l’ordre dans le modèle de message :

var apples = 1;
var pears = 2;
var bananas = 3;

_logger.LogInformation("Parameters: {Pears}, {Bananas}, {Apples}", apples, pears, bananas);

Cependant, les paramètres sont attribués aux espaces réservés dans l’ordre : apples, pears, bananas. Le message de journal reflète l’ordre des paramètres :

Parameters: 1, 2, 3

Cette approche permet aux fournisseurs de journalisation d’implémenter une journalisation sémantique ou structurée. Les arguments proprement dits, et pas seulement le modèle de message mis en forme, sont transmis au système de journalisation. Cela permet aux fournisseurs de journalisation de stocker les valeurs des paramètres sous forme de champs. Prenons l’exemple de la méthode d’enregistreur d’événements suivante :

_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);

Par exemple, lorsque vous journalisez des événements vers le Stockage Table Azure :

  • Chaque entité de table Azure peut avoir des propriétés ID et RequestTime.
  • Les tables avec des propriétés simplifient les requêtes qui sont exécutées sur des données journalisées. Par exemple, vous pouvez rechercher tous les journaux compris dans une plage RequestTime spécifique, sans avoir besoin d’analyser le délai d’expiration du message texte.

Enregistrer des exceptions

Les méthodes d’enregistreur d’événements ont des surcharges qui prennent un paramètre d’exception :

[HttpGet("{id}")]
public IActionResult TestExp(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    try
    {
        if (id == 3)
        {
            throw new Exception("Test exception");
        }
    }
    catch (Exception ex)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, ex, "TestExp({Id})", id);
        return NotFound();
    }

    return ControllerContext.MyDisplayRouteInfo();
}

MyDisplayRouteInfo et ToCtxString sont fournis par le package NuGet Rick.Docs.Samples.RouteInfo. Les méthodes affichent les informations de routage Controller et Razor Page.

La journalisation des exceptions dépend du fournisseur.

Niveau de journalisation par défaut

Si le niveau de journalisation par défaut n’est pas défini, la valeur sera Information.

Prenons l’exemple de l’application web suivante :

  • Créée avec les modèles d’application web ASP.NET.
  • appsettings.json et appsettings.Development.json ont été supprimés ou renommés.

Avec la configuration précédente, l’accès à la page de confidentialité ou d’accueil produit de nombreux messages Trace, Debug et Information de catégorie Microsoft.

Le code suivant définit le niveau de journalisation par défaut lorsque celui-ci n’est pas défini dans la configuration :

var builder = WebApplication.CreateBuilder();
builder.Logging.SetMinimumLevel(LogLevel.Warning);

En règle générale, les niveaux de journalisation doivent être spécifiés dans la configuration et non dans le code.

fonction Filter

Une fonction de filtre est appelée pour tous les fournisseurs et toutes les catégories auxquels aucune règle n’est affectée dans la configuration ou dans le code :

var builder = WebApplication.CreateBuilder();
builder.Logging.AddFilter((provider, category, logLevel) =>
{
    if (provider.Contains("ConsoleLoggerProvider")
        && category.Contains("Controller")
        && logLevel >= LogLevel.Information)
    {
        return true;
    }
    else if (provider.Contains("ConsoleLoggerProvider")
        && category.Contains("Microsoft")
        && logLevel >= LogLevel.Information)
    {
        return true;
    }
    else
    {
        return false;
    }
});

Le code précédent affiche les journaux de console lorsque la catégorie contient Controller ou Microsoft, et si le niveau de journalisation est Information ou supérieur.

En règle générale, les niveaux de journalisation doivent être spécifiés dans la configuration et non dans le code.

ASP.NET Core et catégories EF Core

Le tableau suivant contient certaines catégories utilisées par ASP.NET Core et Entity Framework Core, ainsi que des notes à propos des journaux :

Catégorie Notes
Microsoft.AspNetCore Diagnostics ASP.NET Core généraux.
Microsoft.AspNetCore.DataProtection Liste des clés considérées, trouvées et utilisées.
Microsoft.AspNetCore.HostFiltering Hôtes autorisés.
Microsoft.AspNetCore.Hosting Temps de traitement des requêtes HTTP et heure de démarrage. Liste des assemblys de démarrage d’hébergement chargés.
Microsoft.AspNetCore.Mvc Diagnostics MVC et Razor. Liaison de données, exécution de filtres, compilation de vues, sélection d’actions.
Microsoft.AspNetCore.Routing Informations de correspondance des itinéraires.
Microsoft.AspNetCore.Server Démarrage et arrêt de la connexion, et réponses persistantes. Informations du certificat HTTPS.
Microsoft.AspNetCore.StaticFiles Fichiers pris en charge.
Microsoft.EntityFrameworkCore Diagnostics Entity Framework Core généraux. Activité et configuration de la base de données, détection des modifications, migrations.

Pour afficher d’autres catégories dans la fenêtre de console, définissez appsettings.Development.json sur la valeur suivante :

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

Étendues de journal

Une étendue peut regrouper un ensemble d’opérations logiques. Ce regroupement permet de joindre les mêmes données à tous les journaux créés au sein d’un ensemble. Par exemple, chaque journal créé dans le cadre du traitement d’une transaction peut contenir l’ID de la transaction.

Une étendue :

Les fournisseurs suivants prennent en charge les étendues :

Utilisez une étendue en incluant les appels de l’enregistrement d’événements dans un bloc using :

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    TodoItem todoItem;
    var transactionId = Guid.NewGuid().ToString();
    using (_logger.BeginScope(new List<KeyValuePair<string, object>>
        {
            new KeyValuePair<string, object>("TransactionId", transactionId),
        }))
    {
        _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

        todoItem = await _context.TodoItems.FindAsync(id);

        if (todoItem == null)
        {
            _logger.LogWarning(MyLogEvents.GetItemNotFound, 
                "Get({Id}) NOT FOUND", id);
            return NotFound();
        }
    }

    return ItemToDTO(todoItem);
}

Fournisseurs de journalisation intégrés

ASP.NET Core inclut les fournisseurs de journalisation suivants dans le cadre du framework partagé :

Les fournisseurs de journalisation suivants sont fournis par Microsoft, mais pas dans le cadre du framework partagé. Ils doivent être installés en tant que NuGet supplémentaire.

ASP.NET Core n’inclut pas de fournisseur de journalisation permettant d’écrire des journaux dans des fichiers. Pour écrire des journaux d’activité dans des fichiers à partir d’une application ASP.NET Core, vous pouvez utiliser un fournisseur de journalisation tiers.

Pour plus d’informations sur stdout et sur la journalisation du débogage avec le module ASP.NET Core, consultez Résoudre les problèmes liés à ASP.NET Core sur Azure App Service et IIS et Module ASP.NET Core (ANCM) pour IIS.

Console

Le fournisseur Console journalise la sortie de la console. Pour plus d’informations sur l’affichage des journaux Console durant la phase de développement, consultez Journalisation de la sortie de l’exécution dotnet et Visual Studio.

Débogage

Le fournisseur Debug écrit la sortie du journal à l’aide de la classe System.Diagnostics.Debug. Les appels à System.Diagnostics.Debug.WriteLine sont écrits dans le fournisseur Debug.

Sur Linux, l’emplacement du journal du fournisseur Debug dépend de la distribution et peut être l’un des emplacements suivants :

  • /var/log/message
  • /var/log/syslog

Source de l’événement

Le fournisseur EventSource écrit les données dans une source d’événements multiplateforme portant le nom de Microsoft-Extensions-Logging. Sur Windows, le fournisseur utilise ETW.

Outils dotnet-trace

L’outil dotnet-trace est un outil CLI multiplateforme qui permet la collection de traces .NET Core issues d’un processus en cours d’exécution. L’outil collecte des données de fournisseur Microsoft.Extensions.Logging.EventSource à l’aide d’un LoggingEventSource.

Pour obtenir des instructions d’installation, consultez dotnet-trace.

Utilisez les outils dotnet-trace pour collecter une trace à partir d’une application :

  1. Exécutez l’application avec la commande dotnet run.

  2. Déterminez l’identificateur de processus (PID) de l’application .NET Core :

    dotnet-trace ps
    

    Recherchez le PID du processus qui porte le même nom que l’assembly de l’application.

  3. Exécutez la commande dotnet-trace.

    Syntaxe de commande générale :

    dotnet-trace collect -p {PID} 
        --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Category Level 1};
                {Logger Category 2}:{Category Level 2};
                ...
                {Logger Category N}:{Category Level N}\"
    

    Lorsque vous utilisez un interpréteur de commandes PowerShell, placez la valeur --providers entre guillemets simples (') :

    dotnet-trace collect -p {PID} 
        --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Category Level 1};
                {Logger Category 2}:{Category Level 2};
                ...
                {Logger Category N}:{Category Level N}\"'
    

    Sur les plateformes autres que Windows, ajoutez l’option -f speedscope pour remplacer le format du fichier de trace de sortie par speedscope.

    Le tableau suivant définit le mot clé :

    Mot clé Description
    1 Journalise les événements meta à propos de LoggingEventSource. Ne journalise pas les événements provenant de ILogger.
    2 Active l’événement Message lors de l’appel de ILogger.Log(). Fournit les informations de façon programmatique (sans mise en forme).
    4 Active l’événement FormatMessage lors de l’appel de ILogger.Log(). Fournit la version de chaîne mise en forme des informations.
    8 Active l’événement MessageJson lors de l’appel de ILogger.Log(). Fournit une représentation JSON des arguments.

    Le tableau suivant liste les niveaux fournisseur :

    Niveau fournisseur Description
    0 LogAlways
    1 Critical
    2 Error
    3 Warning
    4 Informational
    5 Verbose

    L’analyse d’un niveau de catégorie peut être une chaîne ou un nombre :

    Valeur nommée de catégorie Valeur numérique
    Trace 0
    Debug 1
    Information 2
    Warning 3
    Error 4
    Critical 5

    Le niveau fournisseur et le niveau catégorie :

    • Sont dans l’ordre inverse.
    • Les constantes de chaîne ne sont pas toutes identiques.

    Si aucune FilterSpecs n’est spécifiée, l’implémentation de EventSourceLogger tente de convertir le niveau fournisseur en niveau catégorie, et l’applique à toutes les catégories.

    Niveau fournisseur Niveau catégorie
    Verbose(5) Debug(1)
    Informational(4) Information(2)
    Warning(3) Warning(3)
    Error(2) Error(4)
    Critical(1) Critical(5)

    Si des FilterSpecs sont fournies, toutes les catégories incluses dans la liste utiliseront le niveau catégorie qui y est encodé. Toutes les autres catégories seront filtrées.

    Les exemples suivants supposent ce qui suit :

    • Une application s’exécute et appelle logger.LogDebug("12345").
    • L’ID de processus (PID) a été défini via set PID=12345, où 12345 est le PID réel.

    Prenez la commande suivante :

    dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5
    

    La commande précédente :

    • Capture les messages de débogage.
    • Ne s’applique pas aux FilterSpecs.
    • Spécifie le niveau 5 qui mappe la catégorie Débogage.

    Prenez la commande suivante :

    dotnet-trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:5\"
    

    La commande précédente :

    • Ne capture pas les messages de débogage, car le niveau de catégorie 5 est Critical.
    • Fournit des FilterSpecs.

    La commande suivante capture les messages de débogage, car le niveau de catégorie 1 spécifie Debug.

    dotnet-trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\"
    

    La commande suivante capture les messages de débogage, car la catégorie 1 spécifie Debug.

    dotnet-trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\"
    

    Les entrées FilterSpecs pour {Logger Category} et {Category Level} représentent des conditions de filtrage des journaux supplémentaires. Séparez les entrées FilterSpecs par un point-virgule (;).

    Exemple utilisant un interpréteur de commandes Windows :

    dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"
    

    La commande précédente active :

    • L’enregistreur d’événements source afin de produire des chaînes mises en forme (4) pour les erreurs (2).
    • La journalisation Microsoft.AspNetCore.Hosting au niveau de journalisation Informational (4).
  4. Arrêtez les outils dotnet-trace en appuyant sur la touche Entrée ou sur Ctrl+C.

    La trace est enregistrée sous le nom trace.nettrace dans le dossier où la commande dotnet-trace est exécutée.

  5. Ouvrez la trace avec Perfview. Ouvrez le fichier trace.nettrace et explorez les événements de trace.

Si l’application ne génère pas l’hôte avec WebApplication.CreateBuilder, ajoutez le fournisseur de source d’événements à la configuration de journalisation de l’application.

Pour plus d'informations, consultez les pages suivantes :

Perfview

Utilisez l’utilitaire PerfView pour collecter et afficher les journaux. Il existe d’autres outils d’affichage des journaux ETW, mais PerfView est l’outil recommandé pour gérer les événements ETW générés par ASP.NET Core.

Pour configurer PerfView afin qu’il collecte les événements enregistrés par ce fournisseur, ajoutez la chaîne *Microsoft-Extensions-Logging à la liste des fournisseurs supplémentaires. N’oubliez pas d’inclure le * au début de la chaîne.

Journal des événements Windows

Le fournisseur EventLog envoie la sortie de journal dans le journal des événements Windows. Contrairement aux autres fournisseurs, le fournisseur EventLog n’hérite pas des paramètres par défaut qui ne sont pas relatifs au fournisseur. Si les paramètres du journal EventLog ne sont pas spécifiés, leur valeur par défaut est LogLevel.Warning.

Pour journaliser les événements inférieurs à LogLevel.Warning, définissez explicitement le niveau de journalisation. L’exemple suivant définit le niveau de journalisation par défaut du journal des événements sur LogLevel.Information :

"Logging": {
  "EventLog": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

Les surcharges AddEventLog peuvent passer EventLogSettings. Si la valeur est null ou non spécifiée, les paramètres par défaut suivants sont utilisés :

  • LogName : "Application"
  • SourceName : ".NET Runtime"
  • MachineName : le nom de l’ordinateur local est utilisé.

Le code suivant remplace la valeur par défaut de SourceName (".NET Runtime") par MyLogs :


var builder = WebApplication.CreateBuilder();
builder.Logging.AddEventLog(eventLogSettings =>
{
    eventLogSettings.SourceName = "MyLogs";
});

Azure App Service

Le package de fournisseur Microsoft.Extensions.Logging.AzureAppServices écrit les journaux dans des fichiers texte dans le système de fichiers d’une application Azure App Service, ainsi que dans un stockage Blob dans un compte de stockage Azure.

Le fournisseur de package n’est pas inclus dans le framework partagé. Pour utiliser le fournisseur, ajoutez le package du fournisseur au projet.

Pour configurer les paramètres du fournisseur, utilisez AzureFileLoggerOptions et AzureBlobLoggerOptions, comme illustré dans l’exemple suivant :

using Microsoft.Extensions.Logging.AzureAppServices;

var builder = WebApplication.CreateBuilder();
builder.Logging.AddAzureWebAppDiagnostics();
builder.Services.Configure<AzureFileLoggerOptions>(options =>
{
    options.FileName = "azure-diagnostics-";
    options.FileSizeLimit = 50 * 1024;
    options.RetainedFileCountLimit = 5;
});
builder.Services.Configure<AzureBlobLoggerOptions>(options =>
{
    options.BlobName = "log.txt";
});

Si elle est déployée dans Azure App Service, l’application utilise les paramètres qui sont définis dans la section Journaux App Service de la page App Service du portail Azure. Quand les paramètres suivants sont mis à jour, les changements prennent effet immédiatement sans avoir besoin de redémarrer ou redéployer l’application.

  • Journalisation des applications (système de fichiers)
  • Journalisation des applications (objet blob)

L’emplacement par défaut des fichiers journaux est le dossier D:\\home\\LogFiles\\Application, et le nom de fichier par défaut est diagnostics-yyyymmdd.txt. La limite de taille de fichier par défaut est de 10 Mo, et le nombre maximal de fichiers conservés par défaut est de 2. Le nom d’objet blob par défaut est {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt.

Ce fournisseur journalise uniquement quand le projet s’exécute dans l’environnement Azure.

Streaming des journaux Azure

Le streaming de journaux Azure prend en charge l’affichage de l’activité des journaux en temps réel provenant du :

  • Serveur d'applications
  • Serveur web
  • Suivi des demandes ayant échoué

Pour configurer le streaming des journaux Azure :

  • Accédez à la page Journaux App Service dans le portail de l’application.
  • Définissez Journal des applications (Système de fichiers) sur Activé.
  • Choisissez le niveau du journal. Ce paramètre s’applique uniquement au streaming de journaux Azure.

Accédez à la page Streaming des journaux pour afficher les journaux. Les messages journalisés le sont avec l’interface ILogger.

Azure Application Insights

Le package de fournisseur Microsoft.Extensions.Logging.ApplicationInsights écrit les journaux dans Azure Application Insights. Application Insights est un service qui surveille une application web et fournit des outils pour interroger et analyser les données de télémétrie. Si vous utilisez ce fournisseur, vous pouvez interroger et analyser vos journaux à l’aide des outils Application Insights.

Le fournisseur de journalisation est inclus en tant que dépendance de Microsoft.ApplicationInsights.AspNetCore, qui est le package qui fournit toutes les données de télémétrie disponibles pour ASP.NET Core. Si vous utilisez ce package, vous n’avez pas besoin d’installer le package du fournisseur.

Le package Microsoft.ApplicationInsights.Web est destiné à ASP.NET 4.x, et non à ASP.NET Core.

Pour plus d’informations, consultez les ressources suivantes :

Fournisseurs de journalisation tiers

Frameworks de journalisation tiers qui sont pris en charge dans ASP.NET Core :

Certains frameworks tiers prennent en charge la journalisation sémantique, également appelée journalisation structurée.

L’utilisation d’un framework tiers est semblable à l’utilisation des fournisseurs intégrés :

  1. Ajoutez un package NuGet à votre projet.
  2. Appelez une méthode d’extension ILoggerFactory fournie par le framework de journalisation.

Pour plus d’informations, consultez la documentation de chaque fournisseur. Les fournisseurs de journalisation tiers ne sont pas pris en charge par Microsoft.

Aucune méthode d’enregistreur d’événements asynchrone

La journalisation doit être suffisamment rapide par rapport au coût du code asynchrone en matière de performances. Si un magasin de données de journalisation est lent, n’écrivez pas de données directement dedans. Écrivez les messages de journal dans un magasin rapide, puis déplacez-les vers le magasin lent. Par exemple, lorsque vous vous connectez à SQL Server, ne le faites pas directement dans une méthode Log, puisque les méthodes Log sont synchrones. Ajoutez plutôt de façon synchronisée des messages de journal à une file d’attente en mémoire, puis configurez un traitement en arrière-plan afin d’extraire les messages de la file d’attente et d’effectuer le travail asynchrone d’envoi des données vers SQL Server. Pour plus d’informations, consultez Guidance on how to log to a message queue for slow data stores (dotnet/AspNetCore.Docs n° 11801).

Modifier les niveaux de journalisation dans une application en cours d’exécution

L’API de journalisation ne permet pas de modifier les niveaux de journalisation pendant l’exécution d’une application. Toutefois, certains fournisseurs de configuration sont capables de recharger la configuration, ce qui agit immédiatement sur la configuration de la journalisation. Par exemple, File Configuration Provider recharge la configuration de journalisation par défaut. Si la configuration est modifiée dans le code pendant l’exécution d’une application, celle-ci peut appeler IConfigurationRoot.Reload pour mettre à jour la configuration de journalisation de l’application.

ILogger et ILoggerFactory

Les interfaces et les implémentations ILogger<TCategoryName> et ILoggerFactory sont incluses dans le SDK .NET Core. Elles sont également disponibles dans les packages NuGet suivants :

Appliquer des règles de filtre de journaux dans le code

Pour définir des règles de filtre de journaux, l’approche recommandée consiste à utiliser Configuration.

L'exemple suivant montre comment enregistrer des règles de filtre dans le code :

using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Logging.Debug;

var builder = WebApplication.CreateBuilder();
builder.Logging.AddFilter("System", LogLevel.Debug);
builder.Logging.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information);
builder.Logging.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace);

logging.AddFilter("System", LogLevel.Debug) spécifie la catégorie System et le niveau de journalisation Debug. Le filtre est appliqué à tous les fournisseurs, car aucun fournisseur spécifique n’a été configuré.

AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information) spécifie :

  • Le fournisseur de journalisation Debug.
  • Le niveau de journalisation Information et niveaux supérieurs.
  • Toutes les catégories commençant par "Microsoft".

Journalisez automatiquement l’étendue avec SpanId, TraceId, ParentId, Baggage et Tags.

Les bibliothèques de journalisation créent implicitement un objet d’étendue avec SpanId, TraceId, ParentId,Baggage et Tags. Ce comportement est configuré via ActivityTrackingOptions.

var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddSimpleConsole(options =>
{
    options.IncludeScopes = true;
});

builder.Logging.Configure(options =>
{
    options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
                                       | ActivityTrackingOptions.TraceId
                                       | ActivityTrackingOptions.ParentId
                                       | ActivityTrackingOptions.Baggage
                                       | ActivityTrackingOptions.Tags;
});
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

Si l’en-tête de requête HTTP traceparent est défini, le ParentId dans l’étendue du journal affiche le parent-id W3C issu de l’en-tête entrant traceparent, et le SpanId dans l’étendue du journal affiche le parent-id mis à jour pour l’étape/l’étendue sortante suivante. Pour plus d’informations, consultez Mutating the traceparent Field.

Créer un enregistreur d’événements personnalisé

Pour créer un enregistreur d’événements personnalisé, consultez Implémenter un fournisseur de journalisation personnalisé dans .NET.

Ressources supplémentaires

Par Kirk Larkin, Juergen Gutsch et Rick Anderson

Cette rubrique décrit la journalisation dans .NET, telle qu’elle s’applique aux applications ASP.NET Core. Pour plus d’informations sur la journalisation dans .NET, consultez Journalisation dans .NET. Pour plus d’informations sur la journalisation dans les applications Blazor, consultez Journalisation Blazor ASP.NET Core.

Affichez ou téléchargez un exemple de code (procédure de téléchargement).

Fournisseurs de journalisation

Les fournisseurs de journalisation permettent de stocker les journaux, à l’exception du fournisseur Console qui permet d’afficher les journaux. Par exemple, le fournisseur Azure Application Insights stocke les journaux dans Azure Application Insights. Plusieurs fournisseurs peuvent être activés.

Les modèles d’application web ASP.NET Core par défaut :

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

Le code précédent montre la classe Program créée à l’aide des modèles d’application web ASP.NET Core. Les sections suivantes fournissent des exemples basés sur les modèles d’application web ASP.NET Core, qui utilisent l’hôte générique. Les applications console non hôtes sont abordées plus loin dans ce document.

Pour remplacer l’ensemble par défaut de fournisseurs de journalisation ajoutés par Host.CreateDefaultBuilder, appelez ClearProviders puis ajoutez les fournisseurs de journalisation nécessaires. Par exemple, le code suivant :

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            logging.AddConsole();
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Pour connaître les autres fournisseurs, consultez :

Créer des journaux

Pour créer des journaux, utilisez un objet ILogger<TCategoryName> issu d’une injection de dépendances.

L’exemple suivant :

  • Crée un enregistreur d’événements (ILogger<AboutModel>) qui utilise une catégorie de journal pour le nom complet du type AboutModel. La catégorie du journal est une chaîne associée à chaque journal.
  • Appelle LogInformation pour journaliser au niveau Information. Le niveau du journal indique la gravité de l’événement consigné.
public class AboutModel : PageModel
{
    private readonly ILogger _logger;

    public AboutModel(ILogger<AboutModel> logger)
    {
        _logger = logger;
    }
    public string Message { get; set; }

    public void OnGet()
    {
        Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
        _logger.LogInformation(Message);
    }
}

Les niveaux et les catégories sont expliqués en détail plus loin dans ce document.

Pour plus d’informations sur Blazor, consultez Journalisation Blazor ASP.NET Core.

Créer des journaux dans Main et Startup montre comment créer des journaux dans Main et Startup.

Configuration de la journalisation

La configuration de la journalisation est généralement fournie par la section Logging des fichiers appsettings.{Environment}.json. Le fichier appsettings.Development.json suivant est généré par les modèles d’application web ASP.NET Core :

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

Dans le code JSON précédent :

  • Les catégories "Default", "Microsoft" et "Microsoft.Hosting.Lifetime" sont spécifiées.
  • La catégorie "Microsoft" s’applique à toutes les catégories qui commencent par "Microsoft". Par exemple, ce paramètre s’applique à la catégorie "Microsoft.AspNetCore.Routing.EndpointMiddleware".
  • La catégorie "Microsoft" journalise au niveau de journalisation Warning et aux niveaux supérieurs.
  • La catégorie "Microsoft.Hosting.Lifetime" est plus précise que la catégorie "Microsoft". La catégorie "Microsoft.Hosting.Lifetime" journalise donc au niveau « Informations » et aux niveaux supérieurs.
  • Aucun fournisseur de journaux n’est spécifié. LogLevel s’applique donc à tous les fournisseurs de journalisation activés, à l’exception de Windows EventLog.

La propriété Logging peut avoir des propriétés LogLevel et des propriétés de fournisseur de journaux. La propriété LogLevel spécifie le niveau de journalisation minimal pour les catégories sélectionnées. Dans le code JSON précédent, les niveaux de journalisation Information et Warning sont spécifiés. LogLevel indique le niveau de gravité du journal, qui peut varier de 0 à 6 :

Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5 et None = 6.

Quand LogLevel est spécifié, la journalisation est activée pour les messages au niveau spécifié et aux niveaux supérieurs. Dans le code JSON précédent, la catégorie Default est journalisée pour Information et niveaux supérieurs. Par exemple, les messages Information, Warning, Error et Critical sont journalisés. Si aucun n’est LogLevel spécifié, la journalisation est définie par défaut sur le niveau Information. Pour plus d’informations, consultez Niveaux de journalisation.

Une propriété de fournisseur peut spécifier une propriété LogLevel. Le LogLevel indiqué sous un fournisseur spécifie les niveaux à journaliser pour ce fournisseur, et remplace les paramètres de journalisation ne concernant pas le fournisseur. Examinons le fichier appsettings.json suivant :

{
  "Logging": {
    "LogLevel": { // All providers, LogLevel applies to all the enabled providers.
      "Default": "Error", // Default logging, Error and higher.
      "Microsoft": "Warning" // All Microsoft* categories, Warning and higher.
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information", // Overrides preceding LogLevel:Default setting.
        "Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category.
      }
    },
    "EventSource": { // EventSource provider
      "LogLevel": {
        "Default": "Warning" // All categories of EventSource provider.
      }
    }
  }
}

Les paramètres de Logging.{providername}.LogLevel remplacent les paramètres de Logging.LogLevel. Dans le code JSON précédent, le niveau de journalisation par défaut du fournisseur Debug est défini sur Information :

Logging:Debug:LogLevel:Default:Information

Le paramètre précédent spécifie le niveau de journalisation Information pour chaque catégorie Logging:Debug:, sauf Microsoft.Hosting. Lorsqu’une catégorie spécifique est listée, celle-ci remplace la catégorie par défaut. Dans le code JSON précédent, les catégories Logging:Debug:LogLevel"Microsoft.Hosting" et "Default" remplacent les paramètres de Logging:LogLevel.

Le niveau de journalisation minimal peut être spécifié pour tous les éléments suivants :

  • Certains fournisseurs : par exemple, Logging:EventSource:LogLevel:Default:Information
  • Certaines catégories : par exemple, Logging:LogLevel:Microsoft:Warning
  • Tous les fournisseurs et toutes les catégories : Logging:LogLevel:Default:Warning

Les journaux situés en dessous du niveau minimal ne seront pas :

  • Passés au fournisseur.
  • Journalisés ou affichés.

Pour supprimer tous les journaux, spécifiez LogLevel.None. LogLevel.None a une valeur de 6, ce qui est supérieur à LogLevel.Critical (5).

Lorsqu’un fournisseur prend en charge les étendues de journal, IncludeScopes indique si elles sont activées. Pour plus d’informations, consultez Étendues de journalisation.

Le fichier appsettings.json suivant contient tous les fournisseurs activés par défaut :

{
  "Logging": {
    "LogLevel": { // No provider, LogLevel applies to all the enabled providers.
      "Default": "Error",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Warning"
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information" // Overrides preceding LogLevel:Default setting.
      }
    },
    "Console": {
      "IncludeScopes": true,
      "LogLevel": {
        "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
        "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
        "Microsoft.AspNetCore.Mvc.Razor": "Error",
        "Default": "Information"
      }
    },
    "EventSource": {
      "LogLevel": {
        "Microsoft": "Information"
      }
    },
    "EventLog": {
      "LogLevel": {
        "Microsoft": "Information"
      }
    },
    "AzureAppServicesFile": {
      "IncludeScopes": true,
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "AzureAppServicesBlob": {
      "IncludeScopes": true,
      "LogLevel": {
        "Microsoft": "Information"
      }
    },
    "ApplicationInsights": {
      "LogLevel": {
        "Default": "Information"
      }
    }
  }
}

Dans l’exemple précédent :

  • Les catégories et les niveaux ne sont pas des valeurs suggérées. L’exemple est fourni pour afficher tous les fournisseurs par défaut.
  • Les paramètres de Logging.{providername}.LogLevel remplacent les paramètres de Logging.LogLevel. Par exemple, le niveau dans Debug.LogLevel.Default remplace le niveau dans LogLevel.Default.
  • Chaque alias de fournisseur par défaut est utilisé. Chaque fournisseur définit un alias qui peut être utilisé dans la configuration à la place du nom de type complet. Les alias de fournisseurs intégrés sont les suivants :
    • Console
    • Déboguer
    • EventSource
    • EventLog
    • AzureAppServicesFile
    • AzureAppServicesBlob
    • ApplicationInsights

Définir le niveau de journalisation à l’aide de la ligne de commande, de variables d’environnement et d’autres méthodes de configuration

Le niveau de journalisation peut être défini par l’un des fournisseurs de configuration.

Le séparateur : ne fonctionne pas avec les clés hiérarchiques des variables d’environnement sur toutes les plateformes. Le double trait de soulignement __ est :

  • Pris en charge par toutes les plateformes. Par exemple, le séparateur : n’est pas pris en charge par Bash, mais __ est pris en charge.
  • Remplacé automatiquement par :

Les commandes suivantes permettent de :

  • Définissez la clé d’environnement Logging:LogLevel:Microsoft sur la valeur Information dans Windows.
  • Testez les paramètres lorsque vous utilisez une application créée avec les modèles d’application web ASP.NET Core. La commande dotnet run doit être exécutée dans le répertoire du projet après l’utilisation de set.
set Logging__LogLevel__Microsoft=Information
dotnet run

Le paramètre d’environnement précédent :

  • Est uniquement défini dans les processus lancés à partir de la fenêtre de commande dans laquelle il a été défini.
  • Ne sera pas lu par les navigateurs lancés avec Visual Studio.

La commande setx suivante définit également la clé et la valeur d’environnement dans Windows. Contrairement à set, les paramètres setx sont persistants. Le commutateur /M définit la variable dans l’environnement système. Si /M n’est pas utilisé, une variable d’environnement utilisateur est définie.

setx Logging__LogLevel__Microsoft Information /M

Examinons le fichier appsettings.json suivant :

"Logging": {
    "Console": {
      "LogLevel": {
        "Microsoft.Hosting.Lifetime": "Trace"
      }
    }
}

La commande suivante définit la configuration précédente dans l’environnement :

setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M

Dans Azure App Service, sélectionnez Nouveau paramètre d’application dans la page Paramètres > Configuration. Les paramètres d’application Azure App Service sont :

  • Chiffrés au repos et transmis sur un canal chiffré.
  • Exposés en tant que variables d’environnement.

Pour plus d’informations, consultez Azure Apps : remplacer la configuration de l’application à l’aide du portail Azure.

Pour plus d’informations sur la définition de valeurs de configuration ASP.NET Core à l’aide de variables d’environnement, consultez Variables d’environnement. Pour plus d’informations sur l’utilisation d’autres sources de configuration, notamment la ligne de commande, Azure Key Vault, Azure App Configuration, d’autres formats de fichiers, etc. consultez Configuration dans ASP.NET Core.

Mode d’application des règles de filtre

À la création d’un objet ILogger<TCategoryName>, l’objet ILoggerFactory sélectionne une seule règle à appliquer à cet enregistrement d’événements par fournisseur. Tous les messages écrits par une instance ILogger sont filtrés selon les règles sélectionnées. La règle la plus précise qui peut être appliquée à chaque paire catégorie/fournisseur est sélectionnée parmi les règles disponibles.

L’algorithme suivant est utilisé pour chaque fournisseur quand un objet ILogger est créé pour une catégorie donnée :

  • Sélectionnez toutes les règles qui correspondent au fournisseur ou à son alias. Si aucune correspondance n’est trouvée, sélectionnez toutes les règles avec un fournisseur vide.
  • À partir du résultat de l’étape précédente, sélectionnez les règles ayant le plus long préfixe de catégorie correspondant. Si aucune correspondance n’est trouvée, sélectionnez toutes les règles qui ne spécifient pas de catégorie.
  • Si plusieurs règles sont sélectionnées, prenez la dernière.
  • Si aucune règle n’est sélectionnée, utilisez MinimumLevel.

Journalisation de la sortie de l’exécution dotnet et Visual Studio

Les journaux créés à l’aide des fournisseurs de journalisation par défaut sont affichés :

  • Dans Visual Studio
    • Dans la fenêtre de sortie Débogage lors du débogage.
    • Dans la fenêtre ASP.NET Core Web Server.
  • Dans la fenêtre de console lorsque l’application est exécutée avec dotnet run.

Les journaux qui commencent par les catégories « Microsoft » proviennent du code du framework ASP.NET Core. ASP.NET Core et le code d’application utilisent la même API de journalisation et les mêmes fournisseurs.

Catégorie de journal

Quand un objet ILogger est créé, une catégorie est spécifiée. Cette catégorie est incluse dans tous les messages de journal créés par cette instance de ILogger. La chaîne de catégorie est arbitraire, cependant, la convention veut que l’on utilise le nom de la classe. Par exemple, dans un contrôleur, le nom peut être "TodoApi.Controllers.TodoController". Les applications web ASP.NET Core utilisent ILogger<T> pour obtenir automatiquement une instance ILogger qui utilise le nom de type complet de T en tant que catégorie :

public class PrivacyModel : PageModel
{
    private readonly ILogger<PrivacyModel> _logger;

    public PrivacyModel(ILogger<PrivacyModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.PrivacyModel called.");
    }
}

Pour spécifier explicitement la catégorie, appelez ILoggerFactory.CreateLogger :

public class ContactModel : PageModel
{
    private readonly ILogger _logger;

    public ContactModel(ILoggerFactory logger)
    {
        _logger = logger.CreateLogger("TodoApi.Pages.ContactModel.MyCategory");
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.ContactModel called.");
    }

L’appel de CreateLogger avec un nom fixe peut être utile si vous l’utilisez dans plusieurs méthodes afin que les événements puissent être organisés par catégorie.

ILogger<T> équivaut à appeler CreateLogger avec le nom de type complet T.

Log level

Le tableau suivant liste les valeurs LogLevel, la méthode d’extension de commodité Log{LogLevel}, ainsi que des suggestions d’utilisation :

LogLevel Valeur Méthode Description
Trace 0 LogTrace Contiennent les messages les plus détaillés. Ces messages peuvent contenir des données d’application sensibles. Ils sont désactivés par défaut et ne doivent pas être activés dans un environnement de production.
Déboguer 1 LogDebug Pour le débogage et le développement. À utiliser avec prudence dans un environnement de production en raison du volume élevé de messages.
Information 2 LogInformation Effectue le suivi du flux général de l’application. Peut avoir une valeur à long terme.
Avertissement 3 LogWarning Pour les événements anormaux ou inattendus. Comprend généralement des erreurs ou des conditions qui n’entraînent pas l’échec de l’application.
Error 4 LogError Fournit des informations sur des erreurs et des exceptions qui ne peuvent pas être gérées. Ces messages indiquent un échec de l’opération ou de la demande en cours, et non l’échec de l’application.
Critical 5 LogCritical Fournit des informations sur des échecs qui nécessitent un examen immédiat. Exemples : perte de données, espace disque insuffisant.
Aucun 6 Spécifie qu’une catégorie de journalisation ne doit écrire aucun message.

Dans le tableau précédent, LogLevel est listé du plus faible niveau de gravité au plus élevé.

Le premier paramètre de la méthode Log (LogLevel) indique le niveau de gravité du journal. Au lieu d’appeler Log(LogLevel, ...), la plupart des développeurs appellent les méthodes d’extension Log{LogLevel}. Les méthodes d’extension Log{LogLevel}appellent la méthode Log et spécifient le LogLevel. Par exemple, les deux appels de journalisation suivants ont un fonctionnement équivalent et produisent le même journal :

[HttpGet]
public IActionResult Test1(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);

    _logger.Log(LogLevel.Information, MyLogEvents.TestItem, routeInfo);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    return ControllerContext.MyDisplayRouteInfo();
}

MyLogEvents.TestItem est l’ID de l’événement. MyLogEvents fait partie de l’exemple d’application et s’affiche dans la section ID d’événement du journal.

MyDisplayRouteInfo et ToCtxString sont fournis par le package NuGet Rick.Docs.Samples.RouteInfo. Les méthodes affichent les informations de routage Controller et Razor Page.

Le code suivant crée des journaux Information et Warning :

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

Dans le code précédent, le premier paramètre Log{LogLevel} (MyLogEvents.GetItem) est l’ID de l’événement de journal. Le deuxième paramètre est un modèle de message contenant des espaces réservés pour les valeurs d’argument fournies par les autres paramètres de méthode. Les paramètres de méthode sont expliqués dans la section Modèle de message plus loin dans ce document.

Appelez la méthode Log{LogLevel} appropriée pour contrôler le volume de la sortie de journal pouvant être écrite sur un support de stockage spécifique. Exemple :

  • En production :
    • La journalisation aux niveaux Trace ou Information produit un volume élevé de messages de journal détaillés. Pour contrôler les coûts et ne pas dépasser les limites de stockage des données, journalisez les messages de niveau Trace et Information dans un magasin de données à haut volume et à faible coût. Il est conseillé de limiter Trace et Information à certaines catégories.
    • La journalisation aux niveaux allant de Warning à Critical doivent produire moins de messages de journal.
      • Les coûts et les limites de stockage ne posent généralement pas problème.
      • Peu de journaux permettent une plus grande flexibilité au niveau du choix du magasin de données.
  • Lors du développement :
    • Réglez sur Warning.
    • Ajoutez les messages Trace ou Information lorsque vous résolvez des problèmes. Pour limiter la sortie, définissez Trace ou Information uniquement pour les catégories en cours d’investigation.

ASP.NET Core écrit des journaux pour les événements de framework. Par exemple, tenez compte de la sortie du journal pour :

  • Une application Razor Pages créée avec les modèles ASP.NET Core.
  • Journalisation définie sur Logging:Console:LogLevel:Microsoft:Information
  • Navigation vers la page Privacy :
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/Privacy
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/Privacy'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
      Route matched with {page = "/Privacy"}. Executing page /Privacy
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
      Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
      Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
      Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
      Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
      Executed page /Privacy in 74.5188ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/Privacy'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 149.3023ms 200 text/html; charset=utf-8

Le code JSON suivant définit Logging:Console:LogLevel:Microsoft:Information :

{
  "Logging": {      // Default, all providers.
    "LogLevel": {
      "Microsoft": "Warning"
    },
    "Console": { // Console provider.
      "LogLevel": {
        "Microsoft": "Information"
      }
    }
  }
}

ID d’événement de log

Chaque journal peut spécifier un ID d’événement. L’exemple d’application utilise la classe MyLogEvents pour définir les ID d’événement :

public class MyLogEvents
{
    public const int GenerateItems = 1000;
    public const int ListItems     = 1001;
    public const int GetItem       = 1002;
    public const int InsertItem    = 1003;
    public const int UpdateItem    = 1004;
    public const int DeleteItem    = 1005;

    public const int TestItem      = 3000;

    public const int GetItemNotFound    = 4000;
    public const int UpdateItemNotFound = 4001;
}
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

Un ID d’événement associe un jeu d’événements. Par exemple, tous les journaux liés à l’affichage d’une liste d’éléments sur une page peuvent être 1001.

Le fournisseur de journalisation peut stocker l’ID d’événement dans un champ ID, dans le message de journalisation, ou pas du tout. Le fournisseur Debug n’affiche pas les ID d’événements. Le fournisseur Console affiche les ID d’événements entre crochets après la catégorie :

info: TodoApi.Controllers.TodoItemsController[1002]
      Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
      Get(1) NOT FOUND

Certains fournisseurs de journalisation stockent l’ID d’événement dans un champ, ce qui permet de filtrer en fonction de l’ID.

Modèle de message de journal

Chaque API de journalisation utilise un modèle de message. Ce dernier peut contenir des espaces réservés pour lesquels les arguments sont fournis. Utilisez des noms et non des nombres pour les espaces réservés.

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

C’est l’ordre des paramètres, et non leur nom d’espace réservé, qui détermine les paramètres utilisés pour fournir des valeurs d’espace réservé dans les messages de journal. Dans le code suivant, les noms de paramètres ne sont pas dans l’ordre dans le modèle de message :

var apples = 1;
var pears = 2;
var bananas = 3;

_logger.LogInformation("Parameters: {pears}, {bananas}, {apples}", apples, pears, bananas);

Cependant, les paramètres sont attribués aux espaces réservés dans l’ordre : apples, pears, bananas. Le message de journal reflète l’ordre des paramètres :

Parameters: 1, 2, 3

Cette approche permet aux fournisseurs de journalisation d’implémenter une journalisation sémantique ou structurée. Les arguments proprement dits, et pas seulement le modèle de message mis en forme, sont transmis au système de journalisation. Cela permet aux fournisseurs de journalisation de stocker les valeurs des paramètres sous forme de champs. Prenons l’exemple de la méthode d’enregistreur d’événements suivante :

_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);

Par exemple, lorsque vous journalisez des événements vers le Stockage Table Azure :

  • Chaque entité de table Azure peut avoir des propriétés ID et RequestTime.
  • Les tables avec des propriétés simplifient les requêtes qui sont exécutées sur des données journalisées. Par exemple, vous pouvez rechercher tous les journaux compris dans une plage RequestTime spécifique, sans avoir besoin d’analyser le délai d’expiration du message texte.

Enregistrer des exceptions

Les méthodes d’enregistreur d’événements ont des surcharges qui prennent un paramètre d’exception :

[HttpGet("{id}")]
public IActionResult TestExp(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    try
    {
        if (id == 3)
        {
            throw new Exception("Test exception");
        }
    }
    catch (Exception ex)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, ex, "TestExp({Id})", id);
        return NotFound();
    }

    return ControllerContext.MyDisplayRouteInfo();
}

MyDisplayRouteInfo et ToCtxString sont fournis par le package NuGet Rick.Docs.Samples.RouteInfo. Les méthodes affichent les informations de routage Controller et Razor Page.

La journalisation des exceptions dépend du fournisseur.

Niveau de journalisation par défaut

Si le niveau de journalisation par défaut n’est pas défini, la valeur sera Information.

Prenons l’exemple de l’application web suivante :

  • Créée avec les modèles d’application web ASP.NET.
  • appsettings.json et appsettings.Development.json ont été supprimés ou renommés.

Avec la configuration précédente, l’accès à la page de confidentialité ou d’accueil produit de nombreux messages Trace, Debug et Information de catégorie Microsoft.

Le code suivant définit le niveau de journalisation par défaut lorsque celui-ci n’est pas défini dans la configuration :

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning))
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

En règle générale, les niveaux de journalisation doivent être spécifiés dans la configuration et non dans le code.

fonction Filter

Une fonction de filtre est appelée pour tous les fournisseurs et toutes les catégories auxquels aucune règle n’est affectée dans la configuration ou dans le code :

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
            {
                logging.AddFilter((provider, category, logLevel) =>
                {
                    if (provider.Contains("ConsoleLoggerProvider")
                        && category.Contains("Controller")
                        && logLevel >= LogLevel.Information)
                    {
                        return true;
                    }
                    else if (provider.Contains("ConsoleLoggerProvider")
                        && category.Contains("Microsoft")
                        && logLevel >= LogLevel.Information)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                });
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Le code précédent affiche les journaux de console lorsque la catégorie contient Controller ou Microsoft, et si le niveau de journalisation est Information ou supérieur.

En règle générale, les niveaux de journalisation doivent être spécifiés dans la configuration et non dans le code.

ASP.NET Core et catégories EF Core

Le tableau suivant contient certaines catégories utilisées par ASP.NET Core et Entity Framework Core, ainsi que des notes à propos des journaux :

Catégorie Notes
Microsoft.AspNetCore Diagnostics ASP.NET Core généraux.
Microsoft.AspNetCore.DataProtection Liste des clés considérées, trouvées et utilisées.
Microsoft.AspNetCore.HostFiltering Hôtes autorisés.
Microsoft.AspNetCore.Hosting Temps de traitement des requêtes HTTP et heure de démarrage. Liste des assemblys de démarrage d’hébergement chargés.
Microsoft.AspNetCore.Mvc Diagnostics MVC et Razor. Liaison de données, exécution de filtres, compilation de vues, sélection d’actions.
Microsoft.AspNetCore.Routing Informations de correspondance des itinéraires.
Microsoft.AspNetCore.Server Démarrage et arrêt de la connexion, et réponses persistantes. Informations du certificat HTTPS.
Microsoft.AspNetCore.StaticFiles Fichiers pris en charge.
Microsoft.EntityFrameworkCore Diagnostics Entity Framework Core généraux. Activité et configuration de la base de données, détection des modifications, migrations.

Pour afficher d’autres catégories dans la fenêtre de console, définissez appsettings.Development.json sur la valeur suivante :

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

Étendues de journal

Une étendue peut regrouper un ensemble d’opérations logiques. Ce regroupement permet de joindre les mêmes données à tous les journaux créés au sein d’un ensemble. Par exemple, chaque journal créé dans le cadre du traitement d’une transaction peut contenir l’ID de la transaction.

Une étendue :

Les fournisseurs suivants prennent en charge les étendues :

Utilisez une étendue en incluant les appels de l’enregistrement d’événements dans un bloc using :

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    TodoItem todoItem;
    var transactionId = Guid.NewGuid().ToString();
    using (_logger.BeginScope(new List<KeyValuePair<string, object>>
        {
            new KeyValuePair<string, object>("TransactionId", transactionId),
        }))
    {
        _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

        todoItem = await _context.TodoItems.FindAsync(id);

        if (todoItem == null)
        {
            _logger.LogWarning(MyLogEvents.GetItemNotFound, 
                "Get({Id}) NOT FOUND", id);
            return NotFound();
        }
    }

    return ItemToDTO(todoItem);
}

Fournisseurs de journalisation intégrés

ASP.NET Core inclut les fournisseurs de journalisation suivants dans le cadre du framework partagé :

Les fournisseurs de journalisation suivants sont fournis par Microsoft, mais pas dans le cadre du framework partagé. Ils doivent être installés en tant que NuGet supplémentaire.

ASP.NET Core n’inclut pas de fournisseur de journalisation permettant d’écrire des journaux dans des fichiers. Pour écrire des journaux d’activité dans des fichiers à partir d’une application ASP.NET Core, vous pouvez utiliser un fournisseur de journalisation tiers.

Pour plus d’informations sur stdout et sur la journalisation du débogage avec le module ASP.NET Core, consultez Résoudre les problèmes liés à ASP.NET Core sur Azure App Service et IIS et Module ASP.NET Core (ANCM) pour IIS.

Console

Le fournisseur Console journalise la sortie de la console. Pour plus d’informations sur l’affichage des journaux Console durant la phase de développement, consultez Journalisation de la sortie de l’exécution dotnet et Visual Studio.

Débogage

Le fournisseur Debug écrit la sortie du journal à l’aide de la classe System.Diagnostics.Debug. Les appels à System.Diagnostics.Debug.WriteLine sont écrits dans le fournisseur Debug.

Sur Linux, l’emplacement du journal du fournisseur Debug dépend de la distribution et peut être l’un des emplacements suivants :

  • /var/log/message
  • /var/log/syslog

Source de l’événement

Le fournisseur EventSource écrit les données dans une source d’événements multiplateforme portant le nom de Microsoft-Extensions-Logging. Sur Windows, le fournisseur utilise ETW.

Outils de suivi dotnet

L’outil dotnet-trace est un outil CLI multiplateforme qui permet la collection de traces .NET Core issues d’un processus en cours d’exécution. L’outil collecte des données de fournisseur Microsoft.Extensions.Logging.EventSource à l’aide d’un LoggingEventSource.

Consultez dotnet-trace pour obtenir des instructions d’installation.

Utilisez les outils dotnet-trace pour collecter une trace à partir d’une application :

  1. Exécutez l’application avec la commande dotnet run.

  2. Déterminez l’identificateur de processus (PID) de l’application .NET Core :

    dotnet trace ps
    

    Recherchez le PID du processus qui porte le même nom que l’assembly de l’application.

  3. Exécutez la commande dotnet trace.

    Syntaxe de commande générale :

    dotnet trace collect -p {PID} 
        --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Category Level 1};
                {Logger Category 2}:{Category Level 2};
                ...
                {Logger Category N}:{Category Level N}\"
    

    Lorsque vous utilisez un interpréteur de commandes PowerShell, placez la valeur --providers entre guillemets simples (') :

    dotnet trace collect -p {PID} 
        --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Category Level 1};
                {Logger Category 2}:{Category Level 2};
                ...
                {Logger Category N}:{Category Level N}\"'
    

    Sur les plateformes autres que Windows, ajoutez l’option -f speedscope pour remplacer le format du fichier de trace de sortie par speedscope.

    Le tableau suivant définit le mot clé :

    Mot clé Description
    1 Journalise les événements meta à propos de LoggingEventSource. Ne journalise pas les événements provenant de ILogger.
    2 Active l’événement Message lors de l’appel de ILogger.Log(). Fournit les informations de façon programmatique (sans mise en forme).
    4 Active l’événement FormatMessage lors de l’appel de ILogger.Log(). Fournit la version de chaîne mise en forme des informations.
    8 Active l’événement MessageJson lors de l’appel de ILogger.Log(). Fournit une représentation JSON des arguments.

    Le tableau suivant liste les niveaux fournisseur :

    Niveau fournisseur Description
    0 LogAlways
    1 Critical
    2 Error
    3 Warning
    4 Informational
    5 Verbose

    L’analyse d’un niveau de catégorie peut être une chaîne ou un nombre :

    Valeur nommée de catégorie Valeur numérique
    Trace 0
    Debug 1
    Information 2
    Warning 3
    Error 4
    Critical 5

    Le niveau fournisseur et le niveau catégorie :

    • Sont dans l’ordre inverse.
    • Les constantes de chaîne ne sont pas toutes identiques.

    Si aucune FilterSpecs n’est spécifiée, l’implémentation de EventSourceLogger tente de convertir le niveau fournisseur en niveau catégorie, et l’applique à toutes les catégories.

    Niveau fournisseur Niveau catégorie
    Verbose(5) Debug(1)
    Informational(4) Information(2)
    Warning(3) Warning(3)
    Error(2) Error(4)
    Critical(1) Critical(5)

    Si des FilterSpecs sont fournies, toutes les catégories incluses dans la liste utiliseront le niveau catégorie qui y est encodé. Toutes les autres catégories seront filtrées.

    Les exemples suivants supposent ce qui suit :

    • Une application s’exécute et appelle logger.LogDebug("12345").
    • L’ID de processus (PID) a été défini via set PID=12345, où 12345 est le PID réel.

    Prenez la commande suivante :

    dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5
    

    La commande précédente :

    • Capture les messages de débogage.
    • Ne s’applique pas aux FilterSpecs.
    • Spécifie le niveau 5 qui mappe la catégorie Débogage.

    Prenez la commande suivante :

    dotnet trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:5\"
    

    La commande précédente :

    • Ne capture pas les messages de débogage, car le niveau de catégorie 5 est Critical.
    • Fournit des FilterSpecs.

    La commande suivante capture les messages de débogage, car le niveau de catégorie 1 spécifie Debug.

    dotnet trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\"
    

    La commande suivante capture les messages de débogage, car la catégorie 1 spécifie Debug.

    dotnet trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\"
    

    Les entrées FilterSpecs pour {Logger Category} et {Category Level} représentent des conditions de filtrage des journaux supplémentaires. Séparez les entrées FilterSpecs par un point-virgule (;).

    Exemple utilisant un interpréteur de commandes Windows :

    dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"
    

    La commande précédente active :

    • L’enregistreur d’événements source afin de produire des chaînes mises en forme (4) pour les erreurs (2).
    • La journalisation Microsoft.AspNetCore.Hosting au niveau de journalisation Informational (4).
  4. Arrêtez les outils de trace dotnet en appuyant sur la touche Entrée ou Ctrl+C.

    La trace est enregistrée sous le nom trace.nettrace dans le dossier où la commande dotnet trace est exécutée.

  5. Ouvrez la trace avec Perfview. Ouvrez le fichier trace.nettrace et explorez les événements de trace.

Si l’application ne génère pas l’hôte avec CreateDefaultBuilder, ajoutez le fournisseur de source d’événements à la configuration de journalisation de l’application.

Pour plus d'informations, consultez les pages suivantes :

Perfview

Utilisez l’utilitaire PerfView pour collecter et afficher les journaux. Il existe d’autres outils d’affichage des journaux ETW, mais PerfView est l’outil recommandé pour gérer les événements ETW générés par ASP.NET Core.

Pour configurer PerfView afin qu’il collecte les événements enregistrés par ce fournisseur, ajoutez la chaîne *Microsoft-Extensions-Logging à la liste des fournisseurs supplémentaires. N’oubliez pas d’inclure le * au début de la chaîne.

Journal des événements Windows

Le fournisseur EventLog envoie la sortie de journal dans le journal des événements Windows. Contrairement aux autres fournisseurs, le fournisseur EventLog n’hérite pas des paramètres par défaut qui ne sont pas relatifs au fournisseur. Si les paramètres du journal EventLog ne sont pas spécifiés, leur valeur par défaut est LogLevel.Warning.

Pour journaliser les événements inférieurs à LogLevel.Warning, définissez explicitement le niveau de journalisation. L’exemple suivant définit le niveau de journalisation par défaut du journal des événements sur LogLevel.Information :

"Logging": {
  "EventLog": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

Les surcharges AddEventLog permettent de passer EventLogSettings. Si la valeur est null ou non spécifiée, les paramètres par défaut suivants sont utilisés :

  • LogName : "Application"
  • SourceName : ".NET Runtime"
  • MachineName : le nom de l’ordinateur local est utilisé.

Le code suivant remplace la valeur par défaut de SourceName (".NET Runtime") par MyLogs :

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
            {
                logging.AddEventLog(eventLogSettings =>
                {
                    eventLogSettings.SourceName = "MyLogs"; 
                });
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Azure App Service

Le package de fournisseur Microsoft.Extensions.Logging.AzureAppServices écrit les enregistrements de journal dans des fichiers texte dans le système de fichiers d’une application Azure App Service, et dans un stockage Blob dans un compte de stockage Azure.

Le fournisseur de package n’est pas inclus dans le framework partagé. Pour utiliser le fournisseur, ajoutez le package du fournisseur au projet.

Pour configurer les paramètres du fournisseur, utilisez AzureFileLoggerOptions et AzureBlobLoggerOptions, comme illustré dans l’exemple suivant :

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

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
                .ConfigureServices(serviceCollection => serviceCollection
                    .Configure<AzureFileLoggerOptions>(options =>
                    {
                        options.FileName = "azure-diagnostics-";
                        options.FileSizeLimit = 50 * 1024;
                        options.RetainedFileCountLimit = 5;
                    })
                    .Configure<AzureBlobLoggerOptions>(options =>
                    {
                        options.BlobName = "log.txt";
                    }))
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Si elle est déployée dans Azure App Service, l’application utilise les paramètres qui sont définis dans la section Journaux App Service de la page App Service du portail Azure. Quand les paramètres suivants sont mis à jour, les changements prennent effet immédiatement sans avoir besoin de redémarrer ou redéployer l’application.

  • Journalisation des applications (système de fichiers)
  • Journalisation des applications (objet blob)

L’emplacement par défaut des fichiers journaux est le dossier D:\home\LogFiles\Application, et le nom de fichier par défaut est diagnostics-yyyymmdd.txt. La limite de taille de fichier par défaut est de 10 Mo, et le nombre maximal de fichiers conservés par défaut est de 2. Le nom par défaut du blob est {app-name}{timestamp}/aaaa/mm/jj/hh/{guid}-applicationLog.txt.

Ce fournisseur journalise uniquement quand le projet s’exécute dans l’environnement Azure.

Streaming des journaux Azure

Le streaming de journaux Azure prend en charge l’affichage de l’activité des journaux en temps réel provenant du :

  • Serveur d'applications
  • Serveur web
  • Suivi des demandes ayant échoué

Pour configurer le streaming des journaux Azure :

  • Accédez à la page Journaux App Service dans le portail de l’application.
  • Définissez Journal des applications (Système de fichiers) sur Activé.
  • Choisissez le niveau du journal. Ce paramètre s’applique uniquement au streaming de journaux Azure.

Accédez à la page Streaming des journaux pour afficher les journaux. Les messages journalisés le sont avec l’interface ILogger.

Azure Application Insights

Le package de fournisseur Microsoft.Extensions.Logging.ApplicationInsights écrit des journaux dans Azure Application Insights. Application Insights est un service qui surveille une application web et fournit des outils pour interroger et analyser les données de télémétrie. Si vous utilisez ce fournisseur, vous pouvez interroger et analyser vos journaux à l’aide des outils Application Insights.

Le fournisseur de journalisation est inclus en tant que dépendance de Microsoft.ApplicationInsights.AspNetCore, le package qui fournit toutes les données de télémétrie disponibles pour ASP.NET Core. Si vous utilisez ce package, vous n’avez pas besoin d’installer le package du fournisseur.

Le package Microsoft.ApplicationInsights.Web est destiné à ASP.NET 4.x, et non à ASP.NET Core.

Pour plus d’informations, consultez les ressources suivantes :

Fournisseurs de journalisation tiers

Frameworks de journalisation tiers qui sont pris en charge dans ASP.NET Core :

Certains frameworks tiers prennent en charge la journalisation sémantique, également appelée journalisation structurée.

L’utilisation d’un framework tiers est semblable à l’utilisation des fournisseurs intégrés :

  1. Ajoutez un package NuGet à votre projet.
  2. Appelez une méthode d’extension ILoggerFactory fournie par le framework de journalisation.

Pour plus d’informations, consultez la documentation de chaque fournisseur. Les fournisseurs de journalisation tiers ne sont pas pris en charge par Microsoft.

Application console non hôte

Pour obtenir un exemple d’utilisation de l’hôte générique dans une application console non web, consultez le fichier Program.cs de l’exemple d’application Background Tasks (Tâches d’arrière-plan avec des services hébergés dans ASP.NET Core).

Le code de journalisation pour les applications sans hôte générique diffère de la façon dont les fournisseurs sont ajoutés et enregistreurs d’événements sont créés.

Fournisseurs de journalisation

Dans une application de console non hôte, appelez la méthode d’extension Add{provider name} du fournisseur lors de la création d’un LoggerFactory :

class Program
{
    static void Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddFilter("System", LogLevel.Warning)
                .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddConsole()
                .AddEventLog();
        });
        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Example log message");
    }
}

Créer des journaux

Pour créer des journaux, utilisez un objet ILogger<TCategoryName>. Utilisez LoggerFactory pour créer un ILogger.

L’exemple suivant crée un enregistreur d’événements de catégorie LoggingConsoleApp.Program.

class Program
{
    static void Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddFilter("System", LogLevel.Warning)
                .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddConsole()
                .AddEventLog();
        });
        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Example log message");
    }
}

Dans l’exemple suivant, l’enregistreur d’événements est utilisé pour créer des journaux de niveau Information. Le niveau du journal indique la gravité de l’événement consigné.

class Program
{
    static void Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddFilter("System", LogLevel.Warning)
                .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddConsole()
                .AddEventLog();
        });
        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Example log message");
    }
}

Les niveaux et les catégories sont expliqués en détail dans ce document.

Journaliser pendant la construction de l’hôte

La journalisation pendant la construction de l’hôte n’est pas prise en charge directement. Toutefois, un enregistreur d’événements distinct peut être utilisé. Dans l’exemple suivant, un enregistreur d’événements Serilog est utilisé pour journaliser dans CreateHostBuilder. AddSerilog utilise la configuration statique spécifiée dans Log.Logger :

using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

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

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var builtConfig = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddCommandLine(args)
            .Build();

        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .WriteTo.File(builtConfig["Logging:FilePath"])
            .CreateLogger();

        try
        {
            return Host.CreateDefaultBuilder(args)
                .ConfigureServices((context, services) =>
                {
                    services.AddRazorPages();
                })
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddConfiguration(builtConfig);
                })
                .ConfigureLogging(logging =>
                {   
                    logging.AddSerilog();
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host builder error");

            throw;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }
}

Configurer un service qui dépend de ILogger

L’injection de constructeur d’un enregistreur d’événements dans Startup fonctionne dans les versions antérieures d’ASP.NET Core, car un conteneur d’injection de dépendances distinct est créé pour l’hôte web. Pour plus d’informations sur la raison de la création d’un seul conteneur pour l’hôte générique, consultez l’annonce de changement cassant.

Pour configurer un service qui dépend de ILogger<T>, utilisez l’injection de constructeur ou fournissez une méthode de fabrique. L’approche de la méthode de fabrique est recommandée uniquement s’il n’y a aucune autre option. Par exemple, prenons un service qui a besoin d’une instance ILogger<T> fournie par une injection de dépendances :

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddRazorPages();

    services.AddSingleton<IMyService>((container) =>
    {
        var logger = container.GetRequiredService<ILogger<MyService>>();
        return new MyService() { Logger = logger };
    });
}

Le code en surbrillance précédent est une Func<T,TResult> qui s’exécute la première fois que le conteneur d’injection de dépendances doit construire une instance de MyService. Vous pouvez accéder à tous les services inscrits de cette manière.

Créer des journaux dans Main

Le code suivant journalise dans Main en obtenant une instance ILogger à partir d’une injection de dépendances après avoir créé l’hôte :

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    var logger = host.Services.GetRequiredService<ILogger<Program>>();
    logger.LogInformation("Host created.");

    host.Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Créer des journaux au démarrage

Le code suivant écrit les journaux dans Startup.Configure :

public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
                      ILogger<Startup> logger)
{
    if (env.IsDevelopment())
    {
        logger.LogInformation("In Development.");
        app.UseDeveloperExceptionPage();
    }
    else
    {
        logger.LogInformation("Not Development.");
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapRazorPages();
    });
}

L’écriture de journaux avant la fin de l’installation du conteneur d’injection de dépendances dans la méthode Startup.ConfigureServices n’est pas prise en charge :

  • L’injection d’un enregistreur d’événements dans le constructeur Startup n’est pas prise en charge.
  • L’injection d’un enregistreur d’événements dans la signature de méthode Startup.ConfigureServices n’est pas prise en charge.

La raison de cette restriction est que la journalisation dépend de l’injection de dépendances et de la configuration qui, à son tour, dépend de l’injection de dépendances. Le conteneur d’injection de dépendances n’est pas configuré avant que ConfigureServices soit terminé.

Pour plus d’informations sur la configuration d’un service qui dépend de ILogger<T>, ou pour savoir pourquoi l’injection de constructeur d’un enregistreur d’événements dans Startup fonctionnait dans les versions antérieures, consultez Configurer un service qui dépend de ILogger

Aucune méthode d’enregistreur d’événements asynchrone

La journalisation doit être suffisamment rapide par rapport au coût du code asynchrone en matière de performances. Si un magasin de données de journalisation est lent, n’écrivez pas de données directement dedans. Écrivez les messages de journal dans un magasin rapide, puis déplacez-les vers le magasin lent. Par exemple, lorsque vous vous connectez à SQL Server, ne le faites pas directement dans une méthode Log, puisque les méthodes Log sont synchrones. Ajoutez plutôt de façon synchronisée des messages de journal à une file d’attente en mémoire, puis configurez un traitement en arrière-plan afin d’extraire les messages de la file d’attente et d’effectuer le travail asynchrone d’envoi des données vers SQL Server. Pour plus d’informations, consultez ce problème GitHub.

Modifier les niveaux de journalisation dans une application en cours d’exécution

L’API de journalisation ne permet pas de modifier les niveaux de journalisation pendant l’exécution d’une application. Toutefois, certains fournisseurs de configuration sont capables de recharger la configuration, ce qui agit immédiatement sur la configuration de la journalisation. Par exemple, File Configuration Provider recharge la configuration de journalisation par défaut. Si la configuration est modifiée dans le code pendant l’exécution d’une application, celle-ci peut appeler IConfigurationRoot.Reload pour mettre à jour la configuration de journalisation de l’application.

ILogger et ILoggerFactory

Les interfaces et les implémentations ILogger<TCategoryName> et ILoggerFactory sont incluses dans le SDK .NET Core. Elles sont également disponibles dans les packages NuGet suivants :

Appliquer des règles de filtre de journaux dans le code

Pour définir des règles de filtre de journaux, l’approche recommandée consiste à utiliser Configuration.

L'exemple suivant montre comment enregistrer des règles de filtre dans le code :

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
               logging.AddFilter("System", LogLevel.Debug)
                  .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
                  .AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace))
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

logging.AddFilter("System", LogLevel.Debug) spécifie la catégorie System et le niveau de journalisation Debug. Le filtre est appliqué à tous les fournisseurs, car aucun fournisseur spécifique n’a été configuré.

AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information) spécifie :

  • Le fournisseur de journalisation Debug.
  • Le niveau de journalisation Information et niveaux supérieurs.
  • Toutes les catégories commençant par "Microsoft".

Journaliser automatiquement l’étendue avec SpanId, TraceId et ParentId

Les bibliothèques de journalisation créent implicitement un objet d’étendue avec SpanId, TraceId et ParentId. Ce comportement est configuré via ActivityTrackingOptions.

  var loggerFactory = LoggerFactory.Create(logging =>
  {
      logging.Configure(options =>
      {
          options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
                                              | ActivityTrackingOptions.TraceId
                                              | ActivityTrackingOptions.ParentId;
      }).AddSimpleConsole(options =>
      {
          options.IncludeScopes = true;
      });
  });

Si l’en-tête de requête HTTP traceparent est défini, le ParentId dans l’étendue du journal affiche le parent-id W3C issu de l’en-tête entrant traceparent, et le SpanId dans l’étendue du journal affiche le parent-id mis à jour pour l’étape/l’étendue sortante suivante. Pour plus d’informations, consultez Mutating the traceparent Field.

Créer un enregistreur d’événements personnalisé

Pour créer un enregistreur d’événements personnalisé, consultez Implémenter un fournisseur de journalisation personnalisé dans .NET.

Ressources supplémentaires