Instructions de requête Analytique OData pour Azure DevOps

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2019

Les développeurs d’extensions peuvent bénéficier en suivant les instructions fournies dans cet article pour concevoir des requêtes OData efficaces sur Analytique pour Azure DevOps. Le suivi de ces instructions permet de s’assurer que les requêtes présentent de bonnes performances pour le temps d’exécution et la consommation des ressources. Les requêtes qui ne respectent pas ces instructions peuvent entraîner des performances médiocres, avec des temps d’attente longs de rapport, des requêtes qui dépassent la consommation de ressources autorisée ou des blocages de service.

Remarque

Le service Analytique est automatiquement activé et pris en charge en production pour tous les services Azure DevOps. L’intégration de Power BI et l’accès au flux OData du service Analytique sont généralement disponibles. Nous vous encourageons à l’utiliser et à nous faire part de vos commentaires. Les données disponibles dépendent de la version. La dernière version prise en charge est v2.0, et la dernière version d’évaluation est v4.0-preview. Pour plus d’informations, consultez gestion des versions de l’API OData.

Remarque

Le service Analytique est automatiquement installé et pris en charge en production pour toutes les nouvelles collections de projets pour Azure DevOps Server 2020 et versions ultérieures. L’intégration de Power BI et l’accès au flux OData du service Analytique sont généralement disponibles. Nous vous encourageons à l’utiliser et à nous faire part de vos commentaires. Si vous avez effectué une mise à niveau à partir d’Azure DevOps Server 2019, vous pouvez installer le service Analytique pendant la mise à niveau.

Les données disponibles dépendent de la version. La dernière version prise en charge est v2.0, et la dernière version d’évaluation est v4.0-preview. Pour plus d’informations, consultez gestion des versions de l’API OData.

Remarque

Le service Analytique est en préversion pour Azure DevOps Server 2019. Vous pouvez l’activer ou l’installer pour une collection de projets. L’intégration de Power BI et l’accès au flux OData du service Analytique sont en préversion. Nous vous encourageons à l’utiliser et à nous faire part de vos commentaires.

Les données disponibles dépendent de la version. La dernière version prise en charge est v2.0, et la dernière version d’évaluation est v4.0-preview. Pour plus d’informations, consultez gestion des versions de l’API OData.

Ces recommandations sont précédées des termes DO, CONSIDER, AVOID et DON’T. Les règles restrictives appliquées par Analytique contiennent le préfixe [BLOCKED]. Vous devez comprendre les compromis entre différentes solutions. Dans certaines circonstances, vous pouvez avoir des exigences de données qui vous obligent à violer une ou plusieurs instructions. Ces cas doivent être rares. Nous vous recommandons d’avoir une raison claire et convaincante pour ces décisions.

Conseil

Les exemples présentés dans ce document sont basés sur une URL Azure DevOps Services. Utilisez des substitutions pour les versions locales.

https://{servername}:{port}/tfs/{OrganizationName}/{ProjectName}/_odata/{version}/

Messages d’erreur et d’avertissement

✔️ Vérifier les avertissements de réponse OData

Chaque requête que vous exécutez est vérifiée par rapport à un ensemble de règles prédéfinies. Les violations retournent la réponse OData suivante @vsts.warnings. Passez en revue ces avertissements, car ils fournissent des informations actuelles et contextuelles sur la façon d’améliorer votre requête.

{
  "@odata.context": "https://{OrganizationName}.tfsallin.net/_odata/v1.0/$metadata#WorkItems",
  "@vsts.warnings": [
    "The specified query does not include a $select or $apply clause which is recommended for all queries."
  ],
  ...
}

✔️ Vérifier les messages d’erreur OData

Les requêtes qui violent une règle d’erreur OData entraînent une réponse ayant échoué avec un code d’état 400 (Requête incorrecte). Les messages associés n’apparaissent pas dans la @vsts.warnings propriété. Au lieu de cela, ils génèrent un message d’erreur dans la message propriété dans la réponse JSON.

{
  "error": {
  "code": "0",
  "message": "The query specified in the URI is not valid. The Snapshot tables in Analytics are intended to be used only in an aggregation."
  }
}

Restrictions

Pratiques conseillées

Consider

Bloqué

Éviter

✔️ Limitez la requête au ou aux projets auquel vous avez accès

Si votre requête cible les données d’un projet auquel vous n’avez pas accès, la requête retourne un message « Accès au projet refusé ». Pour vous assurer que vous disposez d’un accès, vérifiez que votre autorisation d’affichage analytique est définie sur Autoriser pour tous les projets que vous interrogez. Pour plus d’informations, consultez Autorisations requises pour accéder à Analytique.

Si vous n’avez pas accès à un projet, le message suivant s’affiche :

Les résultats de la requête incluent des données dans un ou plusieurs projets pour lesquels vous n’avez pas accès. Ajoutez un ou plusieurs filtres de projets pour spécifier le ou les projets auquel vous avez accès dans l’entité « WorkItems ». Si vous utilisez des propriétés $expand ou de navigation, le filtre de projet est requis pour ces entités.

Pour contourner ce problème, vous pouvez ajouter explicitement un filtre de projet ou utiliser le point de terminaison étendu au projet, comme expliqué plus loin dans cet article.

Par exemple, la requête suivante extrait des éléments de travail qui appartiennent à des projets nommés {projectSK1} et {projectSK2}.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=ProjectSK eq {projectSK1} or ProjectSK eq {projectSK2}
  &$select=WorkItemId, Title

✔️ Spécifiez le filtre de projet à l’intérieur de la $expand clause si votre extension peut inclure des données dans d’autres projets potentiellement inaccessibles

Lorsque vous développez des propriétés de navigation, il est possible que vous finissent par référencer des données à partir d’autres projets inaccessibles. Si vous référencez des données inaccessibles, vous recevez le même message d’erreur répertorié précédemment, « Les résultats de la requête incluent des données dans un ou plusieurs projets... ». De même, vous pouvez résoudre ce problème en ajoutant des filtres de projet explicites pour contrôler les données développées.

Vous pouvez le faire dans la clause régulière $filter pour les propriétés de navigation simples. Par exemple, la requête suivante demande WorkItemLinks explicitement où le lien et sa cible existent dans le même projet.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemLinks?
  $filter=ProjectSK eq {projectSK} and TargetWorkItem/ProjectSK eq {projectSK}
  &$select=LinkTypeReferenceName, SourceWorkItemId, TargetWorkItemId
  &$expand=TargetWorkItem($select=WorkItemId, Title)

Au lieu de cela, vous pouvez déplacer le filtre pour $filter développer l’option dans la $expand clause. Toutefois, elle modifie la sémantique de la requête. Par exemple, la requête suivante obtient tous les liens d’un projet donné et développe conditionnellement la cible uniquement s’il existe dans le même projet. Bien qu’elle soit valide, cette approche peut entraîner une confusion, car il peut être difficile de déterminer si une propriété n’est pas développée, car elle est null ou parce qu’elle a été filtrée. Utilisez cette solution uniquement si vous avez vraiment besoin de ce comportement particulier.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemLinks?
  $filter=ProjectSK eq {projectSK}
  &$select=LinkTypeReferenceName, SourceWorkItemId, TargetWorkItemId
  &$expand=TargetWorkItem($filter=ProjectSK eq {projectSK}; $select=WorkItemId, Title)

L’option $filter expand est utile lorsque vous utilisez la propriété expand collection telle que Children dans WorkItems l’ensemble d’entités. Par exemple, la requête suivante retourne tous les éléments de travail d’un projet donné, ainsi que tous leurs enfants appartenant au même projet.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=ProjectSK eq {projectSK}
  &$select=WorkItemId, Title
  &$expand=Children($filter=ProjectSK eq {projectSK}; $select=WorkItemId, Title)

Spécifiez le filtre si vous développez l’une des propriétés suivantes :

  • WorkItems jeu d’entités : Parent, Children
  • WorkItemLinks jeu d’entités : TargetWorkItem.

✔️ ENVISAGEZ d’interroger à l’aide du point de terminaison étendu au projet

Si vous êtes intéressé par les données d’un seul projet, nous vous recommandons d’utiliser le point de terminaison OData étendu au projet (/{ProjectName}/_odata/v1.0). Il évite les problèmes décrits dans les deux sections précédentes et filtre implicitement les données dans le projet un, le jeu d’entités référencé et toutes les propriétés de navigation développées.

Avec cette simplification, les requêtes de la section précédente peuvent être réécrites dans le formulaire suivant. Non seulement le filtre dans la clause expand a disparu, mais il n’y a pas besoin du filtre sur le jeu d’entités principal.

https://analytics.dev.azure.com/{OrganizationName}/{ProjectName}/_odata/{version}//WorkItemLinks?
  &$select=LinkTypeReferenceName, SourceWorkItemId, TargetWorkItemId
  &$expand=TargetWorkItem($select=WorkItemId, Title)

La requête pour les enfants d’éléments de travail est également beaucoup plus courte et plus simple.

https://analytics.dev.azure.com/{OrganizationName}/{ProjectName}/_odata/{version}//WorkItems?
  &$select=WorkItemId, Title
  &$expand=Children($select=WorkItemId, Title)

Vous pouvez appliquer cette solution uniquement lorsque votre focus est des données d’un seul projet. Pour la création de rapports entre projets, vous devez utiliser des stratégies de filtrage décrites dans les sections précédentes.

✔️ Attendez ou arrêtez l’opération si votre requête dépasse les limites d’utilisation

Si vous exécutez de nombreuses requêtes ou que les requêtes nécessitent de nombreuses ressources à exécuter, vous pouvez dépasser les limites de service et être temporairement bloqués. Si vous dépassez les limites du service, arrêtez votre opération, car il est probable que la requête suivante que vous envoyez échoue avec le même message d’erreur.

La demande a été bloquée en raison du dépassement de l’utilisation de la ressource « {resource} » dans l’espace de noms « {espace de noms} ».

Pour plus d’informations sur la limitation du débit, consultez Limites de débit. Pour savoir comment concevoir des requêtes OData efficaces, reportez-vous aux instructions de performances plus loin dans cet article.

✔️ Patientez ou arrêtez l’opération en cas d’échec de votre requête avec un délai d’expiration

Comme pour dépasser les limites d’utilisation, vous devez attendre ou arrêter l’opération si votre requête rencontre un délai d’expiration. Il peut signaler un problème temporaire. Vous pouvez donc réessayer une fois pour voir si le problème est résolu. Toutefois, les délais d’expiration persistants indiquent que la requête est probablement trop coûteuse à exécuter. De nouvelles tentatives entraînent uniquement un dépassement des limites d’utilisation et vous êtes bloqué.

TF400733 : la demande a été annulée : la demande a dépassé le délai d’expiration de la demande, réessayez.

Les délais d’expiration indiquent qu’une requête nécessite une optimisation. Pour savoir comment concevoir des requêtes OData efficaces, consultez les recommandations en matière de performances plus loin dans cet article.

❌ [BLOQUÉ] N’utilisez pas d’entités d’instantané pour quoi que ce soit d’autre que les agrégations

Les jeux d’entités d’instantanés avec le Snapshot suffixe sont spéciaux, car ils sont modélisés comme instantanés quotidiens. Vous pouvez les utiliser pour obtenir un état d’entités tel qu’elles étaient à la fin de chaque jour dans le passé. Par exemple, si vous avez interrogé WorkItemSnapshot et filtré sur un seul WorkItemIdenregistrement, vous obtenez un enregistrement pour chaque jour depuis la création de l’élément de travail. Le chargement direct de toutes ces données serait coûteux et probablement dépasserait les limites d’utilisation et serait bloqué. Toutefois, les agrégations sur ces entités sont autorisées et recommandées. En fait, les jeux d’entités d’instantané ont été conçus avec des scénarios d’agrégation à l’esprit.

Par exemple, la requête suivante obtient le nombre d’éléments de travail comme date pour observer comment elle a augmenté en janvier 2020.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemSnapshot?
  $apply=
    filter(DateSK ge 20200101 and DateSK le 20200131)/
    groupby((DateSK), aggregate($count as Count))

Pour plus d’informations sur les agrégations, consultez Données d’agrégation.

✔️ DO include DateSK ou DateValue column in groupby clause when you aggregate over snapshot tables

Étant donné que toutes les entités d’instantané sont modélisées en tant que tables d’instantanés quotidiennes, vous devez toujours inclure l’une des propriétés de jour (DateSK ou DateValue) dans la clause de regroupement. Sinon, le résultat peut apparaître incorrectement gonflé.

Par exemple, si vous n’avez regroupé WorkItemSnapshot que par AssignedTo propriété et agrègez-le avec le nombre, tous les nombres d’éléments de travail attribués aux personnes seraient multipliés par le nombre de jours où chaque affectation était active. Bien que vous ayez peut-être une situation où il s’agit du résultat souhaité, ces cas sont rares.

❌ [BLOQUÉ] N’utilisez pas de clés d’entité dans les chemins d’accès aux ressources pour l’adressage d’entité

La syntaxe OData permet d’accéder à une entité particulière en incluant ses clés directement dans les segments d’URL. Pour plus d’informations, consultez OData version 4.0. Partie 2 : Conventions d’URL - 4.3 Entités d’adressage. Bien qu’OData autorise ce type d’adressage, Analytique le bloque. L’inclusion dans une requête entraîne l’erreur suivante.

La requête spécifiée dans l’URI n’est pas valide. Analytique ne prend pas en charge la navigation de clé ou de propriété comme WorkItems(Id) ou WorkItem(Id)/AssignedTo. Si vous obtenez cette erreur dans PowerBI, réécrivez votre requête pour éviter le pliage incorrect qui provoque un problème N+1.

Comme les indicateurs de messages d’erreur, certains outils clients peuvent abuser de l’adressage direct d’entité. Au lieu de charger toutes les données dans une seule requête, ces clients peuvent choisir d’interroger chaque entité indépendamment. Cette pratique est déconseillée, car elle peut entraîner un nombre élevé de demandes. Au lieu de cela, nous vous recommandons d’utiliser l’adressage d’entité explicite, comme expliqué dans la section suivante.

✔️ DO adresse explicitement des entités avec des clauses de filtre

Si vous souhaitez extraire des données pour une entité unique, vous devez utiliser la même approche que pour une collection d’entités et définir explicitement des filtres dans la $filter clause.

Par exemple, la requête suivante obtient un élément de travail unique par son identificateur.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=WorkItemId eq {id}
  &$select=WorkItemId, Title

Si vous ne savez pas quelles propriétés vous devez inclure dans un tel filtre, vous pouvez la rechercher dans les métadonnées. Consultez Construire des requêtes OData pour Analytique, composants d’URL pour interroger les métadonnées. Les propriétés se trouvent dans l’élément Key du EntityType. Par exemple, WorkItemId et Revision sont des colonnes clés pour l’entité WorkItemRevision .

<EntityType Name="WorkItemRevision">
  <Key>
    <PropertyRef Name="WorkItemId"/>
    <PropertyRef Name="Revision"/>
  </Key>
  [...]
</EntityType>

❌[BLOQUÉ] NE pas développer Revisions l’entité WorkItem

Le modèle de données Analytique interdit certains types d’expansions. L’un d’eux, qui peut être surprenant à certains, est la Revisions propriété de collection sur l’entité WorkItem . Si vous essayez de développer cette propriété, vous recevez le message d’erreur suivant.

La requête spécifiée dans l’URI n’est pas valide. La propriété « Revisions » ne peut pas être utilisée dans l’option de requête $expand.

Cette restriction a été mise en place pour encourager tout le monde à utiliser la solution recommandée, qui extrait les révisions WorkItemRevisions comme expliqué dans la section suivante.

✔️ Utiliser l’ensemble WorkItemRevisions d’entités pour charger toutes les révisions d’un élément de travail donné

Utilisez WorkItemRevisions chaque fois que vous souhaitez récupérer l’historique complet d’un élément de travail ou d’une collection d’éléments de travail.

Par exemple, la requête suivante retourne toutes les révisions d’un élément de travail avec l’identificateur {id} .

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemRevisions?
  $filter=WorkItemId eq {id}
  &$select=WorkItemId, Title

Si vous vous souciez de l’historique complet de tous les éléments de travail qui correspondent à certains critères, exprimez-le à l’aide d’un filtre sur la propriété de WorkItem navigation. Par exemple, la requête suivante obtient toutes les révisions de tous les éléments de travail actuellement actifs.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemRevisions?
  $filter=WorkItem/State eq 'Active'
  &$select=WorkItemId, Title

❌ [BLOQUÉ] NE PAS regrouper sur des colonnes distinctes

Vous utilisez une opération de regroupement pour réduire le nombre d’enregistrements. L’utilisation de colonnes distinctes dans la groupby clause indique un problème et la requête échoue immédiatement. Si vous rencontrez accidentellement cette situation, vous recevez le message d’erreur suivant.

Une ou plusieurs des colonnes spécifiées dans la clause groupby de cette requête ne sont pas recommandées.

Pour résoudre ce problème, supprimez la colonne distincte de la groupby clause.

❌ [BLOQUÉ] N’utilisez countdistinct pas l’agrégation

Analytique ne prend pas en charge la countdistinct fonction, même si OData le fait. Même si nous prévoyons d’ajouter du support à l’avenir, il n’est actuellement pas disponible. Une requête qui contient cette fonction retourne le message d’erreur suivant.

Les requêtes qui appliquent un nombre distinct avec une agrégation ne sont pas prises en charge.

❌ ÉVITER les agrégations qui peuvent entraîner un dépassement arithmétique

Dans de rares cas, une requête d’agrégation peut rencontrer des problèmes de dépassement arithmétique. Par exemple, il peut se produire lorsque vous additionnez certaines propriétés numériques qui ne sont pas destinées à la somme, comme StackRank dans les entités d’élément de travail. Étant donné que l’extension OData pour la norme d’agrégation de données ne permet pas de convertir une propriété en un autre type, la seule façon de résoudre ce problème consiste à supprimer la propriété problématique de l’agrégation.

✔️ Utiliser le point de terminaison batch pour les requêtes longues

Vous pouvez rencontrer des problèmes avec de longues requêtes. En particulier, des problèmes peuvent se produire quand :

  • Vous interrogez un projet avec de nombreux champs personnalisés.
  • Votre requête est construite par programmation.

La limite actuelle des requêtes OData envoyées est HTTP GET de 3 000 caractères. Si vous la dépassez, vous obtenez une réponse « 404 Introuvable ».

HTTP/1.1 404 Not Found
Content-Length: 0

Pour résoudre ce problème, utilisez le point de terminaison de lot OData, comme expliqué dans la spécification, OData Version 4.0. Partie 1 : Protocole - Requêtes par lots 11.7. La fonctionnalité Batch a principalement été conçue pour regrouper plusieurs opérations dans une charge utile de requête unique HTTP , mais vous pouvez également l’utiliser comme solution de contournement pour la limitation de longueur de requête. En envoyant une HTTP POST requête, vous pouvez passer une requête d’une longueur arbitraire et le service l’interprète correctement.

❌ [BLOQUÉ] N’utilisez pas de point de terminaison batch pour l’envoi de plusieurs requêtes

Nous limitons l’utilisation du point de terminaison de traitement par lots de plusieurs requêtes. Une seule requête ne peut toujours avoir qu’une seule requête. Si vous essayez d’envoyer un lot de plusieurs requêtes, l’opération échoue avec le message d’erreur suivant. La seule solution consiste à fractionner des requêtes en plusieurs requêtes.

Analytique ne prend pas en charge le traitement de plusieurs opérations que contient le message de lot actuel. Analytique utilise le lot OData pour prendre en charge les requêtes POST, mais vous devez limiter l’opération à une seule requête.

❌ [BLOQUÉ] N’utilisez pas de requêtes qui entraînent plus de 800 colonnes

Nous limitons les requêtes qui entraînent plus de 800 colonnes. Si vous n’êtes pas suffisamment sélectif dans les colonnes retournées par votre requête, vous pouvez recevoir le message d’erreur suivant.

VS403670 : la requête spécifiée retourne des colonnes « N » supérieures à la limite autorisée de 800 colonnes. Utilisez des options de $select explicites (y compris dans le $expand) pour limiter le nombre de colonnes.

Ajoutez une clause $select à votre requête et $expand opérations dans votre requête pour éviter de dépasser cette limite.

❌ ÉVITER de créer des requêtes longues

Nous vous recommandons d’évaluer votre approche chaque fois que vous construisez une longue requête. Bien qu’il existe de nombreux scénarios nécessitant une longue requête (par exemple, des filtres complexes ou une longue liste de propriétés), ils fournissent généralement un indicateur précoce d’une conception non optimale.

Lorsque votre requête contient de nombreuses clés d’entité dans la requête (par exemple, WorkItemId eq {id 1} or WorkItemId eq {id 2} or ...), vous pouvez probablement la réécrire. Au lieu de passer les identificateurs, essayez de définir d’autres critères qui sélectionnent le même ensemble d’entités. Parfois, vous devrez peut-être modifier votre processus (par exemple, ajouter un nouveau champ ou une balise), mais cela vaut généralement la peine. Les requêtes qui utilisent des filtres plus abstraits sont plus faciles à gérer et peuvent mieux fonctionner.

Un autre scénario qui tend à générer des requêtes longues se produit lorsque vous incluez de nombreuses dates individuelles (par exemple). DateSK eq {dateSK 1} or DateSK eq {dateSK 2} or ... Recherchez un autre modèle que vous pouvez utiliser pour créer un filtre plus abstrait. Par exemple, la requête suivante retourne tous les éléments de travail créés le lundi.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedOn/DayOfWeek eq 2
  &$select=WorkItemId, Title, State

✔️ Spécifier le fuseau horaire lors du filtrage sur les colonnes de date

Le fuseau horaire (Edm.DateTimeOffset) expose toutes les informations de date et d’heure avec un décalage qui correspond aux paramètres de fuseau horaire de l’organisation. Ces données sont précises et simples à interpréter en même temps. Une autre conséquence non discrète est que tous les filtres doivent également transmettre les informations de fuseau horaire. Si vous l’ignorez, vous obtenez le message d’erreur suivant.

La requête spécifiée dans l’URI n’est pas valide. Aucun décalage datetime n’a été spécifié. Utilisez l’un de ces formats AAAA-MM-JJZ pour spécifier tout depuis minuit ou aaaa-MM-jjThh :mm-hh :mm (représentation standard ISO 8601 de dates et d’heures) pour spécifier le décalage.

Pour résoudre ce problème, ajoutez les informations de fuseau horaire. Par exemple, en supposant que l’organisation est configurée pour afficher les données dans le fuseau horaire « (UTC-08:00) Pacific Time (ÉTATS-Unis et Canada), la requête suivante obtient tous les éléments de travail créés depuis le début de 2020.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDate ge 2020-01-01T00:00:00-08:00
  &$select=WorkItemId, Title, State

La même solution fonctionne pour les fuseaux horaires avec des décalages positifs, cependant, le caractère plus (+) a une signification spéciale dans l’URI et vous devez le gérer correctement. Si vous spécifiez 2020-01-01T00:00:00+08:00 (avec un + caractère) comme point de départ, vous obtenez l’erreur suivante.

La requête spécifiée dans l’URI n’est pas valide. Erreur de syntaxe à la position 31 dans « CreatedDate ge 2020-01-01T0000 08:00 ».

Pour le résoudre, remplacez le + caractère par sa version encodée. %2B Par exemple, en supposant que l’organisation est configurée pour afficher les données dans le fuseau horaire « (UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi », la requête suivante retourne tous les éléments de travail créés depuis le début de 2020.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDate ge 2020-01-01T00:00:00%2B08:00
  &$select=WorkItemId, Title, State

Une autre approche consiste à utiliser les propriétés de clé de substitution de date, car elles ne conservent pas les informations de fuseau horaire. Par exemple, la requête suivante retourne tous les éléments de travail créés depuis le début de 2020, quels que soient les paramètres de l’organisation.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDateSK ge 20200101
  &$select=WorkItemId, Title, State

Recommandations sur les performances

Pratiques conseillées

N’est pas

Consider

Éviter

✔️ Mesurer l’effet de l’implémentation d’une directive sur les performances

Comme avec les recommandations de performances, vous ne devez pas les implémenter aveuglement. Au lieu de cela, capturez toujours la ligne de base et mesurez l’effet des modifications que vous apportez. Toutes les lignes directrices ont été créées en fonction des interactions avec les clients de Analytique qui avaient des exigences et des défis spécifiques. Ces recommandations ont été considérées comme générales et potentiellement utiles pour toute personne qui conçoit des requêtes similaires. Toutefois, dans de rares cas, le fait de suivre les instructions ne pouvait avoir aucun effet ou même un effet négatif sur les performances. Vous devez mesurer la différence pour la remarquer. Si cela se produit, fournissez des commentaires dans le portail de la Communauté des développeurs.

Il existe de nombreuses options pour mesurer les performances. La plus simple consiste à exécuter deux versions de la même requête directement dans le navigateur. Observez le temps nécessaire aux outils de développement. Par exemple, vous pouvez utiliser le panneau Réseau dans les outils de développement Microsoft Edge F12. Une autre option consiste à capturer ces informations à l’aide de l’outil de débogueur Web Fiddler.

Quelle que soit votre approche, exécutez les deux requêtes plusieurs fois. Par exemple, exécutez les requêtes 30 fois chacune pour avoir un ensemble d’échantillons suffisamment volumineux. Ensuite, déterminez les caractéristiques de performances. Analytique suit l’architecture mutualisée. Par conséquent, d’autres opérations se produisant en même temps peuvent affecter la durée de vos requêtes.

✔️ Utiliser des extensions d’agrégation

De loin, la meilleure chose que vous pouvez faire pour améliorer les performances de vos requêtes consiste à utiliser l’extension d’agrégation - Extension OData pour l’agrégation de données. Avec l’extension d’agrégation, demandez au service de synthétiser le serveur de données et de retourner une réponse plus petite que ce que vous pouvez extraire en appliquant le même côté client de fonction. Enfin, Analytique est optimisé pour ce type de requêtes, donc utilisez-le.

Pour plus d’informations, consultez Données agrégées.

✔️ Spécifier des colonnes dans la $select clause

Spécifiez les colonnes qui vous intéressent dans la $select clause. Analytique repose sur une technologie Columnstore Index . Cela signifie que les données sont à la fois le stockage et le traitement des requêtes est basé sur des colonnes. En réduisant l’ensemble de propriétés, vous référencez dans $select la clause vous pouvez réduire le nombre de colonnes qui doivent être analysées et améliorer les performances globales de la requête.

Par exemple, la requête suivante spécifie les colonnes des éléments de travail.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $select=WorkItemId, Title, State

Remarque

Azure DevOps prend en charge la personnalisation des processus. Certains administrateurs utilisent cette fonctionnalité et créent des centaines de champs personnalisés. Si vous omettez la $select clause, votre requête retourne tous les champs, y compris les champs personnalisés.

✔️ Spécifier des colonnes dans l’option développer à l’intérieur $select de la $expand clause

Comme pour les instructions de $select clause, spécifiez les propriétés de l’option $select expand dans la $expand clause. Il est facile d’oublier, mais si vous l’omettez, votre réponse contient toutes les propriétés de l’objet développé.

Par exemple, la requête suivante spécifie les colonnes de l’élément de travail et de son parent.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $select=WorkItemId, Title, State
  &$expand=Parent($select=WorkItemId, Title, State)

✔️ Définissez un filtre RevisedDateSK lorsque vous interrogez des données d’éléments de travail historiques (WorkItemRevisions ou WorkItemSnapshot des jeux d’entités)

Lorsque vous interrogez des données historiques, les chances sont que vous êtes intéressé par la période la plus récente (par exemple, 30 jours, 90 jours). En raison de la façon dont les entités d’éléments de travail sont implémentées, il existe un moyen pratique d’écrire ces requêtes pour obtenir de bonnes performances. Chaque fois que vous mettez à jour un élément de travail, il crée une nouvelle révision et enregistre cette action dans le System.RevisedDate champ, ce qui le rend parfait pour les filtres d’historique.

Dans Analytique, la date révisée est affichée dans les RevisedDate propriétés (Edm.DateTimeOffset) et RevisedDateSK (Edm.Int32). Pour des performances optimales, utilisez-la. Il s’agit de la clé de substitution de date et représente la date à laquelle une révision a été créée ou qu’elle a null pour les révisions actives et incomplètes. Si vous souhaitez toutes les dates depuis l’inclus {startDate} , ajoutez le filtre suivant à votre requête.

RevisedDateSK eq null or RevisedDateSK gt {startDateSK}

Par exemple, la requête suivante retourne le nombre d’éléments de travail pour chaque jour depuis le début de 2020. Notez qu’en dehors du filtre évident sur DateSK la colonne, il y a un deuxième filtre sur RevisedDateSK. Bien qu’il semble redondant, il aide le moteur de requête à filtrer les révisions qui ne sont pas dans l’étendue et améliore considérablement les performances des requêtes.

https://analytics.dev.azure.com/{OrganizationName}/_odata/v1.0/WorkItemSnapshot?
  $apply=
    filter(DateSK gt 20200101)/
    filter(RevisedDateSK eq null or RevisedDateSK gt 20200101)/
    groupby(
      (DateValue), 
      aggregate($count as Count)
    )

Remarque

Nous avons fourni cette recommandation lorsque nous travaillions sur les widgets Burndown. Initialement, nous avons défini des filtres uniquement pour DateSK mais nous n’avons pas pu obtenir cette requête pour s’adapter correctement aux organisations avec des jeux de données volumineux. Lors du profilage des requêtes, nous avons remarqué que DateSK cela ne filtre pas correctement les révisions. Seulement après l’ajout d’un filtre, RevisedDateSK nous avons pu obtenir de bonnes performances à grande échelle.
~ Équipe produit

✔️ Utiliser des instantanés hebdomadaires ou mensuels pour les requêtes de tendance qui s’étendent sur une longue période

Par défaut, toutes les tables d’instantanés sont modélisées en tant que tables de faits d’instantané quotidiennes. Si vous interrogez un intervalle de temps, il obtient une valeur pour chaque jour. Les intervalles de temps longs entraînent un grand nombre d’enregistrements. Si vous n’avez pas besoin d’une telle précision, vous pouvez utiliser des instantanés hebdomadaires ou même mensuels.

Vous pouvez le faire avec d’autres expressions de filtre pour supprimer des jours qui ne terminent pas une semaine ou un mois donné. Utilisez la IsLastDayOfPeriod propriété, qui a été ajoutée à Analytique avec ce scénario à l’esprit. Cette propriété est de type Microsoft.VisualStudio.Services.Analytics.Model.Period et peut déterminer si un jour se termine dans différentes périodes (par exemple, semaines, mois, etc.).

<EnumType Name="Period" IsFlags="true">
  <Member Name="None" Value="0"/>
  <Member Name="Day" Value="1"/>
  <Member Name="WeekEndingOnSunday" Value="2"/>
  <Member Name="WeekEndingOnMonday" Value="4"/>
  <Member Name="WeekEndingOnTuesday" Value="8"/>
  <Member Name="WeekEndingOnWednesday" Value="16"/>
  <Member Name="WeekEndingOnThursday" Value="32"/>
  <Member Name="WeekEndingOnFriday" Value="64"/>
  <Member Name="WeekEndingOnSaturday" Value="128"/>
  <Member Name="Month" Value="256"/>
  <Member Name="Quarter" Value="512"/>
  <Member Name="Year" Value="1024"/>
  <Member Name="All" Value="2047"/>
</EnumType>

Étant Microsoft.VisualStudio.Services.Analytics.Model.Period donné qu’il est défini comme énumération avec des indicateurs, utilisez l’opérateur OData has et spécifiez le type complet pour les littéraux de période.

IsLastDayOfPeriod has Microsoft.VisualStudio.Services.Analytics.Model.Period'Month'

Par exemple, la requête suivante retourne un nombre d’éléments de travail qui ont été définis le dernier jour de chaque mois.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemSnapshot?
  $apply=
    filter(IsLastDayOfPeriod has Microsoft.VisualStudio.Services.Analytics.Model.Period'Month')/
    groupby(
      (DateValue), 
      aggregate($count as Count)
    )

✔️ Utiliser la Tags propriété de collection sur les éléments de travail lors du filtrage par balises

Vous pouvez utiliser la TagNames propriété avec la contains fonction pour déterminer si un travail a été marqué avec une balise spécifique. Toutefois, cette approche peut entraîner des requêtes lentes, en particulier lors de la vérification de plusieurs balises en même temps. Pour des performances et des résultats optimaux, utilisez plutôt la Tags propriété de navigation.

Par exemple, la requête suivante obtient tous les éléments de travail marqués avec un {tag}.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq '{tag}')
  &$select=WorkItemId, Title, State

Cette approche fonctionne également très bien lorsque vous devez filtrer sur plusieurs balises. Par exemple, la requête suivante retourne tous les éléments de travail marqués avec {tag1} ou {tag2}

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq {tag1} or t/TagName eq {tag2})
  &$select=WorkItemId, Title, State

Vous pouvez également combiner ces filtres avec un opérateur « et ». Par exemple, la requête suivante obtient tous les éléments de travail marqués avec les deux {tag1} et {tag2}

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq {tag1}) and Tags/any(t:t/TagName eq {tag2})
  &$select=WorkItemId, Title, State

✔️ TagNames Utilisez la propriété si vous souhaitez afficher toutes les étiquettes d’un élément de travail sous forme de texte

La propriété Tagsde navigation, décrite dans la section précédente, est idéale pour le filtrage. Toutefois, l’utilisation de ces derniers présente certains défis à mesure que la requête retourne des balises dans une collection imbriquée. Le modèle de données contient également une TagNames propriété primitive (Edm.String), que nous avons ajoutée pour simplifier les scénarios de consommation de balises. Il s’agit d’une valeur de texte unique qui contient une liste de toutes les balises combinées à un séparateur de points-virgules « ; ». Utilisez cette propriété lorsque vous vous souciez tous d’afficher des balises ensemble. Vous pouvez la combiner avec les filtres de balises décrits précédemment.

Par exemple, la requête suivante obtient tous les éléments de travail marqués avec un {tag}. Elle retourne l’ID de l’élément de travail, le titre, l’état et une représentation textuelle des balises combinées.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq '{tag}')
  &$select=WorkItemId, Title, State, TagNames

Important

La propriété TagNames a une limite de longueur de 1 024 caractères. Il contient un ensemble de balises qui correspondent à cette limite. Si un élément de travail a de nombreuses balises ou si les balises sont très longues, TagNames ne contiennez pas le jeu complet et Tag la propriété de navigation doit être utilisée à la place.

❌ N’utilisez pas et ne utilisez tolower pas de toupper fonctions pour effectuer une comparaison sans respect de la casse

Si vous avez travaillé avec d’autres systèmes, vous pouvez vous attendre à utiliser les fonctions ou toupper les fonctions pour la comparaison qui ne respecte pas la tolower casse. Avec Analytique, toutes les comparaisons de chaînes ne respectent pas la casse par défaut. Vous n’avez donc pas besoin d’appliquer de fonctions pour la gérer explicitement.

Par exemple, la requête suivante obtient tous les éléments de travail étiquetés avec « QUALITÉ », « qualité » ou toute autre combinaison de cas de ce mot.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq 'quality')
  &$select=WorkItemId, Title, State, TagNames

❌ N’utilisez pas l’extension sans limite avec $levels=max

OData a la possibilité de développer tous les niveaux d’une structure hiérarchique. Par exemple, le suivi des éléments de travail comporte certaines entités où une extension sans limite peut être appliquée. Cette opération fonctionne uniquement pour les organisations avec une petite quantité de données. Il ne s’adapte pas bien aux jeux de données plus volumineux. Ne l’utilisez pas du tout si :

  • Vous utilisez des jeux de données volumineux.
  • Vous développez un widget et vous n’avez aucun contrôle sur l’emplacement où le widget est installé.

✔️ Utiliser la pagination pilotée par le serveur

Si vous demandez un ensemble trop volumineux pour être envoyé dans une seule réponse, Analytique applique la pagination. La réponse inclut uniquement un ensemble partiel et un lien qui permet de récupérer le jeu partiel suivant d’éléments. Cette stratégie est décrite dans la spécification OData - OData Version 4.0. Partie 1 : Protocole - Pagination pilotée par le serveur. En permettant au service de contrôler la pagination, vous obtenez les meilleures performances, car la skiptoken conception a été soigneusement adaptée à chaque entité afin qu’elle soit aussi efficace que possible.

Le lien vers la page suivante est inclus dans la @odata.nextLink propriété.

{
  "@odata.context": "https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/$metadata#WorkItems(*)",
  "value": [
    ...
  ],
  "@odata.nextLink":"https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?$skiptoken=12345"}

Remarque

La plupart des clients OData existants peuvent gérer automatiquement la pagination pilotée par le serveur. Par exemple, cette stratégie est déjà utilisée par les outils suivants : Power BI, SQL Server Integration Services et Azure Data Factory.

❌N’utilisez pas et $skip n’utilisez $top pas les options de requête pour implémenter la pagination pilotée par le client

Avec d’autres API REST, vous avez peut-être implémenté la pagination pilotée par le client et $top $skip les options de requête. Ne les utilisez pas avec Analytique. Il existe plusieurs problèmes avec cette approche et les performances sont l’un d’eux. Au lieu de cela, adoptez la stratégie de pagination pilotée par le serveur décrite dans la section précédente.

✔️ Utiliser l’option $top de requête pour limiter le nombre d’enregistrements

L’option $top de requête n’est déconseillée que lorsqu’elle est utilisée avec $skip. Si, dans votre scénario de création de rapports, vous n’avez besoin que d’un sous-ensemble d’enregistrements (par exemple, exemple), il est recommandé d’utiliser l’option $top de requête. En outre, si vous avez besoin de classer les enregistrements selon certains critères, vous devez toujours utiliser $top en combinaison avec $orderby pour obtenir un résultat stable avec les enregistrements classés les plus hauts.

✔️ ENVISAGEZ d’écrire une requête pour retourner un petit nombre d’enregistrements

L’écriture d’une requête pour retourner un petit nombre d’enregistrements est la directive la plus intuitive. Visez toujours à extraire uniquement les données qui vous intéressent vraiment. Pour ce faire, vous pouvez tirer parti des puissantes fonctionnalités de filtrage disponibles dans le langage de requête OData.

✔️ ENVISAGEZ de limiter le nombre de propriétés sélectionnées à un minimum

Certains administrateurs de projet personnalisent fortement leurs processus en ajoutant des champs personnalisés. La personnalisation intensive peut entraîner des problèmes de performances lors de l’extraction de toutes les colonnes disponibles sur des entités larges (par exemple, WorkItems). Analytique repose sur une technologie Columnstore Index . Cela signifie que les données sont à la fois le stockage et le traitement des requêtes est basé sur des colonnes. Par conséquent, plus les propriétés qu’une requête référence, plus il est coûteux de traiter. Visez toujours à limiter l’ensemble des propriétés de vos requêtes à ce que vous avez vraiment à propos de votre scénario de création de rapports.

✔️ ENVISAGEZ de filtrer sur les propriétés de clé de substitution de date (DateSK suffixe)

Il existe de nombreuses façons de définir un filtre de date. Vous pouvez filtrer directement sur la propriété date (par exemple, CreatedDate), son équivalent de navigation (par exemple, CreatedOnDate) ou sa représentation de clé de substitution (par exemple, CreatedDate). La dernière option génère les meilleures performances et est préférée lorsque les exigences de création de rapports l’autorisent.

Par exemple, la requête suivante obtient tous les éléments de travail créés depuis le début de 2020.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDateSK ge 20200101

✔️ ENVISAGEZ de filtrer sur les colonnes clés de substitution

Si vous souhaitez filtrer les données sur la valeur d’un objet associé (par exemple, en filtrant un élément de travail sur le nom du projet), vous avez toujours deux choix. Vous pouvez utiliser la propriété de navigation (par exemple) Project/ProjectNameou capturer la clé de substitution avant et l’utiliser directement dans la requête (par exemple, ProjectSK).

Si vous créez un widget, nous vous recommandons d’utiliser cette dernière option. Lorsque la clé est passée dans le cadre de la requête, le nombre d’ensembles d’entités qui doivent être tactiles est réduit et les performances s’améliorent.

Par exemple, les filtres WorkItems de requête suivants utilisent ProjectSK la propriété plutôt que la propriété de Project/ProjectName navigation.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=ProjectSK eq {projectSK}

❌AVOID using Parent, , or Revisions Childrenproperties in the $filter or $expand clauses

Les éléments de travail sont les entités les plus coûteuses dans l’ensemble du modèle de données. Ils ont plusieurs propriétés de navigation que vous pouvez utiliser pour accéder aux éléments de travail associés : Parent, Children, Revisions. Toutefois, chaque fois que vous les utilisez dans une requête, attendez-vous à une baisse des performances. Demandez toujours si vous avez vraiment besoin de l’une de ces propriétés et éventuellement de mettre à jour votre conception.

Par exemple, au lieu de développer Parent, vous pouvez récupérer davantage d’éléments de travail et utiliser ParentWorkItemId la propriété pour reconstruire le côté client de la hiérarchie complète. Effectuez cette optimisation au cas par cas.

✔️ ENVISAGEZ de transmettre VSTS.Analytics.MaxSize la préférence dans l’en-tête

Lorsque vous exécutez une requête, vous ne connaissez pas le nombre d’enregistrements retournés par la requête. Envoyez une autre requête avec des agrégations ou suivez tous les liens suivants et récupérez l’intégralité du jeu de données. Analytique respecte les VSTS.Analytics.MaxSize préférences, ce qui vous permet d’échouer rapidement dans ces instances que le jeu de données est plus grand que ce que votre client peut accepter.

Cette option est utile dans les scénarios d’exportation de données. Pour l’utiliser, vous devez ajouter Prefer un en-tête à votre requête HTTP et définir VSTS.Analytics.MaxSize sur une valeur non négative. La VSTS.Analytics.MaxSize valeur représente le nombre maximal d’enregistrements que vous pouvez accepter. Si vous définissez la valeur zéro, une valeur par défaut de 200 K est utilisée.

Par exemple, la requête suivante retourne des éléments de travail si le jeu de données est plus petit ou égal à 1 000 enregistrements.

GET https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems HTTP/1.1
User-Agent: {application}
Prefer: VSTS.Analytics.MaxSize=1000
OData-MaxVersion: 4.0
Accept: application/json;odata.metadata=minimal
Host: analytics.dev.azure.com/{OrganizationName}

Si le jeu de données dépasse la limite de 1 000 enregistrements, la requête échoue immédiatement avec l’erreur suivante.

Le résultat de la requête contient 1 296 lignes et dépasse la taille maximale autorisée de 1 000. Réduisez le nombre d’enregistrements en appliquant des filtres supplémentaires

Pour plus d’informations sur la définition de la taille maximale de la page, consultez la propriété ODataPreferenceHeader.MaxPageSize.

Instructions relatives au style de requête

✔️ Utiliser une $count propriété virtuelle dans les méthodes d’agrégation

Certaines entités exposent Count la propriété. Ils facilitent certains scénarios de création de rapports lorsque les données sont exportées vers un autre stockage. Toutefois, vous ne devez pas utiliser ces colonnes dans les agrégations dans les requêtes OData. Utilisez plutôt la $count propriété virtuelle.

Par exemple, la requête suivante retourne le nombre total d’éléments de travail.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $apply=aggregate($count as Count)

❌ ÉVITER d’utiliser $count la propriété virtuelle dans le segment d’URL

Bien que la norme OData vous permet d’utiliser $count la propriété virtuelle pour les jeux d’entités (par exemple, _odata/v1.0/WorkItems/$count), tous les clients ne peuvent pas interpréter correctement la réponse. Il est donc recommandé d’utiliser des agrégations à la place.

Par exemple, la requête suivante retourne le nombre total d’éléments de travail.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $apply=aggregate($count as Count)

✔️ ENVISAGEZ d’utiliser des alias de paramètre pour séparer les parties volatiles de la requête

Les alias de paramètres fournissent une solution élégante pour extraire des parties volatiles telles que des valeurs de paramètres à partir du texte de la requête principale. Vous pouvez les utiliser dans des expressions qui évaluent :

  • Valeur primitive
  • Valeur complexe
  • Collection de valeurs primitives ou complexes.

Pour plus d’informations, consultez OData version 4.0. Partie 2 : Conventions d’URL - Alias de paramètre 5.1.1.13. Les paramètres sont utiles lorsque le texte de requête est utilisé comme modèle qui peut être instancié avec des valeurs fournies par l’utilisateur.

Par exemple, la requête suivante utilise @createdDateSK un paramètre pour séparer la valeur de l’expression de filtre.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDateSK ge @createdDateSK
  &$select=WorkItemId, Title, State
  &@createdDateSK=20200101

❌ ÉVITER le mélange $apply et $filter les clauses dans une seule requête

Si vous souhaitez ajouter filter à votre requête, vous avez deux options. Vous pouvez le faire avec la $filter clause ou la $apply=filter() combinaison. Chacune de ces options fonctionne parfaitement sur elle-même, mais la combinaison de ces options peut entraîner des résultats inattendus.

Malgré l’attente que l’on peut avoir, OData définit clairement un ordre de l’évaluation. En outre, la $apply clause a la priorité sur $filter. Pour cette raison, vous devez choisir l’une ou l’autre, mais éviter ces deux options de filtre dans une seule requête. Il est important que les requêtes soient générées automatiquement.

Par exemple, la requête suivante filtre d’abord les éléments de travail par StoryPoint gt 5, agrège les résultats par chemin d’accès et enfin filtre le résultat par StoryPoints gt 2. Avec cet ordre d’évaluation, la requête retourne toujours un jeu vide.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=StoryPoints gt 2
  $apply=
    filter(StoryPoints gt 5)/
    groupby(
      (Area/AreaPath),
      aggregate(StoryPoints with sum as StoryPoints)
    )

✔️ ENVISAGEZ de structurer votre requête pour qu’elle corresponde à l’ordre d’évaluation OData

Étant donné que le mélange $apply et filter les clauses dans une seule requête peuvent entraîner une confusion potentielle, nous vous recommandons de structurer vos clauses de requête pour qu’elles correspondent à l’ordre d’évaluation.

  1. $apply
  2. $filter
  3. $orderby
  4. $expand
  5. $select
  6. $skip
  7. $top

✔️ ENVISAGEZ d’examiner les fonctionnalités OData décrites dans les annotations de métadonnées

Lorsque vous ne savez pas quelles fonctionnalités OData Analytique prend en charge, vous pouvez rechercher des annotations dans les métadonnées. Le comité technique OASIS Open Data Protocol (OData) dans un dépôt GitHub TC gère une liste d’annotations disponibles.

Par exemple, la liste des fonctions de filtre prises en charge est disponible dans Org.OData.Capabilities.V1.FilterFunctions l’annotation sur le conteneur d’entités.

<Annotation Term="Org.OData.Capabilities.V1.FilterFunctions">
  <Collection>
  <String>contains</String>
  <String>endswith</String>
  [...]
  </Collection>
</Annotation>

Une autre annotation utile est Org.OData.Capabilities.V1.ExpandRestrictions, qui explique les propriétés de navigation que vous ne pouvez pas utiliser dans la $expand clause. Par exemple, l’annotation suivante explique que Revisions dans l’ensemble WorkItems d’entités ne peut pas être développé.

<EntitySet Name="WorkItems" EntityType="Microsoft.VisualStudio.Services.Analytics.Model.WorkItem">
  [...]
  <Annotation Term="Org.OData.Capabilities.V1.ExpandRestrictions">
    <Record>
      <PropertyValue Property="Expandable" Bool="true"/>
      <PropertyValue Property="NonExpandableProperties">
        <Collection>
          <NavigationPropertyPath>Revisions</NavigationPropertyPath>
        </Collection>
      </PropertyValue>
    </Record>
  </Annotation>
</EntitySet>