Entrainement
Module
Mettre en forme des données alphanumériques en vue de leur affichage en C# - Training
Explorez les méthodes de base en C# pour mettre en forme des données alphanumériques.
Ce navigateur n’est plus pris en charge.
Effectuez une mise à niveau vers Microsoft Edge pour tirer parti des dernières fonctionnalités, des mises à jour de sécurité et du support technique.
.NET prend en charge la journalisation haute performance structurée via l’API ILogger pour faciliter la supervision du comportement des applications et le diagnostic des problèmes. Les journaux peuvent être écrits dans différentes destinations en configurant différents fournisseurs de journalisation. Les fournisseurs de journalisation de base sont intégrés et de nombreux fournisseurs tiers sont également disponibles.
Ce premier exemple montre les principes de base, mais il convient seulement à une application console triviale. Cet exemple d’application console s’appuie sur les packages NuGet suivants :
Dans la section suivante, vous voyez comment améliorer le code en prenant en compte la mise à l’échelle, les performances, la configuration et les modèles de programmation classiques.
using Microsoft.Extensions.Logging;
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
L’exemple précédent :
ILoggerFactory
stocke toute la configuration qui détermine l’emplacement où les messages de journal sont envoyés. Dans le cas présent, vous configurez le fournisseur de journalisation de la console afin que les messages de journal soient écrits dans la console.string
associée à chaque message consigné par le ILogger
. Elle est utilisée pour regrouper les messages de journalisation ayant la même classe (ou catégorie) lors de la recherche ou du filtrage des journaux.Information
. Le niveau de journal indique la gravité de l’événement journalisé et est utilisé pour filtrer les messages de journal moins importants. L’entrée de journal inclut également un modèle de message "Hello World! Logging is {Description}."
et une paire clé-valeur Description = fun
. Le nom de clé (ou l’espace réservé) provient du mot à l’intérieur des accolades dans le modèle et la valeur provient de l’argument de méthode restant.Ce fichier projet pour cet exemple inclut deux packages NuGet :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0" />
</ItemGroup>
</Project>
Conseil
Tous les exemples de code source de journalisation sont disponibles dans l’Explorateur d’exemples pour téléchargement. Pour plus d’informations, consultez Parcourir les exemples de code : Journalisation dans .NET.
Plusieurs modifications de l’exemple précédent sont à envisager pour la journalisation dans un scénario moins trivial :
Si votre application utilise l’injection de dépendances (DI) ou un hôte comme WebApplication d’ASP.NET ou un hôte générique, vous devez utiliser des objets ILoggerFactory
et ILogger
depuis leurs conteneurs d’injection de dépendances respectifs au lieu de les créer directement. Pour plus d’informations, consultez Intégration à une injection de dépendances et à des hôtes.
La journalisation de la génération de source au moment de la compilation est généralement une meilleure alternative aux méthodes d’extension ILogger
comme LogInformation
. La journalisation de la génération de source offre de meilleures performances et un typage plus fort, et évite de propager des constantes string
dans toutes vos méthodes. L’inconvénient est que l’utilisation de cette technique nécessite un peu plus de code.
using Microsoft.Extensions.Logging;
internal partial class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
LogStartupMessage(logger, "fun");
}
[LoggerMessage(Level = LogLevel.Information, Message = "Hello World! Logging is {Description}.")]
static partial void LogStartupMessage(ILogger logger, string description);
}
Type
pour faciliter ce nommage.using Microsoft.Extensions.Logging;
internal class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger<Program>();
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
}
}
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using ILoggerFactory factory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(logging =>
{
logging.AddOtlpExporter();
});
});
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
Si votre application utilise l’injection de dépendances (DI) ou un hôte comme WebApplication d’ASP.NET ou un hôte générique, vous devez utiliser des objets ILoggerFactory
et ILogger
depuis le conteneur d’injection de dépendances au lieu de les créer directement.
Cet exemple obtient un objet ILogger dans une application hébergée en utilisant les API minimales d’ASP.NET :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
var handler = app.Services.GetRequiredService<ExampleHandler>();
app.MapGet("/", handler.HandleRequest);
app.Run();
partial class ExampleHandler(ILogger<ExampleHandler> logger)
{
public string HandleRequest()
{
LogHandleRequest(logger);
return "Hello World";
}
[LoggerMessage(LogLevel.Information, "ExampleHandler.HandleRequest was called")]
public static partial void LogHandleRequest(ILogger logger);
}
L’exemple précédent :
ExampleHandler
et mappage des requêtes web entrantes pour exécuter la fonction ExampleHandler.HandleRequest
.ILogger<ExampleHandler>
. ILogger<TCategoryName> dérive de ILogger et indique la catégorie de l’objet ILogger
. Le conteneur d’injection de dépendances localise un ILogger
avec la catégorie correcte et la fournit comme argument du constructeur. S’il n’existe pas encore de ILogger
avec cette catégorie, le conteneur d’injection de dépendances la crée automatiquement à partir du ILoggerFactory
dans le fournisseur du service.logger
reçu dans le constructeur a été utilisé pour la journalisation dans la fonction HandleRequest
.Les générateurs d’hôtes initialisent la configuration par défaut, puis ajoutent un objet configuré ILoggerFactory
au conteneur d’injection de dépendances de l’hôte lors de la génération de l’hôte. Avant la génération de l’hôte, vous pouvez ajuster la configuration de journalisation via HostApplicationBuilder.Logging, WebApplicationBuilder.Logging ou des API similaires sur d’autres hôtes. Les hôtes appliquent également la configuration de journalisation depuis des sources de configuration par défaut comme appsettings.json et des variables d’environnement. Pour plus d’informations, consultez Configuration dans .NET.
Cet exemple part du précédent pour personnaliser le ILoggerFactory
fourni par WebApplicationBuilder
. Il ajoute OpenTelemetry comme fournisseur de journalisation qui transmet les journaux sur OTLP (protocole OpenTelemetry) :
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddOpenTelemetry(logging => logging.AddOtlpExporter());
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
Si vous utilisez un conteneur d’injection de dépendances sans hôte, utilisez AddLogging pour configurer et ajouter ILoggerFactory
au conteneur.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
// Add services to the container including logging
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddConsole());
services.AddSingleton<ExampleService>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
// Get the ExampleService object from the container
ExampleService service = serviceProvider.GetRequiredService<ExampleService>();
// Do some pretend work
service.DoSomeWork(10, 20);
class ExampleService(ILogger<ExampleService> logger)
{
public void DoSomeWork(int x, int y)
{
logger.LogInformation("DoSomeWork was called. x={X}, y={Y}", x, y);
}
}
L’exemple précédent :
ILoggerFactory
configuré pour écrire sur la consoleExampleService
au conteneurExampleService
du conteneur d’injection de dépendances qui a également créé automatiquement un ILogger<ExampleService>
à utiliser comme argument du constructeur.ExampleService.DoSomeWork
qui a utilisé le ILogger<ExampleService>
pour consigner un message sur la console.La configuration de la journalisation est définie dans le code ou via des sources externes, comme des fichiers de configuration et des variables d’environnement. Quand elle est possible, l’utilisation d’une configuration externe est avantageuse, car elle peut être changée sans regénérer l’application. Cependant, certaines tâches, comme la définition des fournisseurs de journalisation, peuvent être configurées seulement à partir du code.
Pour les apps qui utilisent un hôte, la configuration de la journalisation est généralement fournie par la section "Logging"
des fichiers appsettings.{Environment}
.json. Pour les applications qui n’utilisent pas d’hôte, les sources de configuration externe sont au lieu de cela configurées explicitement ou configurées dans le code.
Le fichier appsettings.Development.json suivant est généré par les modèles de service Worker .NET :
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Dans le code JSON précédent :
"Default"
, "Microsoft"
et "Microsoft.Hosting.Lifetime"
sont spécifiées."Default"
est appliquée à toutes les catégories qui ne sont pas spécifiées, ce qui rendra toutes les valeurs par défaut pour toutes les catégories "Information"
. Vous pouvez remplacer ce comportement en spécifiant une valeur pour une catégorie."Microsoft"
s’applique à toutes les catégories qui commencent par "Microsoft"
."Microsoft"
journalise au niveau de journalisation Warning
et aux niveaux supérieurs."Microsoft.Hosting.Lifetime"
est plus précise que la catégorie "Microsoft"
. La catégorie "Microsoft.Hosting.Lifetime"
journalise donc au niveau "Information"
et aux niveaux supérieurs.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. Considérez le fichier appsettings.json suivant :
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting": "Trace"
}
},
"EventSource": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
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 :
Logging:EventSource:LogLevel:Default:Information
Logging:LogLevel:Microsoft:Warning
Logging:LogLevel:Default:Warning
Les journaux situés en dessous du niveau minimal ne seront pas :
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 des paramètres pour tous les fournisseurs intégrés :
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.Extensions.Hosting": "Warning",
"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 :
Logging.{ProviderName}.LogLevel
remplacent les paramètres de Logging.LogLevel
. Par exemple, le niveau dans Debug.LogLevel.Default
remplace le niveau dans LogLevel.Default
.Console
Debug
EventSource
EventLog
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
Le niveau de journalisation peut être défini par l’un des fournisseurs de configuration. Par exemple, vous pouvez créer une variable d’environnement persistante nommée Logging:LogLevel:Microsoft
avec la valeur Information
.
Créez et assignez une variable d’environnement persistante, en fonction de la valeur de niveau de journal.
:: Assigns the env var to the value
setx "Logging__LogLevel__Microsoft" "Information" /M
Dans une nouvelle instance de l’invite de commandes, lisez la variable d’environnement.
:: Prints the env var value
echo %Logging__LogLevel__Microsoft%
Le paramètre d’environnement précédent est conservé dans l’environnement. Pour tester les paramètres lors de l’utilisation d’une application créée avec les modèles de service Worker .NET, utilisez la commande dotnet run
dans le répertoire du projet après l’affectation de la variable d’environnement.
dotnet run
Conseil
Après avoir défini une variable d’environnement, redémarrez votre environnement de développement intégré (IDE) pour vous assurer que les variables d’environnement nouvellement ajoutées sont disponibles.
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 :
Pour plus d’informations sur la définition de valeurs de configuration .NET à l’aide de variables d’environnement, consultez Variables d’environnement.
Pour configurer la journalisation dans du code, utilisez l’API ILoggingBuilder. Vous pouvez y accéder depuis différents endroits :
ILoggerFactory
directement, configurez dans LoggerFactory.Create.Cet exemple montre comment définir le fournisseur de journalisation de la console et plusieurs filtres.
using Microsoft.Extensions.Logging;
using var loggerFactory = LoggerFactory.Create(static builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogDebug("Hello {Target}", "Everyone");
Dans l’exemple précédent, AddFilter est utilisé pour ajuster le niveau de journalisation qui est activé pour différentes catégories. AddConsole est utilisé pour ajouter le fournisseur de journalisation de la console. Par défaut, les journaux avec la gravité Debug
ne sont pas activés, mais comme la configuration a ajusté les filtres, le message de débogage « Hello Everyone » s’affiche sur la console.
À 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 :
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 une application avec un service défini comme l’objet suivant, la catégorie peut être "Example.DefaultService"
:
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger<DefaultService> _logger;
public DefaultService(ILogger<DefaultService> logger) =>
_logger = logger;
// ...
}
}
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 LoggerFactory.CreateLogger :
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger _logger;
public DefaultService(ILoggerFactory loggerFactory) =>
_logger = loggerFactory.CreateLogger("Example.DefaultService.CustomCategory");
// ...
}
}
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
.
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’aucun message ne doit être écrit. |
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 :
public void LogDetails()
{
var logMessage = "Details for log.";
_logger.Log(LogLevel.Information, AppLogEvents.Details, logMessage);
_logger.LogInformation(AppLogEvents.Details, logMessage);
}
AppLogEvents.Details
est l’ID d’événement et est implicitement représenté par une valeur de constante Int32. AppLogEvents
est une classe qui expose diverses constantes d’identificateur nommées et qui s’affiche dans la section ID d’événement du journal.
Le code suivant crée des journaux Information
et Warning
:
public async Task<T> GetAsync<T>(string id)
{
_logger.LogInformation(AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
return result;
}
Dans le code précédent, le premier Log{LogLevel}
paramètre, AppLogEvents.Read
est l’ID d’événement du 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 cet article.
Configurez le niveau de journal approprié et appelez les méthodes Log{LogLevel}
appropriées pour contrôler la quantité de sortie du journal écrite sur un support de stockage particulier. Exemple :
Trace
ou Debug
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 Debug
dans un magasin de données à haut volume et à faible coût. Il est conseillé de limiter Trace
et Debug
à certaines catégories.Warning
à Critical
doivent produire moins de messages de journal.
Warning
.Trace
ou Debug
lorsque vous résolvez des problèmes. Pour limiter la sortie, définissez Trace
ou Debug
uniquement pour les catégories en cours d’investigation.Le code JSON suivant définit Logging:Console:LogLevel:Microsoft:Information
:
{
"Logging": {
"LogLevel": {
"Microsoft": "Warning"
},
"Console": {
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
Chaque journal peut spécifier un identificateur d’événement, le EventId est une structure avec un Id
et des propriétés en lecture seule facultatives Name
. L’exemple de code source utilise la classe AppLogEvents
pour définir les ID d’événement :
using Microsoft.Extensions.Logging;
internal static class AppLogEvents
{
internal static EventId Create = new(1000, "Created");
internal static EventId Read = new(1001, "Read");
internal static EventId Update = new(1002, "Updated");
internal static EventId Delete = new(1003, "Deleted");
// These are also valid EventId instances, as there's
// an implicit conversion from int to an EventId
internal const int Details = 3000;
internal const int Error = 3001;
internal static EventId ReadNotFound = 4000;
internal static EventId UpdateNotFound = 4001;
// ...
}
Conseil
Pour plus d’informations sur la conversion d’un int
en un EventId
, consultez Opérateur EventId.Implicit(Int32 en EventId).
Un ID d’événement associe un jeu d’événements. Par exemple, tous les journaux liés à la lecture des valeurs d’un référentiel peuvent être 1001
.
Le fournisseur de journalisation peut journaliser 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: Example.DefaultService.GetAsync[1001]
Reading value for a1b2c3
warn: Example.DefaultService.GetAsync[4000]
GetAsync(a1b2c3) 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.
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. L’ordre des espaces réservés, pas leurs noms, détermine quels paramètres sont utilisés pour fournir leurs valeurs. Dans le code suivant, les noms de paramètres sont hors séquence dans le modèle de message :
string p1 = "param1";
string p2 = "param2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);
Le code précédent crée un message de journal avec les valeurs des paramètres dans la séquence :
Parameter values: param1, param2
Notes
Soyez attentif lorsque vous utilisez plusieurs espaces réservés dans un seul modèle de message, car ils sont basés sur des ordinaux. Les noms ne sont pas utilisés pour aligner les arguments sur les espaces réservés.
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. Tenez compte de la méthode d’enregistreur d’événements suivante :
_logger.LogInformation("Getting item {Id} at {RunTime}", id, DateTime.Now);
Par exemple, lorsque vous journalisez des événements vers le Stockage Table Azure :
ID
et RunTime
.RunTime
spécifique, sans avoir besoin d’analyser le délai d’expiration du message texte.Les modèles de messages de journal prennent en charge la mise en forme des espaces réservés. Les modèles sont libres de spécifier n’importe quel format valide pour l’argument de type donné. Prenons l’exemple de le modèle de message d’enregistreur d’événements Information
suivant :
_logger.LogInformation("Logged on {PlaceHolderName:MMMM dd, yyyy}", DateTimeOffset.UtcNow);
// Logged on January 06, 2022
Dans l’exemple précédent, l’instance DateTimeOffset
est le type qui correspond au PlaceHolderName
dans le modèle de message d’enregistreur d’événements. Ce nom peut être n’importe quel nom, car les valeurs sont basées sur des ordinaux. Le format MMMM dd, yyyy
est valide pour le type DateTimeOffset
.
Pour plus d’informations sur la mise en forme de DateTime
et DateTimeOffset
, consultez Chaînes de format de date et d’heure personnalisées.
Les exemples suivants montrent comment mettre en forme un modèle de message à l’aide de la syntaxe d’espace réservé {}
. En outre, un exemple d’échappement de la syntaxe d’espace réservé {}
s’affiche avec sa sortie. Enfin, l’interpolation de chaîne avec des espaces réservés de création de modèles est également affichée :
logger.LogInformation("Number: {Number}", 1); // Number: 1
logger.LogInformation("{{Number}}: {Number}", 3); // {Number}: 3
logger.LogInformation($"{{{{Number}}}}: {{Number}}", 5); // {Number}: 5
Conseil
Les méthodes d’enregistreur d’événements ont des surcharges qui prennent un paramètre d’exception :
public void Test(string id)
{
try
{
if (id is "none")
{
throw new Exception("Default Id detected.");
}
}
catch (Exception ex)
{
_logger.LogWarning(
AppLogEvents.Error, ex,
"Failed to process iteration: {Id}", id);
}
}
La journalisation des exceptions dépend du fournisseur.
Si le niveau de journalisation par défaut n’est pas défini, la valeur sera Information
.
Par exemple, considérez l’application de service Worker suivante :
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 :
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.SetMinimumLevel(LogLevel.Warning);
using IHost host = builder.Build();
await host.RunAsync();
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 :
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddFilter((provider, category, logLevel) =>
{
return provider.Contains("ConsoleLoggerProvider")
&& (category.Contains("Example") || category.Contains("Microsoft"))
&& logLevel >= LogLevel.Information;
});
using IHost host = builder.Build();
await host.RunAsync();
Le code précédent affiche les journaux de console lorsque la catégorie contient Example
ou Microsoft
, et si le niveau de journalisation est Information
ou supérieur.
Une étendue regroupe 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
:
public async Task<T> GetAsync<T>(string id)
{
T result;
var transactionId = Guid.NewGuid().ToString();
using (_logger.BeginScope(new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("TransactionId", transactionId),
}))
{
_logger.LogInformation(
AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(
AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
}
return result;
}
Le JSON suivant active les étendues pour le fournisseur Console :
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Warning",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
Le code suivant active les étendues pour le fournisseur Console :
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole(options => options.IncludeScopes = true);
using IHost host = builder.Build();
await host.RunAsync();
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 :
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using IHost host = Host.CreateApplicationBuilder(args).Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Host created.");
await host.RunAsync();
Le code précédent s’appuie sur deux packages NuGet :
Son fichier projet se présente comme suit :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
</ItemGroup>
</Project>
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.
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, le fournisseur de configuration de fichier 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 sa configuration de journalisation.
Les interfaces ILogger<TCategoryName> et ILoggerFactory ainsi que les implémentations sont incluses dans la plupart des kits SDK .NET comme référence de package implicite. Elles sont également disponibles explicitement dans les packages NuGet suivants lorsqu’elles ne sont pas référencées implicitement :
Pour plus d’informations sur les références de package implicites du Kit de développement logiciel (SDK) .NET, consultez le Kit de développement logiciel (SDK) .NET : table vers espace de noms implicite.
Commentaires sur .NET
.NET est un projet open source. Sélectionnez un lien pour fournir des commentaires :
Entrainement
Module
Mettre en forme des données alphanumériques en vue de leur affichage en C# - Training
Explorez les méthodes de base en C# pour mettre en forme des données alphanumériques.