Diretrizes de consulta do OData Analytics para o Azure DevOps

Serviços de DevOps do Azure | Azure DevOps Server 2022 - Azure DevOps Server 2019

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

Nota

O serviço Analytics é automaticamente habilitado e suportado na produção para todos os Serviços de DevOps do Azure. A integração do Power BI e o acesso ao feed OData do Serviço de Análise estão geralmente disponíveis. Nós encorajamos você a usá-lo e nos dar feedback. Os dados disponíveis dependem da versão. A última versão suportada é , e a versão de pré-visualização mais recente é v2.0v4.0-preview. Para obter mais informações, consulte Controle de versão da API OData.

Nota

O serviço Analytics é instalado automaticamente e tem suporte na produção para todas as novas coleções de projetos para o 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 geralmente disponíveis. Nós encorajamos você a usá-lo e nos dar feedback. Se você atualizou do Azure DevOps Server 2019, poderá instalar o serviço Analytics durante a atualização.

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

Nota

O serviço Analytics está em pré-visualização para o 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 Pré-visualização. Nós encorajamos você a usá-lo e nos dar feedback.

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

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

Gorjeta

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

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

Mensagens de erro e aviso

✔️ NÃO revise os avisos de resposta 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. Analise 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."
  ],
  ...
}

✔️ DO rever mensagens de erro 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 de associação não aparecem na @vsts.warnings propriedade. Em vez disso, eles geram uma mensagem de erro na propriedade na message 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

Considere

Bloqueado

Evitação

✔️ NÃO limite a consulta ao(s) projeto(s) a que tem acesso

Se a consulta tiver como destino dados de um projeto ao qual você não tem acesso, a consulta retornará uma mensagem "Acesso negado ao projeto". Para garantir que você tenha acesso, verifique se sua permissão Exibir análise está definida como Permitir para todos os projetos que você consultar. Para saber mais, consulte Permissões necessárias para acessar o Google 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 aos quais você não tem acesso. Adicione um ou mais filtros de projetos para especificar o(s) projeto(s) aos quais você tem acesso na entidade 'WorkItems'. Se você estiver usando $expand ou propriedades de 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 de escopo do projeto, conforme explicado posteriormente neste artigo.

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

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

✔️ DO especifique o filtro de projeto dentro da cláusula se sua $expand 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, 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 esta 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 expand é útil quando você usa a propriedade expand collection, como Children no conjunto de WorkItems entidades. Por exemplo, a consulta a seguir retorna todos os itens de trabalho de um determinado projeto juntamente 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 expandir uma das seguintes propriedades:

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

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

Se você estiver interessado em dados de um único projeto, recomendamos que use o ponto de extremidade OData com escopo de 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 referenciadas e todas as propriedades de navegação expandidas.

Com esta simplificação, as consultas da secção anterior poderiam ser reescritas para o seguinte formulário. Não só o filtro na cláusula de expansão desapareceu, mas também não há necessidade do filtro no conjunto de entidades principais.

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

A consulta para 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 dados de um único projeto. Para relatórios entre projetos, você precisa usar estratégias de filtragem descritas nas seções anteriores.

✔️ AGUARDE ou pare a operação se a sua consulta exceder os limites de utilização

Se você executar muitas consultas ou se as consultas exigirem muitos recursos para serem executadas, poderá exceder os limites de serviço e ser bloqueado temporariamente. Se você exceder os limites de serviço, pare 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 projetar consultas OData eficientes, consulte as Diretrizes de desempenho mais adiante neste artigo.

✔️ AGUARDE ou pare a operação se a sua 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. Pode sinalizar um problema transitório, então você pode tentar novamente uma vez para ver se o problema resolve. No entanto, os tempos limite persistentes indicam que a consulta é provavelmente muito cara para ser executada. Outras tentativas só resultam 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 sufixo Snapshot 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 WorkItemSnapshot e filtrasse 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, muito 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 saber mais sobre agregações, consulte Agregar dados.

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

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

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 às 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 que deseja, 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 seguinte erro.

A consulta especificada no URI não é válida. O Google Analytics não oferece suporte à navegação de chaves ou propriedades, como WorkItems(Id) ou WorkItem(Id)/AssignedTo. Se você receber esse erro no PowerBI, reescreva sua consulta para evitar dobragem incorreta que causa o problema N+1.

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

✔️ DO aborda explicitamente entidades com cláusulas de filtro

Se quiser buscar dados para uma única entidade, use a mesma abordagem que para uma coleção de entidades e defina explicitamente filtros $filter na 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 não tiver certeza de quais propriedades devem ser incluídas nesse filtro, você pode procurá-las nos metadados. Consulte Construir consultas OData para Analytics, componentes de URL para consultar os metadados. As propriedades estão no Key elemento EntityTypedo . Por exemplo, WorkItemId e Revision são colunas 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 Google Analytics não permite certos tipos de expansões. Um deles, que pode ser surpreendente para alguns, é a Revisions propriedade de cobrança na WorkItem entidade. Se tentar expandir esta propriedade, receberá a seguinte mensagem de erro.

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

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

✔️ DO 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 agrupar em colunas distintas

Use uma operação de agrupamento para reduzir o número de registros. O uso de groupby colunas distintas na cláusula indica um problema e a consulta falha imediatamente. Se você acidentalmente se deparar com essa situação, você 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 suporta a função, embora o OData o countdistinct 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 possam 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 para 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 incorrer em 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 com HTTP GET é de 3.000 caracteres. Se você excedê-lo, você receberá de volta uma resposta "404 Não encontrado".

HTTP/1.1 404 Not Found
Content-Length: 0

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

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

Restringimos o uso do ponto de extremidade em 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 Google Analytics não oferece suporte ao processamento de várias operações contidas na mensagem em lote atual. O Google Analytics usa o lote OData para dar suporte a solicitações POST, mas exige 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, você receberá a seguinte mensagem de erro.

VS403670: A consulta especificada retorna colunas 'N' que é maior do 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 de $expand na 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 subótimo.

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

✔️ NÃO especifique o fuso horário ao filtrar em 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. Estes dados são precisos e simples de interpretar ao mesmo tempo. Outra consequência não óbvia é que todos os filtros têm que passar as informações de fuso horário também. Se você ignorá-lo, você receberá a seguinte mensagem de erro.

A consulta especificada no URI não é válida. Nenhum deslocamento de data/hora foi especificado. Utilize um destes formatos AAAA-MM-ddZ para especificar tudo desde a 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) Hora do Pacífico (EUA & 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 mais (+) tem um significado especial no URI e você deve manipulá-lo corretamente. Se você especificar 2020-01-01T00:00:00+08:00 (com um + caractere) como seu ponto de partida, obterá 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) Beijing, 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

Não é

Considere

Evitação

✔️ DO mede o efeito da implementação de uma diretriz de desempenho

Como acontece com quaisquer recomendações 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 projete consultas semelhantes. No entanto, em casos raros, seguir as diretrizes pode não ter efeito ou mesmo um efeito negativo sobre o desempenho. Você precisa medir a diferença para notá-la. Se isso acontecer, 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 de 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 Fiddler Web Debugger Tool.

Seja qual for a sua abordagem, execute ambas as 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. O Analytics segue a arquitetura multilocatário. Assim, outras operações que ocorrem ao mesmo tempo podem afetar a duração das suas consultas.

✔️ NÃO 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 dados do lado do servidor e retornar uma resposta menor do que a que você pode obter aplicando a mesma função do lado do cliente. Finalmente, o Analytics é otimizado para este tipo de consultas, por isso faça uso dele.

Para saber mais, consulte Agregar dados.

✔️ DO especificar colunas na $select cláusula

Especifique as colunas que lhe interessam na $select cláusula. O Analytics é construído 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

Nota

O Azure DevOps dá suporte à personalização de processos. 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.

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

Da mesma forma que as diretrizes da cláusula, especifique as propriedades na $select opção expandir dentro da $select$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)

✔️ DO define um filtro quando RevisedDateSK você consulta dados históricos de itens de trabalho (WorkItemRevisionsWorkItemSnapshot ou conjuntos de entidades)

Quando você consulta dados históricos, as chances são de que você está 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 que a torna perfeita para filtros de System.RevisedDate histórico.

No Google Analytics, a data revisada é mostrada RevisedDate nas propriedades () e RevisedDateSK (Edm.DateTimeOffsetEdm.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 o inclusive, adicione o {startDate} seguinte filtro à sua 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 no RevisedDateSK. Embora possa parecer redundante, 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)
    )

Nota

Chegamos a essa recomendação quando estávamos trabalhando em widgets Burndown. Inicialmente, definimos filtros apenas para, mas não conseguimos que essa consulta fosse bem dimensionada para DateSK organizações com grandes conjuntos de dados. Durante a criação de perfil de consulta, notamos que DateSK não filtra bem as revisões. Só depois de adicionarmos um filtro conseguimos RevisedDateSK obter um ótimo desempenho em escala.
~ Equipa 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. Longos intervalos de tempo resultam em um grande número de registros. Se você não precisa de uma precisão tão alta, pode usar instantâneos semanais ou até 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 Google 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 um enum 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)
    )

✔️ DO use Tags a propriedade collection em itens de trabalho ao filtrar por tags

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

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

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

✔️ DO use TagNames a propriedade se quiser exibir todas as tags em um item de trabalho como texto

A propriedade TagsNavigation , descrita na seção anterior, é ótima para filtragem. No entanto, trabalhar com eles apresenta alguns desafios, pois a consulta retorna tags em uma coleção aninhada. O modelo de dados também contém uma TagNames propriedade primitiva (Edm.String), que adicionamos para simplificar cenários de consumo de tags. É um único valor de texto que contém uma lista de todas as tags combinadas com um separador ponto-e-vírgula "; ". Use essa propriedade quando tudo o que lhe interessa é exibir tags 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}arquivo . Ele retorna a ID do item de trabalho, título, estado e uma representação de texto de tags 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 tags ou se as tags forem muito longas, não TagNames contenha o conjunto completo e Tag a propriedade de navegação deve ser usada.

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

Se você já trabalhou com outros sistemas, pode esperar usar as funções ou toupper para a comparação que não diferencia maiúsculas tolower 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 manipulá-las explicitamente.

Por exemplo, a consulta a seguir obtém todos os itens de trabalho marcados com "QUALIDADE", "qualidade" 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

OData tem a capacidade de expandir todos os níveis de uma estrutura hierárquica. Por exemplo, o rastreamento de item de trabalho tem algumas entidades onde uma expansão ilimitada pode ser aplicada. Esta 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 utilize se:

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

✔️ NÃO use paginação orientada por servidor

Se você pedir 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 orientada 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"}

Nota

A maioria dos clientes OData existentes pode lidar com a paginação orientada por 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 orientada pelo cliente

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

✔️ DO 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 $skipo . Se no seu cenário de relatório você precisar apenas de um subconjunto de registros (por exemplo, exemplo), não há problema em usar $top a opção de consulta. Além disso, se você precisa classificar os recordes de acordo com alguns critérios, você deve sempre usar $top em combinação com para obter um resultado estável com $orderby os melhores registros 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. Procure sempre buscar apenas os dados que realmente lhe interessam. Você pode alcançá-lo aproveitando ao máximo os poderosos recursos de filtragem disponíveis 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 amplas (por exemplo, WorkItems). O Analytics é construído com base em uma tecnologia Columnstore Index . Isso significa que os dados são armazenados e o processamento de consultas é baseado em colunas. Assim, quanto mais propriedades uma consulta referenciar, mais caro será processá-la. Sempre procure limitar o conjunto de propriedades em suas consultas ao que você realmente se importa em seu cenário de relatórios.

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

Há muitas maneiras de definir um filtro de data. Você pode filtrar a propriedade date diretamente (por exemplo, ), sua contraparte de navegação (por exemplo, ) ou sua representação de chave substituta (por exemplo, CreatedDateCreatedOnDateCreatedDate). A última opção produz o melhor desempenho e é preferida quando os requisitos de informação 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 sobre o valor de um objeto relacionado (por exemplo, filtrando um item de trabalho no nome do projeto), você sempre tem duas opções. Você pode usar a propriedade de navegação (por exemplo, ) ou capturar a chave substituta antecipadamente e usá-la diretamente na consulta (por exemplo, ). Project/ProjectNameProjectSK

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 a propriedade em ProjectSK vez da Project/ProjectName propriedade navigation.

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

❌EVITE usar Parent, Childrenou propriedades nas $filter cláusulas ou Revisions$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, , ChildrenRevisions. Toda vez que você usá-los dentro de uma consulta, no entanto, 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.

Esta opção é útil em cenários de exportação de dados. Para usá-lo, você precisa adicionar Prefer cabeçalho à sua solicitação HTTP e definir VSTS.Analytics.MaxSize como 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 retorna 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 seguinte erro.

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

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

Diretrizes de estilo de consulta

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

Algumas entidades expõem Count a 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 a 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, recomenda-se usar agregações em vez disso.

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âmetros, do texto de 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 quiser adicionar filter à sua consulta, tem duas opções. Pode fazê-lo com a cláusula ou com a $filter$apply=filter() combinação. Cada uma dessas opções funciona muito bem por si só, 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 cláusula tem prioridade sobre $filter.$apply Por esse motivo, você deve escolher uma ou outra, 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 itens de trabalho por , agrega resultados por caminho e, finalmente, filtra o resultado por StoryPoint gt 5StoryPoints 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 mistura $apply e filter as cláusulas em uma única consulta pode causar confusão potencial, 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 a revisão dos recursos OData descritos nas anotações de metadados

Quando não tiver certeza sobre quais recursos do OData o Google Analytics suporta, você poderá procurar 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 suportadas está disponível em 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 no conjunto de WorkItems 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>