Monitorar Azure Functions e Hubs de Eventos

Hubs de eventos do Azure
Funções do Azure
Azure Monitor

O monitoramento fornece insights sobre o comportamento e a integridade de seus sistemas e ajuda a criar uma visão holística do ambiente, tendências históricas, correlacionar diversos fatores e medir mudanças no desempenho, consumo ou taxa de erro.

O Azure Functions oferece integração interna com o Application Insights. No Application Insights, você pode obter informações como o número de instâncias de aplicativo de função ou a telemetria de solicitação e dependência de uma função. Ao trabalhar com o Functions e os Hubs de Eventos, o Application Insights também pode rastrear as telemetrias de dependência de saída para o hub de eventos, calculando o tempo de processamento e mostrando o fluxo de ponta a ponta do sistema conectado por meio dos Hubs de Eventos.

Esta seção apresenta recursos e insights úteis que você pode obter do Application Insights para sua solução de Hubs de Eventos e Functions.

Mapa do aplicativo

O mapa de aplicativo mostra como os componentes em um sistema estão interagindo entre si. Devido à telemetria de dependência que o Application Insights fornece, ele mapeia o fluxo de eventos entre o Azure Functions e os Hubs de Eventos, incluindo a média de cada execução de função e a duração média de um evento nos Hubs de Eventos, além de mostrar transações que contêm falhas marcadas em vermelho.

Depois de enviar a carga esperada para o sistema, você pode acessar o Application Insights no portal do Azure e, na barra lateral, escolher Mapa do aplicativo. Veja a seguir um mapa que mostra três funções, três hubs de eventos e falhas aparentes ao gravar em um banco de dados downstream:

Mapa do aplicativo

Detalhes da transação de ponta a ponta

Os detalhes da transação de ponta a ponta mostram como os componentes do sistema interagem entre si, em ordem cronológica. Essa exibição também mostra quanto tempo um evento passou em processamento. Você também pode detalhar a telemetria de cada componente a partir dessa exibição, o que facilita a solução de problemas entre componentes dentro da mesma solicitação quando ocorre um problema.

Transação de ponta a ponta

Métricas e telemetria da plataforma

As métricas geradas pela plataforma no Azure Monitor para Hubs de Eventos e Azure Functions podem ser usadas para monitoramento geral do comportamento e da integridade da solução:

O Azure Functions integra-se ao Application Insights para fornecer telemetria avançada e detalhada e insights sobre as execuções de host e função do Functions. Para saber mais, consulte Analisar a telemetria do Azure Functions no Application Insights. Ao usar o Application Insights para monitorar uma topologia, há uma variedade de configurações disponíveis. Para saber mais, confira Como configurar o monitoramento para o Azure Functions.

Veja a seguir um exemplo de telemetria extra para funções acionadas de Hubs de Eventos geradas na tabela de rastreamentos:

Trigger Details: PartionId: 6, Offset: 3985758552064-3985758624640, EnqueueTimeUtc: 2022-10-31T12:51:58.1750000+00:00-2022-10-31T12:52:03.8160000+00:00, SequenceNumber: 3712266-3712275, Count: 10

Essas informações exigem que você use a extensão de Hubs de Eventos 4.2.0 ou uma versão posterior. Esses dados são muito úteis, pois contêm informações sobre a mensagem que acionou a execução da função e podem ser usados para consultas e insights. Ele inclui os seguintes dados para cada vez que a função é acionada:

  • O ID da partição (6)
  • O intervalo de deslocamento de partição (3985758552064-3985758624640)
  • O intervalo de tempo de enfileiramento em UTC (2022-10-31T12:51:58.1750000+00:00-2022-10-31T12:52:03.8160000+00:00)
  • O intervalo de números de sequência 3712266-3712275
  • E a contagem de mensagens (10)

Consulte a seção Exemplo de consultas do Application Insights para obter exemplos sobre como usar essa telemetria.

A telemetria personalizada também é possível para diferentes linguagens (biblioteca de classes C#, C# Isolado, Script C#, JavaScript, Java, PowerShell e Python). Esse registro em log aparece na tabela rastreamentos no Application Insights. Você pode criar suas próprias entradas no Application Insights e adicionar dimensões personalizadas que podem ser usadas para consultar dados e criar painéis personalizados.

Finalmente, quando seu aplicativo de função se conecta a um hub de eventos usando uma associação de saída, as entradas também são gravadas na Tabela de dependências do Application Insights.

Tabela de dependências

Para Hubs de Eventos, a correlação é injetada na carga do evento e você vê uma propriedade Diagnostic-Id em eventos:

Propriedade Diagnostic Id

Isso segue o formato Contexto de Rastreamento W3C que também é usado como ID da operação e Links de operação na telemetria criada pelo Functions, que permite que o Application Insights crie a correlação entre eventos do hub de eventos e execuções de função, mesmo quando são distribuídos.

Correlação de eventos em lote

Exemplo de consultas do Application Insights

Veja abaixo uma lista de consultas úteis do Application Insights ao monitorar Hubs de Eventos com o Azure Functions. Essa consulta exibe informações detalhadas para a função acionada do hub de eventos usando a telemetria emitida pela extensão 4.2.0 e superior dos Hubs de Eventos.

Quando a amostragem está habilitada no Application Insights, pode haver lacunas nos dados.

Informações detalhadas de processamento de eventos

Os dados só são emitidos no formato correto quando o envio em lote é usado. Envio em lote significa que a função aceita vários eventos para cada execução, o que é recomendado para desempenho. Tenha em mente as seguintes considerações:

  • O dispatchTimeMilliseconds valor aproxima o período de tempo entre quando o evento foi gravado no hub de eventos e quando foi selecionado pelo aplicativo de função para processamento.
  • dispatchTimeMilliseconds pode ser negativo ou impreciso devido ao desvio de relógio entre o servidor do Hub de Eventos e o aplicativo de função.
  • As partições dos Hubs de Eventos são processadas sequencialmente. Uma mensagem não será enviada para o código de função para processamento até que todas as mensagens anteriores tenham sido processadas. Monitore o tempo de execução de suas funções, pois tempos de execução mais longos causarão atrasos de envio.
  • O cálculo usa o enqueueTime da primeira mensagem no lote. Os tempos de envio podem ser menores para outras mensagens no lote.
  • dispatchTimeMilliseconds é baseado no ponto no tempo.
  • Os números de sequência são por partição e o processamento duplicado pode ocorrer porque os Hubs de Eventos não garantem a entrega exata de uma mensagem.
traces
| where message startswith "Trigger Details: Parti"
| parse message with * "tionId: " partitionId:string ", Offset: "
offsetStart:string "-" offsetEnd:string", EnqueueTimeUtc: "
enqueueTimeStart:datetime "+00:00-" enqueueTimeEnd:datetime "+00:00, SequenceNumber: "
sequenceNumberStart:string "-" sequenceNumberEnd:string ", Count: "
messageCount:int
| extend dispatchTimeMilliseconds = (timestamp - enqueueTimeStart) / 1ms
| project timestamp, cloud_RoleInstance, operation_Name, processId =
customDimensions.ProcessId, partitionId, messageCount, sequenceNumberStart,
sequenceNumberEnd, enqueueTimeStart, enqueueTimeEnd, dispatchTimeMilliseconds

Processamento detalhado de eventos

Visualização de latência de despacho

Essa consulta visualiza a latência de despacho de eventos de 50% e 90% para uma determinada função acionada do hub de eventos. Confira a consulta acima para obter mais detalhes e observações.

traces
| where operation_Name == "<ENTER THE NAME OF YOUR FUNCTION HERE>"
| where message startswith "Trigger Details: Parti"
| parse message with * "tionId: " partitionId:string ", Offset: "
offsetStart:string "-" offsetEnd:string", EnqueueTimeUtc: "
enqueueTimeStart:datetime "+00:00-" enqueueTimeEnd:datetime "+00:00, SequenceNumber: "
sequenceNumberStart:string "-" sequenceNumberEnd:string ", Count: "
messageCount:int
| extend dispatchTimeMilliseconds = (timestamp - enqueueTimeStart) / 1ms
| summarize percentiles(dispatchTimeMilliseconds, 50, 90) by bin(timestamp, 5m)
| render timechart

Visualização de latência de despacho

Resumo da latência de despacho

Essa consulta é semelhante à acima, mas mostra uma exibição de resumo.

traces
| where message startswith "Trigger Details: Parti"
| parse message with * "tionId: " partitionId:string ", Offset: "
offsetStart:string "-" offsetEnd:string", EnqueueTimeUtc: "
enqueueTimeStart:datetime "+00:00-" enqueueTimeEnd:datetime "+00:00, SequenceNumber: "
sequenceNumberStart:string "-" sequenceNumberEnd:string ", Count: "
messageCount:int
| extend dispatchTimeMilliseconds = (timestamp - enqueueTimeStart) / 1ms
| summarize messageCount = sum(messageCount),
percentiles(dispatchTimeMilliseconds, 50, 90, 99, 99.9, 99.99) by operation_Name

Resumo da latência de despacho

Distribuição de mensagens entre partições

Esta consulta mostra como visualizar a distribuição de mensagens entre partições.

traces
| where message startswith "Trigger Details: Parti"
| parse message with * "tionId: " partitionId:string ", Offset: "
offsetStart:string "-" offsetEnd:string", EnqueueTimeUtc: "
enqueueTimeStart:datetime "+00:00-" enqueueTimeEnd:datetime "+00:00, SequenceNumber: "
sequenceNumberStart:string "-" sequenceNumberEnd:string ", Count: "
messageCount:int
| summarize messageCount = sum(messageCount) by cloud_RoleInstance,
bin(timestamp, 5m)
| render areachart kind=stacked

Distribuição de mensagens entre partições

Distribuição de mensagens entre instâncias

Esta consulta mostra como visualizar a distribuição de mensagens entre instâncias.

traces
| where message startswith "Trigger Details: Parti"
| parse message with * "tionId: " partitionId:string ", Offset: "
offsetStart:string "-" offsetEnd:string", EnqueueTimeUtc: "
enqueueTimeStart:datetime "+00:00-" enqueueTimeEnd:datetime "+00:00, SequenceNumber: "
sequenceNumberStart:string "-" sequenceNumberEnd:string ", Count: "
messageCount:int
| summarize messageCount = sum(messageCount) by cloud_RoleInstance,
bin(timestamp, 5m)
| render areachart kind=stacked

Distribuição de mensagens entre instâncias

Executando instâncias e instâncias alocadas

Esta consulta mostra como visualizar o número de instâncias do Azure Functions que estão processando eventos de Hubs de Eventos e o número total de instâncias (processando e aguardando concessão). Na maioria das vezes devem ser os mesmos.

traces
| where message startswith "Trigger Details: Parti"
| summarize type = "Executing Instances", Count = dcount(cloud_RoleInstance) by
bin(timestamp, 60s)
| union (
    traces
    | summarize type = "Allocated Instances", Count = dcount(cloud_RoleInstance) by
bin(timestamp, 60s)
)
| project timestamp, type, Count
| render timechart

Executando instâncias e instâncias alocadas

Toda a telemetria para uma execução de função específica

O campo operation_Id pode ser usado nas diferentes tabelas no Application Insights. Para Hubs de Eventos acionados pelo Azure Functions, a consulta a seguir, por exemplo, resultará nas informações de gatilho, telemetria de logs dentro do código de função e dependências e exceções:

union isfuzzy=true requests, exceptions, traces, dependencies
| where * has "<ENTER THE OPERATION_ID OF YOUR FUNCTION EXECUTION HERE>"
| order by timestamp asc

Toda a telemetria para uma execução de função específica

Latência de ponta a ponta para um evento

Como a propriedade enqueueTimeUtc no rastreamento de detalhes do gatilho mostra o tempo de enfileiramento de apenas o primeiro evento de cada lote processado pela função, uma consulta mais avançada pode ser usada para calcular a latência de ponta a ponta de eventos entre duas funções com Hubs de Eventos intermediários. Essa consulta expandirá os links de operação (se houver) na solicitação da segunda função e mapeará sua hora de término para o mesmo ID de operação correspondente da hora de início da primeira função.

let start = view(){
requests
| where operation_Name == "FirstFunction"
| project start_t = timestamp, first_operation_Id = operation_Id
};
let link = view(){
requests
| where operation_Name == "SecondFunction"
| mv-expand ex = parse_json(tostring(customDimensions["_MS.links"]))
| extend parent = case(isnotempty(ex.operation_Id), ex.operation_Id, operation_Id )
| project first_operation_Id = parent, second_operation_Id = operation_Id
};
let finish = view(){
traces
| where customDimensions["EventName"] == "FunctionCompleted" and operation_Name
== "SecondFunction"
| project end_t = timestamp, second_operation_Id = operation_Id
};
start
| join kind=inner (
link
| join kind=inner finish on second_operation_Id
) on first_operation_Id
| project start_t, end_t, first_operation_Id, second_operation_Id
| summarize avg(datetime_diff('second', end_t, start_t))

Latência de ponta a ponta para um evento

Colaboradores

Esse artigo é mantido pela Microsoft. Ele foi originalmente escrito pelos colaboradores a seguir.

Autor principal:

Para ver perfis não públicos do LinkedIn, entre no LinkedIn.

Próximas etapas

Para saber mais, veja estes artigos relacionados: