Partager via


TripPin, partie 8 - Ajout de diagnostics

Remarque

Ce contenu fait actuellement référence à celui d’une implémentation héritée pour les diagnostics dans Visual Studio. Le contenu sera mis à jour dans un futur proche pour couvrir le nouveau Kit de développement logiciel (SDK) Power Query dans Visual Studio Code.

Ce tutoriel en plusieurs parties traite de la création d’une extension de source de données pour Power Query. Le tutoriel est destiné à être utilisé de manière séquentielle : chaque leçon s’appuie sur le connecteur créé dans les leçons précédentes, ajoutant de nouvelles fonctionnalités de manière incrémentielle.

Dans cette leçon, vous allez :

  • Découvrir la fonction Diagnostics.Trace
  • Utiliser les fonctions d’assistance Diagnostics pour ajouter des informations de trace afin de faciliter le débogage de votre connecteur

Activation des diagnostics

Les utilisateurs de Power Query peuvent activer la journalisation des traces en cochant la case sous Options | Diagnostic.

Activer le traçage dans Power Query.

Une fois l’option activée, le moteur M émet des informations de trace dans les fichiers journaux situés dans un répertoire utilisateur fixe après chaque requête.

Lors de l’exécution de requêtes M à partir du SDK Power Query, le traçage est activé au niveau du projet. La page des propriétés du projet compte trois paramètres liés au traçage :

  • Effacer le journal : si cette option est définie sur true, le journal est réinitialisé/effacé quand vous exécutez vos requêtes. Nous vous recommandons de conserver la valeur true.
  • Afficher les traces du moteur : ce paramètre contrôle la sortie des traces intégrées du moteur M. Ces traces n’étant utiles qu’aux membres de l’équipe Power Query, vous pouvez généralement conserver la valeur false.
  • Afficher les traces utilisateur : ce paramètre contrôle la sortie des informations de trace par votre connecteur. Définissez ce paramètre sur true.

Propriétés du projet.

Une fois l’option activée, des entrées de journal s’affichent dans la fenêtre Sortie de la requête M, sous l’onglet Journal.

Diagnostics.Trace

La fonction Diagnostics.Trace permet d’écrire des messages dans le journal des traces du moteur M.

Diagnostics.Trace = (traceLevel as number, message as text, value as any, optional delayed as nullable logical as any) => ...

Important

M est un langage fonctionnel à évaluation différée. Quand vous utilisez Diagnostics.Trace, gardez à l’esprit que la fonction n’est appelée que si l’expression dont elle fait partie est réellement évaluée. Vous trouverez des exemples illustrant ceci plus loin dans ce tutoriel.

Le paramètre traceLevel peut prendre l’une des valeurs suivantes (dans l’ordre décroissant) :

  • TraceLevel.Critical
  • TraceLevel.Error
  • TraceLevel.Warning
  • TraceLevel.Information
  • TraceLevel.Verbose

Lorsque le traçage est activé, l’utilisateur peut sélectionner le niveau maximum de messages qu’il souhaite voir. Tous les messages de trace de ce niveau et des niveaux inférieurs sont consignés dans le journal. Par exemple, si l’utilisateur sélectionne le niveau « Avertissement », les messages de trace de TraceLevel.Warning, TraceLevel.Error et TraceLevel.Critical apparaissent dans les journaux.

Le paramètre message est le texte réel qui est généré dans le fichier de trace. Notez que le texte ne contient pas le paramètre value, à moins que vous ne l’incluiez explicitement dans le texte.

Le paramètre value est ce que la fonction retourne. Quand le paramètre delayed est défini sur true, value est une fonction sans aucun paramètre qui retourne la valeur réelle que vous évaluez. Quand delayed est défini sur false, value est la valeur réelle. Un exemple illustrant le fonctionnement de ceci est présenté ci-dessous.

Utilisation de Diagnostics. Trace dans le connecteur TripPin

Pour obtenir un exemple pratique d’utilisation de Diagnostics.Trace et comprendre l’impact du delayed paramètre, mettez à jour la fonction GetSchemaForEntity du connecteur error TripPin pour envelopper l’exception :

GetSchemaForEntity = (entity as text) as type =>
    try
        SchemaTable{[Entity=entity]}[Type]
    otherwise
        let
            message = Text.Format("Couldn't find entity: '#{0}'", {entity})
        in
            Diagnostics.Trace(TraceLevel.Error, message, () => error message, true);

Vous pouvez forcer une erreur durant l’évaluation (à des fins de test) en passant un nom d’entité non valide à la fonction GetEntity. Ici, vous modifiez la ligne withData dans la fonction TripPinNavTable, en remplaçant [Name] par "DoesNotExist".

TripPinNavTable = (url as text) as table =>
    let
        // Use our schema table as the source of top level items in the navigation tree
        entities = Table.SelectColumns(SchemaTable, {"Entity"}),
        rename = Table.RenameColumns(entities, {{"Entity", "Name"}}),
        // Add Data as a calculated column
        withData = Table.AddColumn(rename, "Data", each GetEntity(url, "DoesNotExist"), type table),
        // Add ItemKind and ItemName as fixed text values
        withItemKind = Table.AddColumn(withData, "ItemKind", each "Table", type text),
        withItemName = Table.AddColumn(withItemKind, "ItemName", each "Table", type text),
        // Indicate that the node should not be expandable
        withIsLeaf = Table.AddColumn(withItemName, "IsLeaf", each true, type logical),
        // Generate the nav table
        navTable = Table.ToNavigationTable(withIsLeaf, {"Name"}, "Name", "Data", "ItemKind", "ItemName", "IsLeaf")
    in
        navTable;

Activez le traçage pour votre projet et exécutez vos requêtes de test. Sous l’onglet Errors, vous devriez voir le texte de l’erreur que vous avez déclenchée :

Message d’erreur.

Sous l’onglet Log, vous devriez voir le même message. Si vous utilisez des valeurs différentes pour les paramètres message et value, ces derniers seront différents.

Journal des erreurs.

Notez également que le champ Action du message de journal contient le nom (Genre de source de données) de votre extension (dans ce cas, Engine/Extension/TripPin). Cela facilite la recherche des messages liés à votre extension quand plusieurs requêtes sont impliquées et/ou le traçage du système (moteur de mashup) est activé.

Évaluation différée

Pour illustrer le fonctionnement du paramètre delayed, vous allez apporter quelques modifications et réexécuter les requêtes.

Commencez par définir la valeur de delayed sur false, mais gardez le paramètre value tel quel :

Diagnostics.Trace(TraceLevel.Error, message, () => error message, false);

Lorsque vous exécutez la requête, vous recevez l’erreur « Désolé... Nous n’avons pas pu convertir une valeur de type Fonction en type Type », et non l’erreur réelle que vous avez levée. Cela est dû au fait que l’appel retourne maintenant une valeur function, et non la valeur elle-même.

Ensuite, supprimez la fonction value du paramètre :

Diagnostics.Trace(TraceLevel.Error, message, error message, false);

Quand vous exécutez la requête, vous recevez la bonne erreur, mais aucun message ne figure sous l’onglet Journal. Cela est dû au fait que error finit par être déclenché/évalué pendant l’appel à Diagnostics.Trace. Le message n’est donc jamais réellement généré.

Maintenant que vous comprenez l’impact du paramètre delayed, pensez à remettre votre connecteur dans un état opérationnel avant de continuer.

Fonctions d’assistance de diagnostic dans Diagnostics.pqm

Le fichier Diagnostics.pqm inclus dans ce projet contient un certain nombre de fonctions d’assistance qui facilitent le suivi. Comme indiqué dans le tutoriel précédent, vous pouvez inclure ce fichier dans votre projet (en n’oubliant pas de définir Action de génération de build sur Compiler), puis le charger dans votre fichier de connecteur. La partie inférieure de votre fichier de connecteur doit maintenant ressembler à l’extrait de code ci-dessous. N’hésitez pas à explorer les différentes fonctions fournies par ce module. Toutefois, dans cet exemple, vous n’utiliserez que les fonctions Diagnostics.LogValue et Diagnostics.LogFailure.

// Diagnostics module contains multiple functions. We can take the ones we need.
Diagnostics = Extension.LoadFunction("Diagnostics.pqm");
Diagnostics.LogValue = Diagnostics[LogValue];
Diagnostics.LogFailure = Diagnostics[LogFailure];

Diagnostics.LogValue

La fonction Diagnostics.LogValue ressemble beaucoup à Diagnostics.Trace et peut être utilisée pour afficher la valeur de ce que vous évaluez.

Diagnostics.LogValue = (prefix as text, value as any) as any => ...

Le paramètre prefix est ajouté au début du message de journal. Vous pouvez l’utiliser pour déterminer l’appel ayant généré le message. Le paramètre value est ce que la fonction retourne et est également écrit dans la trace en tant que représentation textuelle de la valeur M. Par exemple, si value est égal à une table avec des colonnes A et B, le journal contient la représentation #table équivalente : #table({"A", "B"}, {{"row1 A", "row1 B"}, {"row2 A", row2 B"}})

Remarque

La sérialisation des valeurs M en texte peut être une opération coûteuse. Tenez compte de la taille potentielle des valeurs que vous générez dans la trace.

Remarque

La plupart des environnements Power Query tronquent les messages de trace selon une longueur maximale.

En guise d’exemple, vous allez mettre à jour la fonction TripPin.Feed pour effectuer le traçage des arguments url et schema passés à la fonction.

TripPin.Feed = (url as text, optional schema as type) as table =>
    let
        _url = Diagnostics.LogValue("Accessing url", url),
        _schema = Diagnostics.LogValue("Schema type", schema),
        //result = GetAllPagesByNextLink(url, schema)
        result = GetAllPagesByNextLink(_url, _schema)
    in
        result;

Vous devez utiliser les nouvelles valeurs _url et _schema dans l’appel à GetAllPagesByNextLink. Si vous utilisez les paramètres de fonction d’origine, les appels Diagnostics.LogValue ne sont jamais réellement évalués et aucun message n’est écrit dans la trace. La programmation fonctionnelle, c’est amusant !

Quand vous exécutez vos requêtes, vous devriez maintenant voir de nouveaux messages dans le journal.

Accès à l’url :

Accès au message de l’url.

Type de schéma :

Message de type de schéma.

La version sérialisée du paramètre schema type est affichée. Le résultat obtenu est différent si vous faites un simple Text.FromValue sur une valeur de type (ce qui donne « type »).

Diagnostics.LogFailure

La fonction Diagnostics.LogFailure peut être utilisée pour wrapper des appels de fonction et n’écrit dans la trace que si l’appel de fonction échoue (autrement dit, s’il retourne error).

Diagnostics.LogFailure = (text as text, function as function) as any => ...

En interne, Diagnostics.LogFailure ajoute un opérateur try à l’appel function. Si l’appel échoue, la valeur text est écrite dans la trace avant de retourner l’origine error. Si l'appel function réussit, le résultat est retourné sans rien écrire dans la trace. Étant donné que les erreurs M ne contiennent pas une trace de pile complète (autrement dit, vous ne voyez généralement que le message de l’erreur), cela peut être utile si vous souhaitez identifier où l’erreur a réellement été levée.

À titre d’exemple (médiocre), modifiez la ligne withData de la fonction TripPinNavTable pour forcer à nouveau une erreur :

withData = Table.AddColumn(rename, "Data", each Diagnostics.LogFailure("Error in GetEntity", () => GetEntity(url, "DoesNotExist")), type table),

Dans la trace, vous pouvez trouver le message d’erreur résultant contenant votre text et les informations d’erreur d’origine.

Message LogFailure.

Pensez à remettre votre fonction dans un état opérationnel avant de passer au tutoriel suivant.

Conclusion

Cette brève leçon (mais importante) vous a montré comment utiliser les fonctions d’assistance de diagnostic pour consigner des informations dans les fichiers de trace Power Query. Utilisées correctement, ces fonctions peuvent être utiles pour déboguer des problèmes au sein de votre connecteur.

Remarque

En tant que développeur de connecteurs, il vous appartient de vérifier que vous ne consignez pas d’informations sensibles ou d’identification personnelle (PII) dans le cadre de votre journalisation de diagnostics. Vous devez également veiller à ne pas générer trop d’informations de trace, car cela peut avoir un impact négatif sur les performances.

Étapes suivantes

TripPin, partie 9 - TestConnection