Monitorar e depurar um aplicativo .NET do Lote do Azure com o Application Insights
O Application Insights fornece uma maneira elegante e avançada para os desenvolvedores monitorarem e depurarem aplicativos implantados nos serviços do Azure. Use o Application Insights para monitorar exceções e contadores de desempenho, bem como instrumentar o código com rastreamento e métricas personalizadas. A integração do Application Insights com o aplicativo Lote do Azure permite que você obtenha insights aprofundados sobre os comportamentos e investigue os problemas quase em tempo real.
Este artigo mostra como adicionar e configurar a biblioteca do Application Insights na solução .NET do Lote do Azure e instrumentar o código do aplicativo. Adicionalmente, mostra maneiras de monitorar o aplicativo por meio do Portal do Azure e criar painéis personalizados. Para obter suporte do Application Insights em outros idiomas, confira a documentação de linguagens, plataformas e integrações.
Uma solução C# de exemplo com código para acompanhar este artigo está disponível no GitHub. Este exemplo adiciona o código de instrumentação do Application Insights ao exemplo do TopNWords. Se você não estiver familiarizado com esse exemplo, tente primeiro compilar e executar o TopNWords. Isso ajudará a compreender um fluxo de trabalho básico do Lote do processamento de um conjunto de blobs de entrada em paralelo em vários nós de computação.
Dica
Como alternativa, configure sua solução em lote para exibir dados do Application Insights, como os contadores de desempenho da VM no Batch Explorer. O Batch Explorer é uma ferramenta cliente autônoma, rica e exclusiva para ajudar a criar, depurar e monitorar aplicativos em lote do Azure. Baixe um pacote de instalação para Mac, Linux ou Windows. Confira o repositório de insights em lote para conhecer etapas rápidas para habilitar dados do Application Insights no Batch Explorer.
Pré-requisitos
Recurso do Application Insights. Use o Portal do Azure para criar um recurso do Application Insights. Selecione o Tipo de aplicativo.Geral.
Copie a chave de instrumentação do portal do Azure. Você precisará desse valor mais tarde.
Observação
Você pode ser cobrado pelos dados armazenados no Application Insights. Isso inclui os dados de diagnóstico e monitoramento discutidos neste artigo.
Adicione o Application Insights ao seu projeto
O pacote do NuGet Microsoft.ApplicationInsights.WindowsServer e suas dependências são necessários para o projeto. Adicione ou restaure-os no projeto do aplicativo. Para instalar o pacote, use comando Install-Package
ou o Gerenciador de Pacotes do NuGet.
Install-Package Microsoft.ApplicationInsights.WindowsServer
Consulte o Application Insights do aplicativo .NET usando o namespace Microsoft.ApplicationInsights.
Instrumentalize seu código
Para instrumentar o código, a solução precisa criar um TelemetryClient do Application Insights. No exemplo, o TelemetryClient carrega a configuração do arquivo ApplicationInsights.config. Certifique-se de atualizar o ApplicationInsights.config nos projetos a seguir com a chave de instrumentação do Application Insights Microsoft.Azure.Batch.Samples.TelemetryStartTask and TopNWordsSample.
<InstrumentationKey>YOUR-IKEY-GOES-HERE</InstrumentationKey>
Adicione também a chave de instrumentação no arquivo TopNWords.cs.
O exemplo em TopNWords.cs usa as seguintes chamadas de instrumentação da API do Application Insights:
TrackMetric()
- Rastreia quanto tempo, em média, um nó de computação demora para baixar o arquivo de texto necessário.TrackTrace()
- Adiciona chamadas de depuração ao código.TrackEvent()
- Rastreia eventos interessantes para capturar.
Este exemplo exclui propositalmente o tratamento de exceções. Em vez disso, o Application Insights informa automaticamente as exceções não tratadas, o que melhora significativamente a experiência de depuração.
O seguinte snippet ilustra como usar esses métodos.
public void CountWords(string blobName, int numTopN, string storageAccountName, string storageAccountKey)
{
// simulate exception for some set of tasks
Random rand = new Random();
if (rand.Next(0, 10) % 10 == 0)
{
blobName += ".badUrl";
}
// log the url we are downloading the file from
insightsClient.TrackTrace(new TraceTelemetry(string.Format("Task {0}: Download file from: {1}", this.taskId, blobName), SeverityLevel.Verbose));
// open the cloud blob that contains the book
var storageCred = new StorageCredentials(storageAccountName, storageAccountKey);
CloudBlockBlob blob = new CloudBlockBlob(new Uri(blobName), storageCred);
using (Stream memoryStream = new MemoryStream())
{
// calculate blob download time
DateTime start = DateTime.Now;
blob.DownloadToStream(memoryStream);
TimeSpan downloadTime = DateTime.Now.Subtract(start);
// track how long the blob takes to download on this node
// this will help debug timing issues or identify poorly performing nodes
insightsClient.TrackMetric("Blob download in seconds", downloadTime.TotalSeconds, this.CommonProperties);
memoryStream.Position = 0; //Reset the stream
var sr = new StreamReader(memoryStream);
var myStr = sr.ReadToEnd();
string[] words = myStr.Split(' ');
// log how many words were found in the text file
insightsClient.TrackTrace(new TraceTelemetry(string.Format("Task {0}: Found {1} words", this.taskId, words.Length), SeverityLevel.Verbose));
var topNWords =
words.
Where(word => word.Length > 0).
GroupBy(word => word, (key, group) => new KeyValuePair<String, long>(key, group.LongCount())).
OrderByDescending(x => x.Value).
Take(numTopN).
ToList();
foreach (var pair in topNWords)
{
Console.WriteLine("{0} {1}", pair.Key, pair.Value);
}
// emit an event to track the completion of the task
insightsClient.TrackEvent("Done counting words");
}
}
Auxiliar do inicializador de telemetria do Lote do Azure
Ao reportar a telemetria para um determinado servidor e instância, o Application Insights usa o nome da VM e a função VM do Azure para os valores padrão. No contexto do Lote do Azure, o exemplo mostra como usar o nome do pool e o nome do nó de computação. Use um inicializador de telemetria para substituir os valores padrão.
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using System;
using System.Threading;
namespace Microsoft.Azure.Batch.Samples.TelemetryInitializer
{
public class AzureBatchNodeTelemetryInitializer : ITelemetryInitializer
{
// Azure Batch environment variables
private const string PoolIdEnvironmentVariable = "AZ_BATCH_POOL_ID";
private const string NodeIdEnvironmentVariable = "AZ_BATCH_NODE_ID";
private string roleInstanceName;
private string roleName;
public void Initialize(ITelemetry telemetry)
{
if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleName))
{
// override the role name with the Azure Batch Pool name
string name = LazyInitializer.EnsureInitialized(ref this.roleName, this.GetPoolName);
telemetry.Context.Cloud.RoleName = name;
}
if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleInstance))
{
// override the role instance with the Azure Batch Compute Node name
string name = LazyInitializer.EnsureInitialized(ref this.roleInstanceName, this.GetNodeName);
telemetry.Context.Cloud.RoleInstance = name;
}
}
private string GetPoolName()
{
return Environment.GetEnvironmentVariable(PoolIdEnvironmentVariable) ?? string.Empty;
}
private string GetNodeName()
{
return Environment.GetEnvironmentVariable(NodeIdEnvironmentVariable) ?? string.Empty;
}
}
}
Para habilitar o inicializador de telemetria, o arquivo ApplicationInsights.config no projeto TopNWordsSample inclui o seguinte:
<TelemetryInitializers>
<Add Type="Microsoft.Azure.Batch.Samples.TelemetryInitializer.AzureBatchNodeTelemetryInitializer, Microsoft.Azure.Batch.Samples.TelemetryInitializer"/>
</TelemetryInitializers>
Atualizar o trabalho e as tarefas para incluir binários do Application Insights
Para que o Application Insights seja executado corretamente nos nós de computação, verifique se os binários estão posicionados corretamente. Adicione os binários necessários à coleção de arquivos de recursos da tarefa para que eles sejam baixados no momento em que a tarefa for executada. Os snippets a seguir são semelhantes ao código no Job.cs.
Primeiro, crie uma lista estática de arquivos do Application Insights para upload.
private static readonly List<string> AIFilesToUpload = new List<string>()
{
// Application Insights config and assemblies
"ApplicationInsights.config",
"Microsoft.ApplicationInsights.dll",
"Microsoft.AI.Agent.Intercept.dll",
"Microsoft.AI.DependencyCollector.dll",
"Microsoft.AI.PerfCounterCollector.dll",
"Microsoft.AI.ServerTelemetryChannel.dll",
"Microsoft.AI.WindowsServer.dll",
// custom telemetry initializer assemblies
"Microsoft.Azure.Batch.Samples.TelemetryInitializer.dll",
};
...
Em seguida, crie os arquivos temporários usados pela tarefa.
...
// create file staging objects that represent the executable and its dependent assembly to run as the task.
// These files are copied to every node before the corresponding task is scheduled to run on that node.
FileToStage topNWordExe = new FileToStage(TopNWordsExeName, stagingStorageAccount);
FileToStage storageDll = new FileToStage(StorageClientDllName, stagingStorageAccount);
// Upload Application Insights assemblies
List<FileToStage> aiStagedFiles = new List<FileToStage>();
foreach (string aiFile in AIFilesToUpload)
{
aiStagedFiles.Add(new FileToStage(aiFile, stagingStorageAccount));
}
...
O método FileToStage
é uma função auxiliar no exemplo de código que permite carregar facilmente um arquivo do disco local em um blob de armazenamento do Azure. Cada arquivo será posteriormente baixado para um nó de computação e referenciado por uma tarefa.
Por fim, adicione as tarefas ao trabalho e inclua os binários necessários do Application Insights.
...
// initialize a collection to hold the tasks that will be submitted in their entirety
List<CloudTask> tasksToRun = new List<CloudTask>(topNWordsConfiguration.NumberOfTasks);
for (int i = 1; i <= topNWordsConfiguration.NumberOfTasks; i++)
{
CloudTask task = new CloudTask("task_no_" + i, String.Format("{0} --Task {1} {2} {3} {4}",
TopNWordsExeName,
string.Format("https://{0}.blob.core.windows.net/{1}",
accountSettings.StorageAccountName,
documents[i]),
topNWordsConfiguration.TopWordCount,
accountSettings.StorageAccountName,
accountSettings.StorageAccountKey));
//This is the list of files to stage to a container -- for each job, one container is created and
//files all resolve to Azure Blobs by their name (so two tasks with the same named file will create just 1 blob in
//the container).
task.FilesToStage = new List<IFileStagingProvider>
{
// required application binaries
topNWordExe,
storageDll,
};
foreach (FileToStage stagedFile in aiStagedFiles)
{
task.FilesToStage.Add(stagedFile);
}
task.RunElevated = false;
tasksToRun.Add(task);
}
Exibir dados no Portal do Azure
Agora que você configurou o trabalho e as tarefas para usar o Application Insights, execute o exemplo de trabalho no pool. Navegue até o Portal do Azure e abra o recurso do Application Insights provisionado. Depois que o pool for provisionado, você deverá começar a ver o fluxo de dados e a obtenção de registros. O restante deste artigo aborda apenas alguns recursos do Application Insights, mas fique à vontade para explorar o conjunto completo de recursos.
Exibir dados do Live Stream
Para exibir os logs de rastreamento no recurso do Applications Insights, clique em Live Stream. A captura de tela a seguir mostra como exibir dados dinâmicos provenientes dos nós de computação no pool, por exemplo, o uso da CPU por nó de computação.
Exibir logs de rastreamento
Para exibir os logs de rastreamento no recurso do Applications Insights, clique em Pesquisar. Essa visualização mostra uma lista de dados de diagnóstico capturados pelo Application Insights, incluindo rastreamentos, eventos e exceções.
A captura de tela a seguir mostra como um único rastreamento de uma tarefa é registrado em log e, posteriormente, consultado para fins de depuração.
Exibir exceções sem tratamento
O Application Insights registra exceções lançadas do aplicativo. Nesse caso, alguns segundos depois que o aplicativo lançar a exceção será possível detalhar uma exceção específica e diagnosticar o problema.
Medir o tempo de download de blob
Métricas personalizadas também são uma ferramenta valiosa no portal. Por exemplo, é possível exibir o tempo médio que cada nó de computação demorou para baixar o arquivo de texto necessário que estava processando.
Para criar um gráfico de exemplo:
- No recurso do Application Insights, clique em Metrics Explorer>Adicionar gráfico.
- Clique em Editar no gráfico que foi adicionado.
- Atualize os detalhes do gráfico conforme a seguir:
- Defina Tipo de gráfico para Grade.
- Defina Agregação para Média.
- Defina Agrupar por para NodeId.
- Em Métrica, selecione Personalizar>Baixar o blob em segundos.
- Ajuste a Paleta de cores à sua escolha.
Monitorar os nós de computação continuamente
Você deve ter observado que todas as métricas, incluindo contadores de desempenho, são registradas apenas quando as tarefas estão em execução. Esse comportamento é útil porque limita a quantidade de dados que o Application Insights registra. No entanto, há casos em que você sempre gostaria de monitorar os nós de computação. Por exemplo, eles podem estar executando um trabalho em segundo plano que não está agendado por meio do serviço do Lote. Nesse caso, configure um processo de monitoramento para executar a vida útil do nó de computação.
Uma maneira de obter esse comportamento é gerar um processo que carregue a biblioteca do Application Insights e seja executado em segundo plano. No exemplo, a tarefa inicial carrega os binários no computador e mantém um processo em execução indefinidamente. Configure o arquivo de configuração do Application Insights para que esse processo emita dados adicionais nos quais você está interessado, como contadores de desempenho.
...
// Batch start task telemetry runner
private const string BatchStartTaskFolderName = "StartTask";
private const string BatchStartTaskTelemetryRunnerName = "Microsoft.Azure.Batch.Samples.TelemetryStartTask.exe";
private const string BatchStartTaskTelemetryRunnerAIConfig = "ApplicationInsights.config";
...
CloudPool pool = client.PoolOperations.CreatePool(
topNWordsConfiguration.PoolId,
targetDedicated: topNWordsConfiguration.PoolNodeCount,
virtualMachineSize: "standard_d1_v2",
VirtualMachineConfiguration: new VirtualMachineConfiguration(
imageReference: new ImageReference(
publisher: "MicrosoftWindowsServer",
offer: "WindowsServer",
sku: "2019-datacenter-core",
version: "latest"),
nodeAgentSkuId: "batch.node.windows amd64");
...
// Create a start task which will run a dummy exe in background that simply emits performance
// counter data as defined in the relevant ApplicationInsights.config.
// Note that the waitForSuccess on the start task was not set so the Compute Node will be
// available immediately after this command is run.
pool.StartTask = new StartTask()
{
CommandLine = string.Format("cmd /c {0}", BatchStartTaskTelemetryRunnerName),
ResourceFiles = resourceFiles
};
...
Dica
Para aumentar a capacidade de gerenciamento da solução, é possível agrupar o assembly em um pacote de aplicativos. Em seguida, para implantar o pacote de aplicativos automaticamente nos pools, adicione uma referência de pacote de aplicativos à configuração do pool.
Limitação e dados de exemplo
Devido à natureza em grande escala dos aplicativos do Lote do Azure executando em produção, convém limitar a quantidade de dados coletados pelo Application Insights para gerenciar os custos. Consulte Amostragem em Application Insights e obtenha alguns mecanismos para fazer isso.
Próximas etapas
- Saiba mais sobre o Application Insights.
- Para obter suporte do Application Insights em outros idiomas, confira a documentação de linguagens, plataformas e integrações.