Diretrizes de consulta do OData Analytics para o Azure DevOps

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

Os desenvolvedores de extensão podem se beneficiar seguindo as diretrizes fornecidas neste artigo para criar consultas OData eficientes no Analytics para Azure DevOps. Seguir essas diretrizes ajuda a garantir que as consultas tenham um bom desempenho para o tempo de execução e o consumo de recursos. As consultas que não seguem essas diretrizes podem resultar em baixo desempenho, com longos tempos de espera de relatório, consultas que excedem o consumo de recursos permitido ou bloqueios de serviço.

Observação

O serviço de Análise é habilitado automaticamente e tem suporte na produção para todos Azure DevOps Services. A integração do Power BI e o acesso ao feed OData do Serviço de Análise estão em disponibilidade geral. Encorajamos você a usá-lo e nos dar feedback. Os dados disponíveis dependem da versão. A versão mais recente com suporte é v2.0, e a versão de visualização mais recente é v4.0-preview. Para obter mais informações, consulte Controle de versão da API OData.

Observação

O serviço de Análise é instalado automaticamente e tem suporte na produção para todas as novas coleções de projetos para Azure DevOps Server 2020 e versões posteriores. A integração do Power BI e o acesso ao feed OData do Serviço de Análise estão em disponibilidade geral. Encorajamos você a usá-lo e nos dar feedback. Se você atualizou de Azure DevOps Server 2019, poderá instalar o serviço de Análise durante a atualização.

Os dados disponíveis dependem da versão. A versão mais recente com suporte é v2.0, e a versão de visualização mais recente é v4.0-preview. Para obter mais informações, consulte Controle de versão da API OData.

Observação

O serviço de Análise está em versão prévia para Azure DevOps Server 2019. Você pode habilitá-lo ou instalá-lo para uma coleção de projetos. A integração do Power BI e o acesso ao feed OData do Serviço de Análise estão em versão prévia. Encorajamos você a usá-lo e nos dar feedback.

Os dados disponíveis dependem da versão. A versão mais recente com suporte é v2.0, e a versão de visualização mais recente é v4.0-preview. Para obter mais informações, consulte Controle de versão da API OData.

Essas diretrizes são nossas recomendações prefixadas com os termos DO, CONSIDER, AVOID e DON't. As regras restritivas aplicadas pelo Google Analytics contêm o prefixo [BLOCKED]. Você deve entender as compensações entre diferentes soluções. Em determinadas circunstâncias, você pode ter requisitos de dados que o forçam a violar uma ou mais diretrizes. Tais casos devem ser raros. Recomendamos que você tenha uma razão clara e convincente para tais decisões.

Dica

Os exemplos mostrados neste documento são baseados em uma URL do Azure DevOps Services. Use substituições para versões locais.

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

Mensagens de erro e de aviso

✔️ Examine os avisos de resposta do OData

Cada consulta executada é verificada em relação a um conjunto de regras predefinidas. As violações retornam a resposta OData após @vsts.warnings. Revise esses avisos, pois eles fornecem informações atuais e contextuais sobre como melhorar sua consulta.

{
  "@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."
  ],
  ...
}

✔️ Examine as mensagens de erro do OData

As consultas que violam uma regra de erro OData resultam em uma resposta com falha com um código de status 400 (Solicitação Incorreta). As mensagens associadas não aparecem na @vsts.warnings propriedade. Em vez disso, eles geram uma mensagem de erro na message propriedade na resposta 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."
  }
}

Restrições

Fazer

Considerações

Bloqueado

Evite

✔️ Limite a consulta ao(s) projeto(s) ao qual você tem acesso

Se sua consulta for direcionada a dados de um projeto ao qual você não tem acesso, ela retornará uma mensagem "Acesso negado ao projeto". Para garantir que você tenha acesso, verifique se a permissão Exibir análise está definida como Permitir para todos os projetos consultados. Para obter mais informações, consulte Permissões necessárias para acessar o Analytics.

Se você não tiver acesso a um projeto, a seguinte mensagem será exibida:

Os resultados da consulta incluem dados em um ou mais projetos para os quais você não tem acesso. Adicione um ou mais filtros de projetos para especificar os projetos aos quais você tem acesso na entidade 'WorkItems'. Se você estiver usando propriedades de $expand ou navegação, o filtro de projeto será necessário para essas entidades.

Para contornar esse problema, você pode adicionar explicitamente um filtro de projeto ou usar o ponto de extremidade no escopo do projeto, conforme explicado posteriormente neste artigo.

Por exemplo, a consulta a seguir busca itens de trabalho que pertencem a projetos chamados {projectSK1} e {projectSK2}.

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

✔️ Especifique o filtro de projeto dentro da $expand cláusula se sua expansão puder incluir dados em outros projetos potencialmente inacessíveis

Quando você expande as propriedades de navegação, há uma chance de acabar fazendo referência a dados de outros projetos inacessíveis. Se você fizer referência a dados inacessíveis, receberá a mesma mensagem de erro listada anteriormente: "Os resultados da consulta incluem dados em um ou mais projetos...". Da mesma forma, você pode resolver esse problema adicionando filtros de projeto explícitos para controlar os dados expandidos.

Você pode fazer isso na cláusula regular $filter para propriedades de navegação simples. Por exemplo, a consulta a seguir pergunta WorkItemLinks explicitamente onde o link e seu destino existem no mesmo projeto.

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)

Em vez disso, você pode mover o filtro para $filter expandir a $expand opção na cláusula. No entanto, ele altera a semântica da consulta. Por exemplo, a consulta a seguir obtém todos os links de um determinado projeto e expande condicionalmente o destino somente se ele existir no mesmo projeto. Embora válida, essa abordagem pode causar confusão, pois pode ser difícil determinar se uma propriedade não é expandida porque é null ou porque foi filtrada. Use essa solução somente se você realmente precisar desse comportamento específico.

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)

A $filter opção de expansão é útil quando você usa a propriedade de coleção de expansão, como Children no WorkItems conjunto de entidades. Por exemplo, a consulta a seguir retorna todos os itens de trabalho de um determinado projeto junto com todos os seus filhos que pertencem ao mesmo projeto.

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)

Especifique o filtro se você expandir uma das seguintes propriedades:

  • WorkItems conjunto de entidades: Parent, Children
  • WorkItemLinks conjunto de entidades: TargetWorkItem.

✔️ CONSIDERE consultar usando o ponto de extremidade no escopo do projeto

Se você estiver interessado em dados de um único projeto, recomendamos que você use o ponto de extremidade OData no escopo do projeto (/{ProjectName}/_odata/v1.0). Ele evita os problemas descritos nas duas seções anteriores e filtra implicitamente os dados para um projeto, o conjunto de entidades referenciado e todas as propriedades de navegação expandidas.

Com essa simplificação, as consultas da seção anterior podem ser reescritas para o seguinte formato. Não apenas o filtro na cláusula expand desapareceu, mas também não há necessidade do filtro no conjunto de entidades principal.

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

A consulta de filhos de item de trabalho também é muito mais curta e simples.

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

Você pode aplicar essa solução somente quando seu foco são os dados de um único projeto. Para relatórios entre projetos, você precisa usar as estratégias de filtragem descritas nas seções anteriores.

✔️ Aguarde ou interrompa a operação se sua consulta exceder os limites de uso

Se você executar muitas consultas ou se as consultas exigirem muitos recursos para serem executadas, você poderá exceder os limites de serviço e ser bloqueado temporariamente. Se você exceder os limites de serviço, interrompa sua operação, pois é provável que a próxima consulta enviada falhe com a mesma mensagem de erro.

A solicitação foi bloqueada devido ao uso excessivo do recurso '{resource}' no namespace '{namespace}'.

Para obter mais informações sobre limitação de taxa, consulte Limites de taxa. Para saber como criar consultas OData eficientes, consulte as Diretrizes de Desempenho mais adiante neste artigo.

✔️ Aguarde ou interrompa a operação se a consulta falhar com um tempo limite

Semelhante a exceder os limites de uso, você deve aguardar ou interromper a operação se sua consulta encontrar um tempo limite. Isso pode sinalizar um problema transitório, portanto, você pode tentar novamente uma vez para ver se o problema é resolvido. No entanto, os tempos limite persistentes indicam que a consulta provavelmente é muito cara para ser executada. Outras tentativas resultam apenas em exceder os limites de uso e você é bloqueado.

TF400733: A solicitação foi cancelada: A solicitação excedeu o tempo limite da solicitação, tente novamente.

Os tempos limite indicam que uma consulta requer otimização. Para saber como criar consultas OData eficientes, consulte Diretrizes de desempenho mais adiante neste artigo.

❌ [BLOQUEADO] NÃO use entidades de snapshot para nada além de agregações

Os conjuntos de entidades de instantâneo com o Snapshot sufixo são especiais porque são modelados como instantâneos diários. Você pode usá-los para obter um estado de entidades como eram no final de cada dia no passado. Por exemplo, se você consultasse e filtrasse WorkItemSnapshot para um único WorkItemId, obteria um registro para cada dia desde que o item de trabalho foi criado. Carregar diretamente todos esses dados seria caro e provavelmente excederia os limites de uso e seria bloqueado. No entanto, agregações nessas entidades são permitidas e recomendadas. Na verdade, os conjuntos de entidades de instantâneo foram projetados com cenários de agregação em mente.

Por exemplo, a consulta a seguir obtém o número de itens de trabalho como por data para observar como ele cresceu em janeiro de 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))

Para obter mais informações sobre agregações, consulte Agregar dados.

✔️ INCLUA DateSK ou DateValue coluna na groupby cláusula quando você agrega tabelas de instantâneo

Como todas as entidades de instantâneo são modeladas como tabelas de instantâneo diário, você deve sempre incluir uma das propriedades do dia (DateSK ou DateValue) na cláusula de agrupamento. Caso contrário, o resultado pode aparecer inflado incorretamente.

Por exemplo, se você agrupasse WorkItemSnapshot apenas por AssignedTo propriedade e a agregasse com a contagem, todos os números de itens de trabalho atribuídos a pessoas seriam multiplicados pelo número de dias em que cada atribuição estava ativa. Embora você possa ter uma situação em que é o resultado desejado, esses casos são raros.

❌ [BLOQUEADO] NÃO use chaves de entidade em caminhos de recursos para endereçamento de entidade

A sintaxe OData fornece uma maneira de acessar uma entidade específica incluindo suas chaves diretamente nos segmentos de URL. Para obter mais informações, consulte OData versão 4.0. Parte 2: Convenções de URL - 4.3 Entidades de endereçamento. Embora o OData permita esse endereçamento, o Analytics o bloqueia. A inclusão em uma consulta resulta no erro a seguir.

A consulta especificada no URI não é válida. O Analytics não é compatível com a navegação de chave ou propriedade, como WorkItems(Id) ou WorkItem(Id)/AssignedTo. Se você receber esse erro no PowerBI, reescreva sua consulta para evitar dobras incorretas que causam problemas de N + 1.

Como as mensagens de erro sugerem, certas ferramentas de cliente podem abusar do endereçamento direto de entidades. Em vez de carregar todos os dados em uma única solicitação, esses clientes podem optar por consultar cada entidade de forma independente. Essa prática é desencorajada, pois pode resultar em um grande número de solicitações. Em vez disso, recomendamos que você use o endereçamento de entidade explícito, conforme explicado na seção a seguir.

✔️ DO endereça explicitamente entidades com cláusulas de filtro

Se você quiser buscar dados para uma única entidade, deverá usar a mesma abordagem de uma coleção de entidades e definir explicitamente os filtros na $filter cláusula.

Por exemplo, a consulta a seguir obtém um único item de trabalho por seu identificador.

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

Se você não tiver certeza de quais propriedades deve incluir nesse filtro, poderá procurá-lo nos metadados. Consulte Construir consultas OData para Analytics, componentes de URL para consultar os metadados. As propriedades estão no Key elemento do EntityType. Por exemplo, WorkItemId e Revision são colunas de chave para a WorkItemRevision entidade.

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

❌ [BLOQUEADO] NÃO expanda Revisions a WorkItem entidade

O modelo de dados do Analytics não permite determinados tipos de expansões. Um deles, que pode ser surpreendente para alguns, é a propriedade de Revisions coleção na WorkItem entidade. Se você tentar expandir essa propriedade, receberá a seguinte mensagem de erro.

A consulta especificada no URI não é válida. A propriedade 'Revisões' não pode ser usada na opção de consulta $expand.

Essa restrição foi implementada WorkItemRevisions para incentivar todos a usar a solução recomendada, que é buscar revisões, conforme explicado na seção a seguir.

✔️ Use WorkItemRevisions o conjunto de entidades para carregar todas as revisões de um determinado item de trabalho

Use WorkItemRevisions sempre que quiser buscar o histórico completo de um item de trabalho ou de uma coleção de itens de trabalho.

Por exemplo, a consulta a seguir retorna todas as revisões de um item de trabalho com o {id} identificador.

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

Se você se preocupa com o histórico completo de todos os itens de trabalho que correspondem a determinados critérios, expresse-o WorkItem usando um filtro na propriedade de navegação. Por exemplo, a consulta a seguir obtém todas as revisões de todos os itens de trabalho ativos no momento.

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

❌ [BLOQUEADO] NÃO agrupe em colunas distintas

Você usa uma operação de agrupamento para reduzir o número de registros. O uso de colunas distintas na groupby cláusula indica um problema e a consulta falha imediatamente. Se você acidentalmente se deparar com essa situação, receberá a seguinte mensagem de erro.

Uma ou mais das colunas especificadas na cláusula groupby desta consulta não são recomendadas.

Para resolver esse problema, remova a coluna distinta da groupby cláusula.

❌ [BLOQUEADO] NÃO use countdistinct agregação

O Analytics não dá suporte à função, embora o countdistinct OData o faça. Embora planejemos adicionar suporte no futuro, ele não está disponível no momento. Uma consulta que contém essa função retorna a seguinte mensagem de erro.

Não há suporte para consultas que aplicam uma contagem distinta com uma agregação.

❌ EVITE agregações que podem resultar em estouro aritmético

Em casos raros, uma consulta de agregação pode ter problemas com estouro aritmético. Por exemplo, isso pode acontecer quando você soma algumas propriedades numéricas que não se destinam à soma, como StackRank nas entidades de item de trabalho. Como o padrão OData Extension for Data Aggregation não fornece uma maneira de converter uma propriedade em um tipo diferente, a única maneira de resolver esse problema é remover a propriedade problemática da agregação.

✔️ Use o ponto de extremidade em lote para consultas longas

Você pode ter problemas com consultas longas. Particularmente, podem ocorrer problemas quando:

  • Você consulta um projeto com muitos campos personalizados.
  • Sua consulta é construída programaticamente.

O limite atual de consultas OData enviadas é de HTTP GET 3.000 caracteres. Se você excedê-lo, receberá uma resposta "404 Não encontrado".

HTTP/1.1 404 Not Found
Content-Length: 0

Para resolver esse problema, use o ponto de extremidade em lote OData, conforme explicado na especificação, OData versão 4.0. Parte 1: Protocolo - 11.7 Solicitações em lote. A funcionalidade do Lote foi projetada principalmente para agrupar várias operações em uma única HTTP carga de solicitação, mas você também pode usá-la como uma solução alternativa para a limitação de comprimento da consulta. Ao enviar uma HTTP POST solicitação, você pode passar uma consulta de comprimento arbitrário e o serviço a interpreta corretamente.

❌ [BLOQUEADO] NÃO use o ponto de extremidade em lote para enviar várias consultas

Restringimos o uso do ponto de extremidade do lote de lidar com um lote de várias solicitações. Uma única solicitação ainda pode ter apenas uma consulta. Se você tentar enviar um lote de várias consultas, a operação falhará com a seguinte mensagem de erro. A única solução é dividir as consultas em várias solicitações.

O Analytics não dá suporte ao processamento de várias operações que a mensagem em lote atual contém. O Analytics usa o lote OData para dar suporte a solicitações POST, mas requer que você limite a operação a uma única solicitação.

❌ [BLOQUEADO] NÃO use consultas que resultem em mais de 800 colunas

Restringimos consultas que resultam em mais de 800 colunas. Se você não for seletivo o suficiente em quais colunas sua consulta retorna, poderá receber a seguinte mensagem de erro.

VS403670: A consulta especificada retorna 'N' colunas que são maiores que o limite permitido de 800 colunas. Por favor, use opções explícitas de $select (inclusive dentro do $expand) para limitar o número de colunas.

Adicione uma cláusula $select à sua consulta e às operações $expand em sua consulta para evitar exceder esse limite.

❌ EVITE criar consultas longas

Recomendamos que você avalie sua abordagem sempre que construir uma consulta longa. Embora existam muitos cenários que precisam de uma consulta longa (por exemplo, filtros complexos ou uma longa lista de propriedades), normalmente eles fornecem um indicador inicial de um design abaixo do ideal.

Quando sua consulta contém muitas chaves de entidade na consulta (por exemplo, WorkItemId eq {id 1} or WorkItemId eq {id 2} or ...), você provavelmente pode reescrevê-la. Em vez de passar os identificadores, tente definir alguns outros critérios que selecionem o mesmo conjunto de entidades. Às vezes, pode ser necessário modificar seu processo (por exemplo, adicionar um novo campo ou tag), mas normalmente vale a pena. As consultas que usam filtros mais abstratos são mais fáceis de manter e têm maior potencial para funcionar melhor.

Outro cenário que tende a gerar consultas longas ocorre quando você inclui muitas datas individuais (por exemplo, DateSK eq {dateSK 1} or DateSK eq {dateSK 2} or ...). Procure outro padrão que você possa usar para criar um filtro mais abstrato. Por exemplo, a consulta a seguir retorna todos os itens de trabalho que foram criados na segunda-feira.

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

✔️ Especifique o fuso horário ao filtrar colunas de data

O fuso horário (Edm.DateTimeOffset) expõe todas as informações de data e hora com um deslocamento que corresponde às configurações de fuso horário da organização. Esses dados são precisos e simples de interpretar ao mesmo tempo. Outra consequência não óbvia é que todos os filtros também precisam passar as informações de fuso horário. Se você ignorá-lo, receberá a seguinte mensagem de erro.

A consulta especificada no URI não é válida. Nenhum deslocamento de data e hora foi especificado. Use um desses formatos AAAA-MM-ddZ para especificar tudo desde meia-noite ou aaaa-MM-ddThh:mm-hh:mm (representação padrão ISO 8601 de datas e horas) para especificar o deslocamento.

Para resolver esse problema, adicione as informações de fuso horário. Por exemplo, supondo que a organização esteja configurada para exibir dados no fuso horário "(UTC-08:00) Horário do Pacífico (EUA e Canadá)", a consulta a seguir obtém todos os itens de trabalho criados desde o início 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

A mesma solução funciona para fusos horários com deslocamentos positivos, no entanto, o caractere de adição (+) tem um significado especial no URI e você deve tratá-lo corretamente. Se você especificar 2020-01-01T00:00:00+08:00 (com um + caractere) como ponto de partida, receberá o seguinte erro.

A consulta especificada no URI não é válida. Erro de sintaxe na posição 31 em 'CreatedDate ge 2020-01-01T0000 08:00'.

Para resolvê-lo, substitua o + caractere por sua versão codificada, %2B. Por exemplo, supondo que a organização esteja configurada para exibir dados no fuso horário "(UTC+08:00) Pequim, Chongqing, Hong Kong, Urumqi", a consulta a seguir retorna todos os itens de trabalho criados desde o início 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

Uma abordagem alternativa é usar propriedades de chave substitutas de data, pois elas não mantêm as informações de fuso horário. Por exemplo, a consulta a seguir retorna todos os itens de trabalho criados desde o início de 2020, independentemente das configurações da organização.

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

Diretrizes de desempenho

Fazer

O que não fazer

Considerações

Evite

✔️ Meça o efeito da implementação de uma diretriz de desempenho

Assim como acontece com qualquer recomendação de desempenho, você não deve implementá-las cegamente. Em vez disso, sempre capture a linha de base e meça o efeito das alterações feitas. Todas as diretrizes foram criadas com base nas interações com clientes do Analytics que tinham requisitos e desafios específicos. Essas recomendações foram consideradas gerais e potencialmente úteis para qualquer pessoa que crie consultas semelhantes. No entanto, em casos raros, seguir as diretrizes pode não ter efeito ou até mesmo um efeito negativo no desempenho. Você precisa medir a diferença para notá-la. Caso isso aconteça, forneça comentários no portal da Comunidade de Desenvolvedores.

Existem muitas opções para medir o desempenho. A mais simples é executar duas versões da mesma consulta diretamente no navegador. Observe o tempo que leva nas ferramentas do desenvolvedor. Por exemplo, você pode usar o painel Rede nas Ferramentas de Desenvolvedor F12 do Microsoft Edge). Outra opção é capturar essas informações usando a Ferramenta de Depuração da Web do Fiddler.

Seja qual for sua abordagem, execute as duas consultas várias vezes. Por exemplo, execute as consultas 30 vezes cada para ter um conjunto de amostras suficientemente grande. Em seguida, descubra as características de desempenho. A análise segue a arquitetura multilocatário. Portanto, outras operações que ocorrem ao mesmo tempo podem afetar a duração de suas consultas.

✔️ Use extensões de agregação

De longe, a melhor coisa que você pode fazer para melhorar o desempenho de suas consultas é usar a extensão de agregação - Extensão OData para Agregação de Dados. Com a extensão de agregação, peça ao serviço para resumir os dados do lado do servidor e retornar uma resposta menor do que a que você pode buscar aplicando a mesma função do lado do cliente. Por fim, o Analytics é otimizado para esse tipo de consulta, portanto, faça uso dele.

Para obter mais informações, consulte Agregar dados.

✔️ Especifique colunas na $select cláusula

Especifique as colunas importantes para você $select na cláusula. A análise é criada com base em uma tecnologia Columnstore Index . Isso significa que os dados são armazenados e o processamento de consultas é baseado em colunas. Ao reduzir o conjunto de propriedades, você faz referência na $select cláusula e pode reduzir o número de colunas que precisam ser verificadas e melhorar o desempenho geral da consulta.

Por exemplo, a consulta a seguir especifica as colunas para itens de trabalho.

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

Observação

O Azure DevOps dá suporte à personalização do processo. Alguns administradores usam esse recurso e criam centenas de campos personalizados. Se você omitir a $select cláusula, sua consulta retornará todos os campos, incluindo campos personalizados.

✔️ Especifique colunas na $select opção expand dentro da $expand cláusula

Da mesma forma que as diretrizes da $select cláusula, especifique as propriedades na $select opção expand dentro da $expand cláusula. É fácil esquecer, mas se você omiti-lo, sua resposta conterá todas as propriedades do objeto expandido.

Por exemplo, a consulta a seguir especifica as colunas para o item de trabalho e seu pai.

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

✔️ Defina um filtro ao RevisedDateSK consultar dados históricos de itens de trabalho (WorkItemRevisions WorkItemSnapshot ou conjuntos de entidades)

Quando você consulta dados históricos, é provável que você esteja interessado no período mais recente (por exemplo, 30 dias, 90 dias). Devido à forma como as entidades de itens de trabalho são implementadas, há uma maneira conveniente de escrever essas consultas para obter um ótimo desempenho. Cada vez que você atualiza um item de trabalho, ele cria uma nova revisão e registra essa ação no campo, o System.RevisedDate que o torna perfeito para filtros de histórico.

No Google Analytics, a data revisada é mostrada RevisedDate nas propriedades (Edm.DateTimeOffset) e RevisedDateSK (Edm.Int32). Para obter o melhor desempenho, use o último. É a chave substituta de data e representa a data em que uma revisão foi criada ou tem null para revisões ativas e incompletas. Se você quiser todas as datas desde a {startDate} inclusão, adicione o filtro a seguir à consulta.

RevisedDateSK eq null or RevisedDateSK gt {startDateSK}

Por exemplo, a consulta a seguir retorna o número de itens de trabalho para cada dia desde o início de 2020. Observe que, além do filtro óbvio na DateSK coluna, há um segundo filtro em RevisedDateSK. Embora possa parecer redundante, ele ajuda o mecanismo de consulta a filtrar revisões que não estão no escopo e melhora significativamente o desempenho da consulta.

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)
    )

Observação

Criamos essa recomendação quando estávamos trabalhando em widgets de burndown. Inicialmente, definimos filtros apenas para DateSK , mas não conseguimos fazer com que essa consulta fosse bem dimensionada para organizações com grandes conjuntos de dados. Durante a criação de perfil de consulta, notamos que DateSK isso não filtra bem as revisões. Somente depois de adicionarmos um filtro RevisedDateSK conseguimos obter um ótimo desempenho em escala.
~ Equipe de produto

✔️ Use instantâneos semanais ou mensais para consultas de tendência que abrangem um longo período de tempo

Por padrão, todas as tabelas de instantâneo são modeladas como tabelas de fatos de instantâneo diário. Se você consultar um intervalo de tempo, ele obterá um valor para cada dia. Intervalos de tempo longos resultam em um grande número de registros. Se você não precisar de uma precisão tão alta, poderá usar instantâneos semanais ou até mesmo mensais.

Você pode fazer isso com outras expressões de filtro para remover dias que não terminam uma determinada semana ou mês. Use a IsLastDayOfPeriod propriedade, que foi adicionada ao Analytics com esse cenário em mente. Essa propriedade é do tipo Microsoft.VisualStudio.Services.Analytics.Model.Period e pode determinar se um dia termina em períodos diferentes (por exemplo, semanas, meses e assim por diante).

<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>

Como Microsoft.VisualStudio.Services.Analytics.Model.Period é definido como uma enumeração com sinalizadores, use o operador OData has e especifique o tipo completo para os literais de período.

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

Por exemplo, a consulta a seguir retorna uma contagem de itens de trabalho que foram definidos no último dia de cada mês.

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)
    )

✔️ USE Tags a propriedade de coleção em itens de trabalho ao filtrar por marcas

Você pode usar a TagNames propriedade com a contains função para determinar se um trabalho foi marcado com uma marca específica. Essa abordagem, no entanto, pode resultar em consultas lentas, especialmente ao verificar várias marcas ao mesmo tempo. Para obter melhor desempenho e resultados, use a Tags propriedade navigation.

Por exemplo, a consulta a seguir obtém todos os itens de trabalho que foram marcados com um {tag}.

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

Essa abordagem também funciona muito bem quando você precisa filtrar várias tags. Por exemplo, a consulta a seguir retorna todos os itens de trabalho que foram marcados com {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

Você também pode combinar esses filtros com um operador "e". Por exemplo, a consulta a seguir obtém todos os itens de trabalho que foram marcados com e {tag1} {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

✔️ Use TagNames a propriedade se quiser exibir todas as marcas em um item de trabalho como texto

A propriedade Tagsde navegação, descrita na seção anterior, é ótima para filtragem. No entanto, trabalhar com eles apresenta alguns desafios, pois a consulta retorna marcas em uma coleção aninhada. O modelo de dados também contém uma TagNames propriedade primitiva (Edm.String), que adicionamos para simplificar os cenários de consumo de marcas. É um único valor de texto que contém uma lista de todas as tags combinadas com um separador de ponto e vírgula "; ". Use essa propriedade quando tudo o que você se importa é exibir marcas juntas. Você pode combiná-lo com os filtros de tags descritos anteriormente.

Por exemplo, a consulta a seguir obtém todos os itens de trabalho que foram marcados com um {tag}. Ele retorna a ID do item de trabalho, o título, o estado e uma representação de texto de marcas combinadas.

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

Importante

A propriedade TagNames tem um limite de comprimento de 1024 caracteres. Ele contém um conjunto de tags que se encaixam dentro desse limite. Se um item de trabalho tiver muitas marcas ou as marcas forem muito longas, TagNames não contenha o conjunto completo e Tag a propriedade de navegação deverá ser usada.

❌ NÃO use tolower e toupper funções para fazer comparação sem distinção entre maiúsculas e minúsculas

Se você já trabalhou com outros sistemas, talvez espere usar as tolower funções or toupper para a comparação que não diferencia maiúsculas de minúsculas. Com o Analytics, todas as comparações de cadeia de caracteres não diferenciam maiúsculas de minúsculas por padrão, portanto, você não precisa aplicar nenhuma função para tratá-las explicitamente.

Por exemplo, a consulta a seguir obtém todos os itens de trabalho marcados com "QUALITY", "quality" ou qualquer outra combinação de maiúsculas e minúsculas dessa palavra.

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

❌ NÃO use expansão ilimitada com $levels=max

O OData tem a capacidade de expandir todos os níveis de uma estrutura hierárquica. Por exemplo, o acompanhamento de item de trabalho tem algumas entidades em que uma expansão não associada pode ser aplicada. Essa operação funciona apenas para organizações com uma pequena quantidade de dados. Ele não é bem dimensionado para conjuntos de dados maiores. Não o use se:

  • Você está trabalhando com grandes conjuntos de dados.
  • Você está desenvolvendo um widget e não tem controle sobre onde o widget é instalado.

✔️ USE paginação controlada por servidor

Se você solicitar um conjunto muito grande para ser enviado em uma única resposta, o Google Analytics aplicará a paginação. A resposta inclui apenas um conjunto parcial e um link que permite recuperar o próximo conjunto parcial de itens. Essa estratégia é descrita na especificação OData – OData versão 4.0. Parte 1: Protocolo - Paginação controlada por servidor. Ao permitir que o serviço controle a paginação, você obtém o melhor desempenho, pois foi skiptoken cuidadosamente projetado para que cada entidade seja o mais eficiente possível.

O link para a próxima página está incluído na @odata.nextLink propriedade.

{
  "@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"}

Observação

A maioria dos clientes OData existentes pode lidar com a paginação controlada pelo servidor automaticamente. Por exemplo, essa estratégia já é usada pelas seguintes ferramentas: Power BI, SQL Server Integration Services e Azure Data Factory.

❌ NÃO use $top e $skip consulte opções para implementar a paginação controlada pelo cliente

Com outras APIs REST, você pode ter implementado a paginação controlada pelo cliente com $top opções de consulta e $skip . Não os use com o Google Analytics. Existem vários problemas com essa abordagem e o desempenho é um deles. Em vez disso, adote a estratégia de paginação controlada por servidor descrita na seção anterior.

✔️ Use $top a opção de consulta para limitar o número de registros

A opção $top de consulta só é desencorajada quando usada em conjunto com $skip. Se, em seu cenário de relatório, você precisar apenas de um subconjunto de registros (por exemplo, amostra), não há problema em usar $top a opção de consulta. Além disso, se você precisar classificar os registros de acordo com alguns critérios, você deve sempre usar $top em combinação com $orderby para obter um resultado estável com os registros mais bem classificados.

✔️ CONSIDERE escrever uma consulta para retornar um pequeno número de registros

Escrever uma consulta para retornar um pequeno número de registros é a diretriz mais intuitiva. Sempre procure buscar apenas os dados com os quais você realmente se importa. Você pode conseguir isso disponibilizando a maioria dos recursos avançados de filtragem na linguagem de consulta OData.

✔️ CONSIDERE limitar o número de propriedades selecionadas ao mínimo

Alguns administradores de projeto personalizam fortemente seus processos adicionando campos personalizados. A personalização pesada pode levar a problemas de desempenho ao buscar todas as colunas disponíveis em entidades largas (por exemplo, WorkItems). A análise é criada com base em uma tecnologia Columnstore Index . Isso significa que os dados são armazenados e o processamento de consultas é baseado em colunas. Portanto, quanto mais propriedades uma consulta referenciar, mais caro será processá-la. Sempre procure limitar o conjunto de propriedades em suas consultas ao que realmente importa para você em seu cenário de relatórios.

✔️ CONSIDERE filtrar por propriedades de chave substituta de data (DateSK sufixo)

Há muitas maneiras de definir um filtro de data. Você pode filtrar a propriedade de data diretamente (por exemplo, CreatedDate), sua contraparte de navegação (por exemplo, CreatedOnDate) ou sua representação de chave substituta (por exemplo, CreatedDate). A última opção produz o melhor desempenho e é preferida quando os requisitos de relatório o permitem.

Por exemplo, a consulta a seguir obtém todos os itens de trabalho criados desde o início de 2020.

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

✔️ CONSIDERE a filtragem em colunas de chave substitutas

Se você quiser filtrar os dados no valor de um objeto relacionado (por exemplo, filtrar um item de trabalho no nome do projeto), sempre terá duas opções. Você pode usar a propriedade de navegação (por exemplo, Project/ProjectName) ou capturar a chave substituta antecipadamente e usá-la diretamente na consulta (por exemplo, ProjectSK).

Se você estiver criando um widget, recomendamos que use a última opção. Quando a chave é passada como parte da consulta, o número de conjuntos de entidades que precisam ser tocados é reduzido e o desempenho melhora.

Por exemplo, a consulta a seguir filtra WorkItems usando ProjectSK propriedade em vez de propriedade de Project/ProjectName navegação.

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

❌EVITE usar ParentChildren, , Revisions ou propriedades nas $filter cláusulas or $expand

Os itens de trabalho são as entidades mais caras em todo o modelo de dados. Eles têm várias propriedades de navegação que você pode usar para acessar itens de trabalho relacionados: Parent, Children, Revisions. No entanto, sempre que você usá-los em uma consulta, espere um declínio no desempenho. Sempre questione se você realmente precisa de uma dessas propriedades e potencialmente atualize seu design.

Por exemplo, em vez de expandir Parent, você pode buscar mais itens de trabalho e usar ParentWorkItemId a propriedade para reconstruir a hierarquia completa do lado do cliente. Realize essa otimização caso a caso.

✔️ CONSIDERE a preferência de passagem VSTS.Analytics.MaxSize no cabeçalho

Ao executar uma consulta, você não sabe o número de registros que a consulta retorna. Envie outra consulta com agregações ou siga todos os próximos links e busque todo o conjunto de dados. O Analytics respeita a VSTS.Analytics.MaxSize preferência, o que permite que você falhe rapidamente nos casos em que o conjunto de dados é maior do que o que seu cliente pode aceitar.

Essa opção é útil em cenários de exportação de dados. Para usá-lo, você deve adicionar Prefer um cabeçalho à sua solicitação HTTP e definir VSTS.Analytics.MaxSize um valor não negativo. O VSTS.Analytics.MaxSize valor representa o número máximo de registros que você pode aceitar. Se você defini-lo como zero, um valor padrão de 200 K será usado.

Por exemplo, a consulta a seguir retornará itens de trabalho se o conjunto de dados for menor ou igual a 1000 registros.

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}

Se o conjunto de dados exceder o limite de 1000 registros, a consulta falhará imediatamente com o erro a seguir.

O resultado da consulta contém 1.296 linhas e excede o tamanho máximo permitido de 1000. Reduza o número de registros aplicando filtros adicionais

Para obter informações sobre como definir o tamanho máximo da página, consulte a propriedade ODataPreferenceHeader.MaxPageSize.

Diretrizes de estilo de consulta

✔️ Use $count a propriedade virtual nos métodos de agregação

Algumas entidades expõem Count propriedade. Eles facilitam alguns cenários de relatórios quando os dados são exportados para um armazenamento diferente. No entanto, você não deve usar essas colunas em agregações em consultas OData. Em vez disso, use a $count propriedade virtual.

Por exemplo, a consulta a seguir retorna o número total de itens de trabalho.

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

❌ EVITE usar $count propriedade virtual no segmento de URL

Embora o padrão OData permita que você use $count a propriedade virtual para conjuntos de entidades (por exemplo, _odata/v1.0/WorkItems/$count), nem todos os clientes podem interpretar a resposta corretamente. Portanto, é recomendável usar agregações.

Por exemplo, a consulta a seguir retorna o número total de itens de trabalho.

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

✔️ CONSIDERE o uso de aliases de parâmetro para separar partes voláteis da consulta

Os aliases de parâmetro fornecem uma solução elegante para extrair partes voláteis, como valores de parâmetro, do texto da consulta principal. Você pode usá-los em expressões que avaliam:

  • Um valor primitivo
  • Um valor complexo
  • Uma coleção de valores primitivos ou complexos.

Para obter mais informações, consulte OData versão 4.0. Parte 2: Convenções de URL - 5.1.1.13 Aliases de parâmetro. Os parâmetros são úteis quando o texto da consulta é usado como um modelo que pode ser instanciado com valores fornecidos pelo usuário.

Por exemplo, a consulta a seguir usa @createdDateSK o parâmetro para separar o valor da expressão de filtro.

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

❌ EVITE misturar $apply e $filter cláusulas em uma única consulta

Se você quiser adicionar filter à sua consulta, você tem duas opções. Você pode fazer isso com a $filter cláusula ou a $apply=filter() combinação. Cada uma dessas opções funciona muito bem por conta própria, mas combiná-las pode levar a alguns resultados inesperados.

Apesar da expectativa que se possa ter, o OData define claramente uma ordem de avaliação. Além disso, a $apply cláusula tem prioridade sobre $filter. Por esse motivo, você deve escolher um ou outro, mas evite essas duas opções de filtro em uma única consulta. É importante que as consultas sejam geradas automaticamente.

Por exemplo, a consulta a seguir primeiro filtra os itens de trabalho por StoryPoint gt 5, agrega resultados por são caminho e, finalmente, filtra o resultado por StoryPoints gt 2. Com essa ordem de avaliação, a consulta sempre retorna um conjunto vazio.

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)
    )

✔️ CONSIDERE estruturar sua consulta para corresponder à ordem de avaliação OData

Como a combinação $apply de cláusulas e filter em uma única consulta pode levar a uma possível confusão, recomendamos que você estruture suas cláusulas de consulta para corresponder à ordem de avaliação.

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

✔️ CONSIDERE revisar os recursos do OData descritos nas anotações de metadados

Quando você não tiver certeza sobre quais recursos OData são compatíveis com o Analytics, poderá pesquisar anotações nos metadados. O Comitê Técnico do OASIS Open Data Protocol (OData) em um repositório TC GitHub mantém uma lista de anotações disponíveis.

Por exemplo, a lista de funções de filtro com suporte está disponível na Org.OData.Capabilities.V1.FilterFunctions anotação no contêiner de entidade.

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

Outra anotação útil é Org.OData.Capabilities.V1.ExpandRestrictions, que explica quais propriedades de navegação você não pode usar na $expand cláusula. Por exemplo, a anotação a seguir explica que Revisions o WorkItems conjunto de entidades não pode ser expandido.

<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>