O blog da AWS

Observabilidade do .NET com o Amazon CloudWatch e o AWS X-Ray: Parte 2 — Registro em log

Por Ulili Nhaga

 

Construir uma aplicação .NET bem arquitetad a vai além de apenas codificar e implantar. É necessário monitorar o desempenho, rastrear transações, coletar logs, reunir métricas e acionar alarmes quando as métricas ultrapassam os limites. Para alcançar isso, você pode projetar e implementar telemetria para habilitar recursos de observabilidade.Na primeira parte desta série de blogs, abordei a implementação de métricas. Neste segundo post, abordarei a implementação de log em aplicações .NET usando o log .NET C#  com o Amazon CloudWatch Logs e, em seguida, mostrarei como correlacionar esses logs com métricas e rastreamentos distribuídos usando o Amazon CloudWatch e  o AWS X-Ray.O registro em log é um recurso de observabilidade fundamental. Ele permite capturar pontos de dados em tempo de execução para que você possa filtrá-los, transmiti-los e armazená-los para fins de análise ou solução de problemas adicionais. O registro em log também ajuda a depurar erros, monitorar o desempenho, rastrear o comportamento do usuário, rastrear transações e muito mais.

Visão geral da solução

Considere uma carga de trabalho .NET em contêineres, como a da Figura 1, que é executada no  Amazon Elastic Container Service (Amazon ECS) com o AWS Fargate. Ela é composta por três microsserviços .NET: uma API Web do ASP.NET Core, dois Worker Services, além dos recursos de nuvem que eles usam. Um sistema ou plataforma em um cenário real de produção pode ter dezenas, centenas ou até milhares desses microsserviços. Se você tivesse que solucionar problemas de vários microsserviços, isso poderia ser demorado ou quase impossível se você não tivesse o log implementado em cada microsserviço.

Para mitigar esse cenário, você pode emitir logs nas etapas-chave de cada componente para incluir pontos de dados relevantes que ajudem a entender o que está ocorrendo durante o processamento. No entanto, se os logs estiverem todos isolados uns dos outros, eles podem não ajudar a identificar rapidamente a causa raiz. Portanto, processá-los em um sistema centralizado que possa correlacioná-los com outros datapoints, como métricas e rastreamentos distribuídos, ajudará.

Embora possa ser um desafio implementar todos os componentes de observabilidade e processá-los de forma centralizada, o Amazon CloudWatch e o AWS X-Ray podem ajudá-lo a enfrentar esse desafio. Neste post, mostrarei como implementar o log em C# do .NET com o CloudWatch Logs e instrumentar os logs com informações do AWS X-Ray Trace para que o Amazon CloudWatch possa correlacionar os logs com outros componentes de observabilidade.

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

Você pode clonar o repositório a partir da 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 o logging com CloudWatch Logs em uma aplicação .NET

O .NET C# oferece suporte a uma especificação de API de log  com vários provedores de log internos e de terceiros. Uma prática recomendada para melhor filtragem e correlação é usar um provedor que gera saídas JSON. O formato JSON ajuda na análise, filtragem e visualização.

Para melhorar a experiência de solução de problemas, você pode adicionar o ID de rastreamento do AWS X-Ray em cada saída de log. Em seguida, o CloudWatch pode correlacionar todos os pontos de dados com essa mesma ID de rastreamento. Esses pontos de dados podem ser métricas, logs e rastreamentos distribuídos. A inclusão do ID de rastreamento em cada saída de log ajuda a simplificar o processo de solução de problemas, permitindo que você filtre e se concentre nos logs que têm o mesmo ID de rastreamento de diferentes componentes da sua carga de trabalho. Ele também permite que você expanda a exibição para mostrar métricas individuais e rastreamentos distribuídos para obter as informações necessárias para ajudar na solução de problemas.

O exemplo de código a seguir demonstra uma implementação de log usando o provedor C# interno em uma das aplicações de serviços de trabalho para adicionar o ID de rastreamento em cada log:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    ...
    while (!stoppingToken.IsCancellationRequested)
    {
        ...
        try
        {
            var messageId = await ReceiveAndDeleteMessage(_sqsClient, queueUrl);
            _logger.LogInformation("Message ID: {messageId}, TraceId: {TraceId}", messageId, traceEntity.TraceId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "error consuming SQS Queue");
            AWSXRayRecorder.Instance.AddException(ex);
        }
        finally
        {
            var traceEntity = AWSXRayRecorder.Instance.TraceContext.GetEntity();
            AWSXRayRecorder.Instance.EndSegment();
            AWSXRayRecorder.Instance.Emitter.Send(traceEntity);
            _logger.LogDebug("Trace sent {TraceId}", traceEntity.TraceId);
        }
       ...
    }
}

Para evitar a repetição da mesma parte do código em cada chamada de log, o .NET permite a implementação de um provedor ou formatador de log personalizado  no qual você adiciona a lógica de ID de rastreamento uma vez e, em seguida, ela é usada toda vez que um código de aplicação invoca métodos de log. A seguir está o código de exemplo que implementa um formatador de log personalizado:

public class XrayCustomFormatter : ConsoleFormatter, IDisposable
{
    ...
    public override void Write<TState>(
        in LogEntry<TState> logEntry,
        IExternalScopeProvider scopeProvider,
        TextWriter textWriter)
    {
        ...
        WriteTraceIdSuffix(textWriter);
        ...
    }

    private void WriteTraceIdSuffix(TextWriter textWriter)
    {
        if (_formatterOptions.EnableTraceIdInjection && AWSXRayRecorder.Instance.IsEntityPresent())
        {
            textWriter.Write($"TraceId: {AWSXRayRecorder.Instance?.GetEntity()?.TraceId}");
        }
    }
    ...
}

Enviar os logs para o CloudWatch Logs

Você deve usar um processo separado para lidar com a transmissão do log para o CloudWatch Logs para que a lógica de processamento de log não afete o desempenho da aplicação. O mecanismo de transmissão de logs varia, dependendo de quais serviços da AWS você está usando para hospedar seu aplicativo .NET. Aqui estão algumas opções:

Como estou usando o Amazon ECS e o AWS Fargate para essa aplicação de exemplo, o exemplo de código a seguir mostra como provisionar o driver de log do Amazon ECS usando o AWS CDK. O AWS CDK permite que você crie aplicações na nuvem como código, com o benefício do poder expressivo das linguagens de programação, como o C#, que estou usando aqui:

//CloudWatch LogGroup and ECS LogDriver
var logGroupName = "/ecs/demo/ecs-fargate-dotnet-microservices";
var logDriver = LogDriver.AwsLogs(new AwsLogDriverProps
{
    LogGroup = new LogGroup(this, "demo-log-group", new LogGroupProps
    {
        LogGroupName = logGroupName,
        Retention = RetentionDays.ONE_DAY,
        RemovalPolicy = cleanUpRemovePolicy
    }),
    StreamPrefix = "ecs/web-api"
});

 var albFargateSvc = new ApplicationLoadBalancedFargateService(this, "demo-service", new ApplicationLoadBalancedFargateServiceProps
{
    ...
    TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions
    {
       ...
        LogDriver = logDriver,
    },
});
C#

Implantar a solução de exemplo

O repositório contém a implementação completa dessa solução, permitindo que você faça uma solicitação HTTP à API Web de exemplo 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 o PowerShell:

.\deploy.ps1

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

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

A Figura 2 ilustra a chamada de API de exemplo.
Example API call

Figura 2: Exemplo de chamada de API

Visualizando os resultados

Depois de fazer uma solicitação de teste para a API, você pode navegar até o Amazon CloudWatch para revisar os logs gerados.

  1. No console da AWS, navegue até o Amazon CloudWatch.
  2. No painel de navegação, escolha X-Ray Trace, Traces.
  3. Deixe o campo Filtrar por Grupo X-Ray em branco, insira o ID de rastreamento que você copiou no campo seguinte e escolha Executar consulta.

O console apresentará uma página semelhante à Figura 3.  O CloudWatch correlaciona todos os pontos de dados de diferentes microsserviços com o ID de rastreamento e os exibe nesta página. A página exibe:

  • Um mapa de rastreamento distribuído.
  • Métricas para segmentos com uma linha do tempo de todos os microsserviços e componentes que processaram a solicitação, incluindo a duração e o status de cada um.
  • Os logs dos serviços associados à ID de rastreamento. Você pode analisar os dados com consultas mais avançadas ao escolher Exibir no CloudWatch Logs Insights.

Logs filtered by trace IDFigura 3: Logs filtrados por ID de rastreamento

Limpeza

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

Usando bash:

./clean.sh

Usando o PowerShell:

.\clean.ps1

Conclusão

No segundo post desta série de postagens de blog sobre a implementação da observabilidade para suas aplicações .NET na AWS, abordei como implementar o uso de log. NET C# com CloudWatch Logs, e demonstrei como você pode usar o ID de rastreamento do  AWS X-Ray para habilitar o Amazon CloudWatch e o AWS X-Ray para simplificar a solução de problemas e a visualização da integridade da sua aplicação. Para saber mais sobre métricas ou implementações de rastreamento distribuído, leia as outras duas partes desta série, “.NET – observabilidade com Amazon CloudWatch e AWS X-Ray: Parte 1 — Métricas” e “NET com Amazon CloudWatch e AWS X-Ray: Parte 3 – Rastreamento distribuído“.

A observabilidade vai além de instrumentar sua aplicação .NET para gerar rastreamentos, logs e métricas. Você pode aproveitar os recursos do CloudWatch para monitoramento, alarmes, detecção de anomalias e muito mais. Consulte a página Recursos do Amazon CloudWatch para saber mais e, para experiência prática, confira o One Observability Workshop.

 

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.