BK cloud / sistemas Artigos
PT-BR
English ENDeutsch DEEspañol ES中文 ZHFrançais FRPortuguês (Brasil) PT-BR日本語 JA
Vamos conversar ↗
← Voltar aos artigos

Um site estático com pulso: estatísticas de acesso na AWS com cuidado com a privacidade

Um site estático é agradavelmente tranquilo. Não há servidor de aplicação esperando atualização, pool de conexões com banco para esgotar nem API pública que precise funcionar sem parar. O navegador pede arquivos; uma rede de distribuição de conteúdo os entrega.

Essa simplicidade trouxe uma pergunta interessante para o portfólio: seria possível mostrar de onde vêm os acessos e como o tráfego muda ao longo do tempo sem tornar o site dinâmico nem publicar o que deveria ficar privado?

A resposta foi um pequeno fluxo de dados com logs de acesso do CloudFront, CloudWatch, Lambda, EventBridge e um único objeto JSON no S3. Quem acessa vê um mapa, totais por país, páginas populares e gráficos de requisições. Não recebe logs brutos, IPs, user agents nem históricos individuais de navegação.

O site continua estático. Os dados são preparados em outro lugar e chegam como mais um arquivo.

A arquitetura no caminho de uma requisição

O caminho público foi mantido curto de propósito:

  1. Uma pessoa acessa o site pelo Amazon CloudFront.
  2. O CloudFront entrega arquivos em cache, cuja origem privada é um bucket S3.
  3. Depois, o navegador busca content/public-visitors.json como qualquer outro arquivo estático.
  4. O JavaScript no navegador desenha o mapa e os gráficos a partir desse documento anônimo.

O navegador não chama Lambda, não consulta CloudWatch e não tem credenciais AWS. Também não pode pedir outro intervalo nem um registro mais detalhado. Todo o trabalho caro ou sensível acontece fora do caminho público das requisições.

Nos bastidores, os dados seguem este caminho:

CloudFront → CloudWatch Logs → scheduled Lambda → aggregated JSON → S3 → CloudFront → browser

Essa separação é a decisão central da arquitetura. O sistema operacional pode lidar com registros detalhados de acesso; a publicação libera apenas o pequeno subconjunto destinado à exibição pública.

Coletar uma vez, publicar menos

O logging padrão v2 do CloudFront entrega campos selecionados a um grupo do CloudWatch Logs. O log operacional tem informação suficiente para investigar requisições e códigos de status. Isso não significa que tudo deva aparecer num painel público.

A função de publicação reduz os dados a agregados de propósito:

  • visualizações HTML bem-sucedidas agrupadas por código de país;
  • os caminhos HTML mais acessados;
  • requisições por minuto calculadas a partir de métricas agregadas de status HTTP;
  • horário da atualização e rótulos dos intervalos.

O arquivo gerado não contém IPs de origem, localização por cidade, cookies, user agents nem sequências que identifiquem a navegação de alguém. O resultado público responde “que tráfego o site recebeu?”, não “quem visitou?”.

É por isso que uso a expressão visualizações de página, e não pessoas. Um leitor pode gerar muitas requisições. Robôs de busca, serviços de prévia de links, verificações de monitoramento e outras automações aparecem junto com o tráfego humano. O painel mostra sinais da infraestrutura, não identidades.

Por que o CloudWatch fica no meio

O CloudWatch oferece duas representações úteis da mesma atividade. O Logs Insights consulta registros estruturados para agregar páginas e países. Filtros de métrica contam as famílias HTTP 2xx, 3xx, 4xx e 5xx, permitindo gerar séries de requisições sem reprocessar todos os eventos de log a cada consulta.

O conjunto público oferece várias visões:

  • totais por país das últimas 24 horas, 7 dias e 30 dias;
  • taxa de requisições para 24 horas, 7 dias, 30 dias e 12 meses;
  • intervalos de agregação maiores nos períodos longos, para manter o documento compacto.

Os logs do CloudFront não são um fluxo em tempo real. Segundo a AWS, os logs padrão costumam chegar em até uma hora, mas alguns registros podem atrasar mais. Servem bem para um painel retrospectivo honesto, não para um contador de visitantes ao vivo.

Um retrato agendado no lugar de uma API pública

Uma regra do EventBridge chama a Lambda de publicação a cada seis horas. A função executa consultas delimitadas, busca as séries de métricas, monta o documento e sobrescreve uma única chave S3: content/public-visitors.json.

Seis horas é um intervalo conservador de propósito. Estatísticas de acesso não precisam mudar a cada segundo, e cada atualização consulta logs. Reduzir o intervalo geraria mais consultas e custo, sem tornar a página muito mais útil.

O objeto JSON é entregue com cabeçalhos de cache voltados à revalidação. Assim, a página inicial encontra uma versão nova enquanto o CloudFront continua protegendo a origem S3. Atualizar estatísticas não exige um deploy completo nem uma invalidação global de cache.

Esse modelo tem uma forma conveniente de falhar. Se uma consulta ou execução da Lambda não funcionar, o documento estático anterior continua disponível. O painel pode ficar desatualizado, mas o portfólio segue no ar, sem requisições esperando pelo processo de estatísticas.

Privilégio mínimo reduz o alcance de uma falha

A Lambda de publicação usa uma role IAM dedicada. As permissões relevantes são restritas de propósito:

  • executar e buscar resultados de consultas apenas no grupo de logs designado;
  • ler as métricas do CloudWatch necessárias ao gráfico de requisições;
  • gravar apenas content/public-visitors.json no bucket do site;
  • gravar os próprios logs de execução.

Ela não pode publicar arquivos arbitrários, alterar a distribuição CloudFront nem expor o bucket S3. O EventBridge só pode chamar essa função específica a partir da regra agendada específica.

O bucket do site permanece privado. O CloudFront usa Origin Access Control para assinar as requisições ao S3, impedindo que usuários contornem a distribuição e usem o bucket como servidor público de arquivos.

O mapa público é menos preciso de propósito

Mais detalhes não tornam um painel público automaticamente melhor. Marcadores por cidade impressionam, mas números pequenos combinados com horário preciso e uma pessoa conhecida podem permitir identificação. Totais por país contam a dimensão global do site sem sugerir que a telemetria revela onde um leitor específico mora.

O visual reforça esse limite: o mapa mostra intensidade por país e um ranking, com uma explicação logo abaixo de que requisições são sinais, não pessoas. A interface não permite abrir eventos individuais.

Essa distinção importa porque gráficos bem acabados podem transmitir uma certeza falsa. O país derivado de um IP é uma observação da plataforma de borda. VPNs, redes corporativas, operadoras móveis, robôs e prévias em cache tornam a interpretação humana mais complicada.

O custo depende do volume consultado, não do visual

Mapa e gráficos são desenhados no navegador com código já entregue pelo site estático. A complexidade visual não gera uma conta de renderização no servidor. O custo operacional relevante vem de coletar e reter logs, ingerir métricas e consultar os registros periodicamente.

Por isso, os controles estão na arquitetura:

  • retenção de logs de 30 dias para evitar crescimento indefinido;
  • apenas quatro execuções diárias da função;
  • consultas com janelas delimitadas e só os campos necessários;
  • períodos de métrica maiores nos gráficos de longo prazo;
  • JSON publicado muito menor que os logs de origem.

Nesse porte, o tempo de Lambda e o armazenamento de um documento compacto no S3 são mínimos. Se tráfego ou retenção crescerem muito, vale acompanhar o volume lido pelo Logs Insights.

O que aprendi com a implementação

Estático não significa sem visibilidade. A observabilidade pode existir ao lado de um site estático, sem entrar no caminho síncrono das requisições.

A agregação é uma barreira de segurança. A passagem dos logs operacionais para um documento público deve ser explícita, revisada e em um só sentido.

Atualizado o suficiente é melhor que um falso tempo real. Um retrato a cada seis horas combina com o atraso dos logs padrão e evita trabalho desnecessário.

Uma falha deve preservar o último estado conhecido. Um retrato antigo é melhor que uma página inicial que para porque o serviço de estatísticas caiu.

Explique os limites perto do gráfico. Uma visualização pública precisa contextualizar robôs, acessos repetidos, inferência geográfica e a diferença entre tráfego e pessoas.

Quando eu escolheria outro desenho

Esse padrão funciona para um site pessoal de tráfego moderado e poucas visões predefinidas. Eu o repensaria se fosse preciso oferecer consultas livres, painéis autenticados, atualização a cada segundo ou grandes conjuntos multidimensionais. Aí uma API, uma base analítica dedicada ou uma plataforma de visualização poderiam fazer sentido.

Neste portfólio, isso resolveria um problema que não tenho. Uma função agendada e um documento estático preservam as vantagens originais: superfície de ataque pequena, comportamento previsível e componentes fáceis de entender.

O aprendizado que ficou

A parte mais importante deste painel não é o mapa. É a separação por trás dele.

Os registros detalhados ficam no ambiente operacional. Um processo com privilégio mínimo os transforma periodicamente em agregados anônimos. O site recebe apenas um retrato compacto, e o navegador o transforma em informação visual.

Assim, o site ganha pulso sem depender de um coração dinâmico vulnerável.

Referências