Executando verificação de segurança...
2

Estratégias de monitoramento de aplicações back/end e front/end

Um tweet me deu a ideia sobre essa publicação e acabei pensando o quanto essa discussão pode ser interessante. Vou compartilhar algumas estratégias que utilizo e seria ótimo se pudessem contribuir com as que cada um vocês utilizam no dia a dia!

Um disclaimer antes de qualquer coisa, não sou adepto a soluções cloud. Trabalhei por muito tempo com bare metal, infra prória, VPS e VM. Por tanto, costumo configurar todo o setup da infra-estrutura antes de iniciar as aplicações. Significa também que algumas estratégias podem não ser aplicáveis para todo mundo.

Back/end

Uma das coisas que quero monitorar no back-end são sempre: eventos críticos e eventos sensíveis.

  • Os eventos críticos se relacionam a (1) erros não tratados e (2) erros tratados porém que afetam a estabilidade da aplicação. Por exemplo, um bug inesperado que não foi detectado antes, um vício oculto da aplicação que promove uma exceção ou erros de comunicação com serviços de terceiro, etc;
  • Os eventos sensíveis se relacionam a (1) segurança e (2) abusos por parte do usuário. Por exemplo, tentativas de acesso não autorizado, exploração indevida de endpoints, tentativa de comprometer a estabilidade da aplicação, etc;

Para monitorar esses eventos, coloco eles em uma fila. Aqui não tem muita firula, pode ser utilizando o próprio Redis com escrita/leitura de payloads que sintetizam os eventos e sua mensagem ou, dependendo do volume de eventos, o RabbitMQ ou qualquer similar.

Não gosto de prender a requisição do usuário, por isso disparo o evento e deixo um processamento em background lidar com ele. Somente em caso de falha desse disparo, aí não tem outra, vai para um log de arquivos de erro, o famoso error.log. Para tratar esses eventos:

  • Leio a mensagem e pela categoria do evento que eu quero inspecionar, envio prioritariamente para o Telegram com redundância para o Discorde. Prefiro mandar para o Telegram que acho que as notificações são mais rápidas e simples de ver do que qualquer outra. O Discord depois de um tempo adormece e o Telegram não. Como serviços de mensagens é onde mais estou por conta de clientes, também faz sentido;
  • Todos os eventos sensíveis, mesmo que eu tenha enviado para o Telegram, adiciono uma mensagem formatada em um arquivo de log chamado security.log. Faço isso, porque do lado do servidor eu configuro duas ferramentas para lidar com esse arquivo:
    • A primeira delas é o LogRotate (aplico em qualquer arquivo de log) para rotacionar o arquivo e não permitir que o arquivo fico enorme ao ponto de causar qualquer lentidão. Então ele vai criando novo arquivo e os antigos passam a ficar com a extensão numérica (.1, .2, etc);
    • A segunda é o Fail2Ban. Como são eventos sensíveis que geralmente podem indicar brechas de segurança, abuso ou ataque de DDoS, o Fail2Ban é responsável banir aquele IP de usuário por um tempo determinado fechando o Firewall interno e, dependendo da onde estou, enviando para o Firewall do host ou Cloudflare para bloquear na primeira ponta. O funcionamento dele é simples, a partir de um REGEX, ele lê os arquivos de log alvo (security.log), detecta o padrão conforme as regras que eu crio e se o padrão for identificado ele dispara o evento para bloquear o IP.
  • Quando o serviço é extremamente crítico ou está em uma versão instável (alpha, beta ou similar), prefiro ter uma dashboard de visualização de logs ao invés de ter que ficar entrando no Servidor toda hora. Nesse caso, uso o Logtail da BetterStack. A versão gratuita permite 3 dias de registro de log, o que é mais suficiente para o tipo de serviço. A partir da ferramenta, consigo ter uma visualização completa tanto do log, quanto sobre o contexto que disparou ele e muito mais;
  • Independente do que estou fazendo no sistema, eu crio um endpoint privado com Basic Authentication apenas para trazer um estado de saúde de todos os serviços externos que utilizo. Então ele basicamente retorna um payload em JSON, contendo o ID do serviço e um booleano indicado se está online. Exemplo: { "mysql": true }. Se todos os serviços que dependo estão online retorno um HTTP 200 do contrário retorno 503;
    • Caso eu esteja utilizando a BetterStack configuro um Uptime Checker para fazer a verificação desse endpoint a cada 5 minutos (ou menos) e me avisar caso dê algum problema para chamar esse endpoint ou o tempo de resposta ultrapasse o máximo desejado;
    • Porém, se não estiver usando a BetterStack no projeto, utilizo o Uptime Kuma (open source) para fazer a mesma coisa e no fim receber no Telegram a notificação de indisponibilidade.
  • No nível do sistema operacional, configuro os eventos críticos do sistema e inspetores que logs (que ficam observando MySQL, Redis, etc) para enviar notificações também quando eles acontecem. Por vezes, por exemplo, o log do MySQL avisa antes de um problema que a aplicação irá enfrentar, então é uma contingência. Fácil de configurar, então não faz sentido deixar de lado;
  • Quando a aplicação é crítica mesmo e precisa de monitoramento, coloco monitores de processo, CPU e memória ram para dispararem notificações. E quando há necessidade de ver em tempo real, vejo na plataforma onde o servidor está hospedado ou, em último caso, instalado o Netdata para ter acesso a dashboard completa de todos os processos que estão rodando na máquina.

A maioria dessas implementações já tenho o boilerplate, logo o esforço de implementar é zero e tem funcionado. Dão uma visão geral do sistema e permitem que eu fique ligado somente e quando realmente for necessário. Evito ao máximo depender de ficar entrando em dashboard ou qualquer interface para ficar vendo o estado da aplicação, etc. Tudo que posso, aposto em notificações para tomar a ação quando necessário.

Front/end

Do lado do usuário, meu monitoramento é baseado em comportamento. Preciso saber se o sistema está operacional para o usuário e ele está conseguindo realizar as operações que ele precisa fazer.

  • Em relação a análise de comportamento vario entre GA4 e Matomo. Hoje estou preferindo o Matomo porque ele não é orientado a eventos como o GA4, então ele permite que eu tenha uma visualização mais rápida do comportamento do usuário. Para tirar o maior proveito aqui, configuro micro-eventos de interação com o Google Tag Manager com a finalidade de saber o botão que a pessoa clicou, quantas vezes foi clicado e quando ela parou em uma seção alvo, quanto dá página ela “leu” pelo scroll, etc;
  • Outra coisa que costumo usar é o Clarity. Ele permite que eu assista o comportamento “real” dos usuários na página. Ajuda a achar gaps e problemas de experiência, até auxiliar em um suporte ao usuário. Já encontrei muito bug oculto por causa do Clarity, aquele que não produz erro, mas o usuário consegue executar mesmo assim. Mas, configuro no Google Tag Manager apenas para uma amostragem das requisições. Isso porque ele costuma deixar o carregamento da página muito lento em celulares/4G, comprometendo muito a performance de resultados com anúncios, por exemplo;
  • Por fim, uso a Logtail do BetterStack para monitorar exceções não tratadas ou eventos específicos que espero obter algum insight a partir deles;
  • As demais regras do back-end também se aplicam: monitoramento de log de acesso do nGINX (ou Apache); rotacionamento de log de acesso; inspeção com Fail2Ban; uptime na página inicial, etc.

E vocês, o que costumam fazer?

Carregando publicação patrocinada...
1

Muito bom! Não conhecia essas ferramentas.
Já implementei o Clarity no sistema depois de conhece-lo por aqui e já esta sendo bem útil.
Uma dúvida, como você trabalha com o modo mascaramento? Deixa rigoroso, equilibrado ou relaxado?

Obrigado e parabéns pelo post!

1

Acredito que dependa da sua finalidade 🤔 a minha é apenas para fins de observação de experiência e otimização de conversão, então removo qualquer dado relacionado ao usuário.

Costumo trabalhar com o modo equilibrado e adicionar no código o seletor CSS c-hidden (coloco essa classe no elemento, principalmente em área de login) para as informações que eu quero censurar, além de censurar todos os inputs.