O blog da AWS

.NET – observabilidade com Amazon CloudWatch e AWS X-Ray: Parte 1 — Métricas

Por Ulili Nhaga, é Cloud Application Architect na AWS

 

Construir uma aplicação .NET bem arquitetada vai além de apenas codificar e implantar. Você deve monitorar o desempenho, rastrear transações, coletar logs, reunir métricas e acionar alarmes quando as métricas ultrapassarem os limites. Para alcançar isso, você pode projetar e implementar a telemetria para habilitar recursos de observabilidade.Esta postagem é a primeira de uma série de três postagens em que demonstrarei como instrumentar uma aplicação .NET para gerar métricas, logs e rastreamentos distribuídos e como usá-los com o Amazon CloudWatch e o AWS X-Ray para melhorar a observabilidade. Nesta primeira postagem, explorarei a implementação e o uso de métricas do Amazon CloudWatch em um trabalho .NET em contêiner executado na AWS.

Visão geral da solução

Imagine um trabalho .NET em contêiner como o mostrado na Figura 1, que é executado no Amazon Elastic Container Service (Amazon ECS) com o AWS Fargate. Ele é composto por três microsserviços .NET: uma API da web ASP.NET Core, dois Serviços de Trabalhador e os recursos em nuvem que eles usam. Se algo der errado com esse trabalho, você pode ver aumento nas taxas de erro, desempenho degradado ou inconsistência de dados. Como você solucionaria a causa raiz do problema, como quais componentes estão falhando ou com desempenho insatisfatório?

Nesse exemplo, os Serviços de Trabalhador não possuem interface do usuário ou API para interação do usuário final, então eles podem falhar silenciosamente. Para evitar esses cenários, você pode implementar a observabilidade usando métricas, logs e rastreamentos distribuídos para fornecer visibilidade sobre a saúde e o desempenho de cada componente. Usando essa arquitetura como exemplo, mostrarei como usar o Amazon CloudWatch e o AWS X-Ray para implementar métricas nesta aplicação .NET.

Architecture Diagram

Figura 1: Solução de microsserviço .NET

Pré-requisitos

Para este exemplo, você pode usar o repositório do GitHub “microservices-dotnet-aws-cdk“, que contém o código de exemplo para os três microsserviços. Ele usa o AWS Cloud Development Kit (CDK) para definir e provisionar a infraestrutura como código usando a linguagem de programação C#.

Os seguintes pré-requisitos são necessários em seu sistema para testar e implantar esta solução:

.NET 6.0 Software Development Kit (SDK)

Git CLI

Interface de Linha de Comando da AWS (AWS CLI)

AWS CDK v2

Docker

Visual Studio Code (ou seu IDE preferido)

Credenciais da AWS para sua conta da AWS configuradas localmente

Git

Você pode clonar o repositório usando a linha de comando com o seguinte comando:

git clone https://github.com/aws-samples/microservices-dotnet-aws-cdk.git

Abra a solução em um IDE como o Visual Studio Code para explorar a implementação.

Implementando métricas com Métricas CloudWatch em aplicações .NET

Você pode implementar diferentes métricas em suas aplicações .NET usando o Amazon CloudWatch. Você pode coletar métricas específicas do negócio que incluem: medições no nível da aplicação, métricas de aplicação web .NET para mensurar solicitações HTTP, ou métricas de infraestrutura para fornecer dados de utilização de recursos da AWS.

Considere coletar métricas específicas do negócio e métricas de aplicação web .NET no código da aplicação. Além disso, você pode coletar métricas de infraestrutura usando a integração do Amazon CloudWatch com os serviços de computação da AWS onde você escolher hospedar a aplicação .NET, como o CloudWatch Container Insights para aplicações baseadas em contêineres.

Para implementar estas métricas, você pode usar a chamada de API PutMetricData do CloudWatch usando o AWS SDK para .NET ou o CloudWatch Embedded Metric Format (EMF). Para este exemplo, estou focando no uso do CloudWatch EMF para mostrar como ele permite a ingestão de dados de aplicação complexos e de alta cardinalidade como logs para gerar métricas acionáveis. O EMF permite que a aplicação incorpore métricas personalizadas nos dados detalhados do evento de log, usando um contêiner auxiliar para processar, analisar e transmitir as métricas para o CloudWatch. Além disso, um processo auxiliar evita a contenção de utilização de recursos na aplicação, ajudando a evitar impacto no desempenho e na taxa de transferência.

Para a implementação do CloudWatch EMF, estou usando o pacote NuGet Amazon.CloudWatch.EMF em todos os três projetos de aplicação. Também uso o pacote NuGet (Amazon.CloudWatch.EMF.Web) no projeto de aplicação web, que permite a instrumentação automática para métricas de todas as solicitações e respostas HTTP. O exemplo de código a seguir ilustra a configuração do CloudWatch EMF no arquivo Program.cs para gerar métricas para a aplicação web. Consulte um dos arquivos Program.cs do Serviço de Trabalhador para aprender como implementá-lo para esse tipo de aplicação.

...
//Register CloudWatch EMF for ASP.NET Core
EMF.Config.EnvironmentConfigurationProvider.Config = new EMF.Config.Configuration
{
    ServiceName = MY_SERVICE_NAME,
    ServiceType = "WebApi",
    LogGroupName = Environment.GetEnvironmentVariable("AWS_EMF_LOG_GROUP_NAME"),
    EnvironmentOverride = EMF.Environment.Environments.ECS
};
builder.Services.AddEmf()
...
//Register CloudWatch EMF Middleware
app.UseEmfMiddleware((context, logger) =>
{
    if (logger == null)
    {
        return Task.CompletedTask;
    }
    logger.PutMetadata("MY_SERVICES_INSTANCE", Environment.GetEnvironmentVariable("MY_SERVICES_INSTANCE"));
    return Task.CompletedTask;
});
...

Para a implementação de métricas específicas do negócio, utilizo injeção de dependência para fornecer uma instância de um objeto que implementa a interface IMetricsLogger em cada controlador ou classe de serviço e emito as métricas específicas do negócio. O exemplo de código a seguir ilustra a implementação.

Injeção da instância IMetricsLogger:

...
 public BooksController(IAmazonSimpleNotificationService client, ILogger<BooksController> logger, IMetricsLogger metrics)
    {
        ...
        _metrics = metrics;
    }
...
C#

Emissão de métricas específicas do negócio no código da aplicação:

private void EmitMetrics(Book book, string traceId, long processingTimeMilliseconds)
{
    //Add Dimensions
    var dimensionSet = new DimensionSet();
    //Unique Id for this WebAPI Instance
    dimensionSet.AddDimension("WebApiInstanceId", Environment.GetEnvironmentVariable("MY_SERVICES_INSTANCE"));
    //Book's Authors
    dimensionSet.AddDimension("Authors", string.Join(",", book.BookAuthors));
    //Book's Year
    dimensionSet.AddDimension("Year", $"{book.Year}");
    _metrics.SetDimensions(dimensionSet);

    _metrics.PutMetric("PublishedMessageCount", 1, Unit.COUNT);
    _metrics.PutMetric("ProcessingTime", processingTimeMilliseconds, Unit.MILLISECONDS);

    //Add some properties
    _metrics.PutProperty("TraceId", traceId);

    _logger.LogInformation("Flushing");
    _metrics.Flush();
}

Provisionando o agente CloudWatch para transmitir as métricas

Você deve instalar e configurar o agente CloudWatch para ingestão, análise e transmissão de logs EMF para o Amazon CloudWatch. A configuração do agente CloudWatch varia dependendo de como você hospeda sua aplicação .NET na AWS. Para obter informações sobre as diferentes opções de hospedagem e configuração do agente CloudWatch, leia o artigo Using the CloudWatch agent to send embedded metric format logs. Estou usando o Amazon ECS e o AWS Fargate para esta aplicação de exemplo. O exemplo de código a seguir mostra a implementação de um contêiner auxiliar do agente CloudWatch para um serviço do Amazon ECS usando o AWS Cloud Development Kit (AWS CDK) para implantar a infraestrutura como código. O AWS CDK permite que você construa aplicativos na nuvem, com o benefício do poder expressivo de linguagens de programação, como C#, usada aqui.

...
public static TaskDefinition AddCloudWatchAgent(this TaskDefinition taskDefinition, CloudWatchAgentProps agentProps)
{
    ...
    taskDefinition
        .AddContainer("cwagent", new ContainerDefinitionOptions
        {
            ...
            PortMappings = new PortMapping[]{
            new PortMapping{
                ContainerPort = 25888,
                Protocol = Amazon.CDK.AWS.ECS.Protocol.TCP
            },
            new PortMapping{
                ContainerPort = 25888,
                Protocol = Amazon.CDK.AWS.ECS.Protocol.UDP
            }},
            Image = ContainerImage.FromRegistry("public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest"),
            Environment = new Dictionary()
                {
                    { "CW_CONFIG_CONTENT", "{\"logs\":{\"metrics_collected\":{\"emf\":{}}}}" }
                },
            ...
        });

     //Grant permission to the cw agent 
    taskDefinition.TaskRole
        .AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("CloudWatchAgentServerPolicy"));

     return taskDefinition;
}
...

Implantar a solução de exemplo

O repositório contém a implementação completa desta solução, permitindo que você faça uma solicitação HTTP para a amostra da Web API para testá-la. Para implantar, execute um dos seguintes scripts de implantação em seu ambiente, usando bash (Linux ou Mac) ou PowerShell para implantar a solução.

Usando bash:

./deploy.sh

Usando PowerShell:

.\deploy.ps1

Após a implantação, copie a URL impressa pelo script de implantação. Ela tem o seguinte formato: http://WebAp-demos-XXXXXXXX-99999999.us-west-2.elb.amazonaws.com/api/Books. O X e o 9 devem ser caracteres alfanuméricos que representam o ID exclusivo de sua implantação. Em seguida, usando um cliente de API REST (como o Thunder Client para o VS Code), teste a solução enviando uma solicitação HTTP POST para a URL com a seguinte carga JSON. Quando você enviar o HTTP POST, deverá receber o status 200 e uma resposta indicando o resultado do TraceId.

{
    "Year" : 2022,
    "Title": "Demo book payload",
    "ISBN": 12345612,
    "Authors": ["Author1", "Author2"],
    "CoverPage": "picture1.jpg"
}
JSON

A Figura 2 ilustra a chamada de API de exemplo.

Example API call

Figure 2: Example API call

Visualizando os resultados

Após fazer uma solicitação de teste para a API, você pode navegar até o Amazon CloudWatch para revisar as métricas geradas.

  1. No console da AWS, navegue até o Amazon CloudWatch.
  2. No painel de navegação, escolha Métricas, Todas as métricas.
  3. Na guia Browse, o console exibe três tipos de métricas na seção Custom Namespaces (Figura 3).

Custom Metrics

Figura 3: Métricas do espaço de nomes personalizado

Os três tipos de métricas coletadas nesta solução são:

  1. ECS/ContainerInsights: Captura as métricas de infraestrutura de nuvem, que são métricas relacionadas a contêineres do Amazon ECS. Elas estão disponíveis porque eu habilitei o CloudWatch Container Insights.
  2. aws-embedded-metrics: Captura as métricas “específicas do negócio”, que são as métricas personalizadas implementadas no código da aplicação .NET para emitir dados relacionados à lógica do negócio.
  3. demo-web-api: Captura as métricas da aplicação web .NET Core. Elas são automaticamente instrumentadas para todas as solicitações e respostas HTTP dos microsserviços da API web.

ECS/ContainerInsights: Métricas de infraestrutura de nuvem do CloudWatch Container Insights

Essas são métricas de desempenho e saúde para a infraestrutura, exibindo informações como utilização de CPU, utilização de memória, rede e outros indicadores-chave de desempenho para a carga de trabalho do Amazon ECS. Você pode usá-las para gerar gráficos, painéis, alarmes ou solucionar problemas. Por exemplo, se a utilização de CPU ou memória aumentar repentinamente, isso pode indicar uma anomalia. Você pode definir limites para acionar alarmes em tais circunstâncias. O Amazon CloudWatch fornece um painel de desempenho pronto para uso para as métricas do Container Insights. Para visualizar este painel, como o mostrado na Figura 4, siga estas etapas:

  1. No console da AWS, navegue até o Amazon CloudWatch.
  2. No painel de navegação, escolha Container Insights em Insights.
  3. Altere a opção de Resources para Performance monitoring na lista suspensa na página.

Sample Container Insights dashboard

Figura 4: Exemplo de painel do Container Insights

aws-embedded-metrics: Métricas específicas do negócio

A Figura 5 é um exemplo de visualização de métricas “específicas do negócio”. Por exemplo, nos microsserviços do Serviço de Trabalhador, a aplicação rastreia métricas personalizadas definidas como “ProcessingTime”, que capturam o tempo de processamento de uma parte da lógica de negócio. O CloudWatch permite que você use métricas personalizadas para gerar gráficos, painéis ou alarmes. Você também pode usar as métricas para solucionar problemas do tempo que cada Serviço de Trabalhador levou para concluir o processamento. Para visualizar essa métrica no exemplo de aplicação, siga estas etapas:

  1. No console da AWS, navegue até o Amazon CloudWatch.
  2. No painel de navegação, escolha All metrics em Metrics.
  3. Na guia Browse, selecione aws-embedded-metrics e escolha a dimensão. O console deve listar as instâncias WorkerId e o Metric name.
  4. Escolha duas instâncias WorkerId diferentes para o mesmo “ProcessingTime”.
  5. Altere a lista suspensa no topo da página para Linha.
  6. Escolha as Opções. Na faixa do medidor, defina valores para Mínimo e Máximo.
  7. Defina os valores para porcentagens como Mínimo 0 e Máximo
  8. Painel de métricas aws-embedded

aws-embedded metrics dashboard

Figura 5: Painel de métricas aws-embedded

demo-web-api: Métricas de aplicação web .NET automaticamente instrumentadas

O Amazon CloudWatch também permite as mesmas capacidades para métricas relacionadas ao framework. Neste exemplo, o CloudWatch agrupa as métricas automaticamente instrumentadas para a API web ASP.NET 6.0 no namespace “demo-web-API”. Você pode usar as métricas relacionadas a solicitações/respostas HTTP para criar gráficos, painéis e alarmes ou solucionar problemas de tempo de resposta de cada ação do controlador de endpoint.

Para visualizar um gráfico de métricas como o mostrado na Figura 6, siga estas etapas:

  1. No console da AWS, navegue até o Amazon CloudWatch.
  2. No painel de navegação, escolha Todas as métricas em Métricas.
  3. Na guia Explorar, selecione demo-web-api e escolha a dimensão “Action, Controller, StatusCode”.
  4. Escolha as duas opções da lista para o mesmo nome de métrica “Time”.
  5. Altere a lista suspensa de Linha para Número no topo da página.

ASP.NET automatically instrumented methods

Figura 6: Métodos automaticamente instrumentados pelo ASP.NET

Limpeza

Para evitar cobranças inesperadas, você deve limpar os recursos criados ao executar esta demonstração. Para fazer isso, execute o script da pasta raiz onde você clonou o repositório do GitHub.

Usando bash:

./clean.sh

Usando PowerShell:

.\clean.ps1

Conclusão

Na primeira parte desta série de postagens no blog sobre a implementação de observabilidade em suas aplicações .NET na AWS, eu abordei como instrumentar suas aplicações .NET modernas para gerar pontos de dados no formato CloudWatch Embedded Metric (EMF). Também mostrei como o CloudWatch usa esses pontos de dados da sua aplicação para simplificar a solução de problemas ou visualizar a saúde da sua aplicação. Para saber mais sobre implementações de Logs ou Rastreamento Distribuído, leia as outras duas partes desta série, “Observabilidade do .NET com o Amazon CloudWatch e o AWS X-Ray: Parte 2 — Registro em log” e “NET com Amazon CloudWatch e AWS X-Ray: Parte 3 – Rastreamento distribuído“.

Observabilidade vai além de instrumentar sua aplicação .NET para gerar rastreamentos, logs e métricas. Você pode usar as capacidades do Amazon CloudWatch para monitoramento, alarmes ou detecção de anomalias. Consulte a página de Recursos do Amazon CloudWatch para saber mais. Para uma experiência mais prática, confira o Workshop de Observabilidade.

 

Este artigo foi traduzido do Blog da AWS em Inglês.


Sobre o autor

Ulili Nhaga é Cloud Application Architect na Amazon Web Services em San Diego, Califórnia. Ele ajuda os clientes a migrar, modernizar, arquitetar e criar aplicativos nativos de nuvem altamente escaláveis ​​na AWS. Fora do trabalho, Ulili adora jogar futebol, correr, andar de bicicleta, churrasco brasileiro e aproveitar o tempo na praia.

 

 

 

 

Revisores

Kevin Lira é um arquiteto de soluções sênior na AWS, trabalhando na indústria de FSI. Sua experiência profissional anterior inclui desenvolvimento de software, liderança técnica e arquitetura em outras indústrias. Bacharel em Sistemas de Informação e Especialista em Computação Flexível e Tecnologias Microsoft.

Me siga no LinkedIn: https://www.linkedin.com/in/kevinlira/

 

 

 

 

Leonardo Bonato Bizaro é consultor de Professional Services no time de ProServe LATAM. Presente desde 2022, vem abraçando a grande oportunidade recebida através da constante busca de experiência e aprendizado na AWS para crescimento e desenvolvimento profissional.