Journalisation et suivi dans les applications .NET

Effectué

Quand vous poursuivrez le développement de votre application et qu’elle deviendra plus complexe, vous aurez besoin d’appliquer des diagnostics de débogage supplémentaires à votre application.

Le traçage vous permet de surveiller l’exécution de votre application pendant son fonctionnement. Vous pouvez ajouter l’instrumentation du suivi et du débogage à votre application .NET quand vous la développez. Vous pouvez utiliser cette instrumentation pendant que vous développez l’application et après l’avoir déployée.

Cette technique simple est étonnamment puissante. Vous pouvez l’utiliser dans les cas où un débogueur ne suffit pas :

  • Les problèmes survenant sur de longues périodes peuvent être difficiles à déboguer avec un débogueur traditionnel. Les journaux permettent d’obtenir des informations détaillées après coup sur de longues périodes. En revanche, les débogueurs se limitent à une analyse en temps réel.
  • Les applications multithread et les applications distribuées sont souvent difficiles à déboguer. Attacher un débogueur tend à modifier les comportements. Vous pouvez analyser les journaux détaillés en fonction des besoins pour comprendre les systèmes complexes.
  • Les problèmes qui surviennent dans les applications distribuées peuvent provenir d’une interaction complexe entre plusieurs composants. Il n’est peut-être pas raisonnable de connecter un débogueur à chaque partie du système.
  • De nombreux services ne devraient pas être bloqués. Attacher un débogueur provoque souvent des échecs de dépassement de délai.
  • Les problèmes ne sont pas toujours anticipés. La journalisation et le suivi sont conçus pour entraîner une faible surcharge, afin que les programmes puissent toujours enregistrer les données en cas de problème.

Inscrire des informations dans les fenêtres de sortie

À ce stade, nous avons utilisé la console pour présenter des informations à l’utilisateur de l’application. Il existe d’autres types d’applications générées avec .NET qui proposent des interfaces utilisateur, notamment des applications mobiles, web et de bureau, et il n’y a pas de console visible. Dans ces applications, System.Console enregistre des messages « en arrière-plan ». Ces messages peuvent s’afficher dans une fenêtre de sortie dans Visual Studio ou Visual Studio Code. Ils peuvent également être générés dans un journal système comme le logcat d’Android. Ainsi, vous devez prendre toutes les précautions nécessaires quand vous utilisez System.Console.WriteLine dans une application non-console.

C’est là que vous pouvez utiliser System.Diagnostics.Debug et System.Diagnostics.Trace en plus de System.Console. Debug et Trace font partie de System.Diagnostics et inscrivent des données dans les journaux uniquement lorsqu’un écouteur approprié est attaché.

Vous avez le choix de l’API de style d’impression à utiliser. :

  • System.Console
    • Toujours activé et toujours écrire dans la console.
    • Utile pour les informations dont votre client peut avoir besoin lors de la mise en production.
    • Comme il s’agit de l’approche la plus simple, elle est souvent utilisée pour le débogage temporaire ad hoc. Souvent, ce code de débogage n’est jamais archivé dans le contrôle de code source.
  • System.Diagnostics.Trace
    • Activé uniquement quand TRACE est défini.
    • Écrit sur les écouteurs attachés, par défaut l’écouteur DefaultTraceListener.
    • Utilisez cette API quand vous créez des journaux qui seront activés dans la plupart des builds.
  • System.Diagnostics.Debug
    • Activé uniquement quand DEBUG est défini (en mode débogage).
    • Écrit dans un débogueur attaché.
    • Utilisez cette API quand vous créez des journaux qui seront activés uniquement dans les builds de débogage.
Console.WriteLine("This message is readable by the end user.");
Trace.WriteLine("This is a trace message when tracing the app.");
Debug.WriteLine("This is a debug message just for developers.");

Quand vous concevez votre stratégie de suivi et de débogage, réfléchissez à l’aspect de la sortie. Si plusieurs instructions d’écriture sont remplies avec des informations sans rapport, le journal créé est difficile à lire. D’un autre côté, si vous utilisez WriteLine pour placer des instructions connexes sur des lignes distinctes, il peut être difficile de déterminer les informations associées. En général, utilisez plusieurs instructions Write quand vous voulez combiner des informations provenant de plusieurs sources pour créer un message d’information unique. Utilisez l’instruction WriteLine quand vous voulez créer un message complet unique.

Debug.Write("Debug - ");
Debug.WriteLine("This is a full line.");
Debug.WriteLine("This is another full line.");

Cette sortie provient de la journalisation précédente avec Debug :

Debug - This is a full line.
This is another full line.

Définir des constantes TRACE et DEBUG

Par défaut, lorsqu’une application s’exécute en mode de débogage, la constante DEBUG est définie. Vous pouvez contrôler cela en ajoutant une entrée DefineConstants dans le fichier projet d’un groupe de propriétés. Voici un exemple d’activation de TRACE pour les configurations Debug et Release, en plus de DEBUG pour les configurations Debug.

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <DefineConstants>TRACE</DefineConstants>
</PropertyGroup>

Si vous utilisez Trace lorsqu’il n’est pas attaché au débogueur, vous avez besoin de configurer un écouteur de suivi comme dotnet-trace.

Suivi conditionnel

En plus des méthodes Write et WriteLine simples, il est également possible d’ajouter des conditions avec WriteIf et WriteLineIf. Par exemple, la logique suivante vérifie si le nombre est égal à zéro, puis écrit un message de débogage :

if(count == 0)
{
    Debug.WriteLine("The count is 0 and this may cause an exception.");
}

Vous pouvez le réécrire dans une seule ligne de code :

Debug.WriteLineIf(count == 0, "The count is 0 and this may cause an exception.");

Vous pouvez également utiliser ces conditions avec Trace et avec des indicateurs que vous définissez dans votre application :

bool errorFlag = false;  
System.Diagnostics.Trace.WriteIf(errorFlag, "Error in AppendData procedure.");  
System.Diagnostics.Debug.WriteIf(errorFlag, "Transaction abandoned.");  
System.Diagnostics.Trace.Write("Invalid value for data request");

Vérifier l’existence de certaines conditions

Une assertion, ou instruction Assert, effectue un test de la condition que vous spécifiez comme argument ou instruction Assert. Si la condition prend la valeur true; sinon aucune action n’a lieu. Si la condition prend la valeur false, l’assertion échoue. Si vous exécutez avec une version debug, votre programme passe en mode arrêt.

Vous pouvez utiliser la méthode Assert à partir de Debug ou Trace, dans l’espace de noms System.Diagnostics. Les méthodes de la classe Debug ne sont pas incluses dans une version release de votre programme ; par conséquent, elles n’augmentent pas la taille ou ne réduisent pas la vitesse de votre code de version release.

Utilisez librement la méthode System.Diagnostics.Debug.Assert pour tester les conditions qui doivent avoir la valeur true si votre code est correct. Supposons, par exemple, que vous ayez écrit une fonction de division par entier. Selon les règles mathématiques, le diviseur ne peut pas être égal à zéro. Vous pouvez tester cette condition à l’aide d’une assertion :

int IntegerDivide(int dividend, int divisor)
{
    Debug.Assert(divisor != 0, $"{nameof(divisor)} is 0 and will cause an exception.");

    return dividend / divisor;
}

Quand vous exécutez ce code sous le débogueur, l’instruction d’assertion est évaluée. Toutefois, la comparaison n’est pas effectuée dans la version de mise en production, il n’y a donc aucune surcharge.

Remarque

Lorsque vous utilisez System.Diagnostics.Debug.Assert, vérifiez qu’aucun code à l’intérieur de Assert ne modifie les résultats du programme si Assert est supprimée. Dans le cas contraire, vous risquez d’introduire accidentellement un bogue qui n’apparaît que dans la version release de votre programme. Soyez particulièrement vigilant avec les assertions qui contiennent des appels de fonction ou de procédure.

L’utilisation de Debug et de Trace à partir de l’espace de noms System.Diagnostics est un excellent moyen de fournir plus de contexte lors de l’exécution et du débogage de votre application.