Pular para o conteúdo
fernando.moretes.com
BlogEstudosCursosE-booksOpen SourcePodcasts
Loading…
Fernando Azevedo

Arquiteto de TI Especialista

Arquitetura, AWS, IA em produção, sistemas financeiros e FinOps, escritos a partir do que foi operado, com os números.

  • LinkedIn
  • GitHub
  • E-mail

Conteúdo

  • Blog
  • Estudos de arquitetura
  • Cursos
  • E-books
  • Open Source
  • Podcasts
  • Assuntos
  • Trilhas

Ferramentas

  • Moretes Architect MCP
  • Well-Architected self-check
  • Arquitetura deste site
  • Números públicos
  • Histórico de estudo

Sobre

  • Comunidade
  • IA Builder
  • Perfil
  • Currículo (CV)
  • Trabalhe comigo
  • Media kit
  • RSS do blog
  • RSS dos estudos
  • Artigos narrados (podcast)
  • llms.txt
  • Termos, privacidade e uso de IA

(c) 2026 Fernando Francisco Azevedo

Blog/Artigo
RSSMarkdownLLMs
AWS & CloudAnatomia do Padrão

CloudWatch para OTel: Desmontando o Padrão de Bridge de Observabilidade

28 de mai. de 2026 7 minAvançado Com apoio de IA000 visualizações00 reproduções
Ouvir artigo

16:46 · voz do Fernando

Em ambientes financeiros onde times de plataforma precisam consolidar sinais de dezenas de workloads AWS em um backend de observabilidade unificado, seja Datadog, Grafana Cloud, Honeycomb ou um stack interno, o padrão de bridge CloudWatch → OpenTelemetry aparece como solução óbvia. Mas 'óbvio' e 'correto' raramente coincidem em arquitetura. Esse padrão tem uma anatomia específica, um envelope de validade estreito e modos de falha que só aparecem em produção sob carga real. Vou dissecar cada camada.

O Problema Real: Fragmentação de Observabilidade em Ambientes AWS-Native

Toda organização que cresce além de dois ou três times de engenharia enfrenta a mesma tensão: serviços AWS emitem métricas nativamente para o CloudWatch: Lambda, RDS, EKS, API Gateway, MSK, mas o backend de observabilidade corporativo fala OTLP. O resultado é um mundo partido: SREs precisam abrir dois consoles para correlacionar um incidente, alertas vivem em namespaces diferentes, e dashboards de negócio ficam impossíveis de construir sem ETL manual.

O padrão de bridge existe para resolver exatamente isso. A ideia central é simples: uma função Lambda (ou um coletor OTel rodando em ECS/EKS) subscreve streams de métricas do CloudWatch via CloudWatch Metric Streams ou polling da API GetMetricData, transforma o payload para o formato OTLP (OpenTelemetry Protocol), e o encaminha para um endpoint de coletor. Na teoria, você ganha um único plano de controle de observabilidade. Na prática, a complexidade se esconde nos detalhes.

O que torna esse problema especialmente traiçoeiro em ambientes financeiros é a combinação de três fatores: (1) volume de métricas, uma conta AWS de médio porte com EKS, RDS Multi-AZ e Lambda pode gerar facilmente 50.000+ séries de métricas por minuto; (2) latência de negócio: SLOs de detecção de anomalia exigem freshness de 60 segundos ou menos; (3) custo de API, cada chamada GetMetricData tem custo direto e quota de 50 métricas por request, o que significa que polling ingênuo em escala quebra tanto o orçamento quanto os rate limits da AWS.

Anatomia do Padrão CloudWatch → OTel Bridge

Fluxo completo desde a emissão de métricas pelos serviços AWS até o backend de observabilidade externo, passando pelos dois caminhos de ingestão (Metric Streams e polling) e os guardrails de segurança e custo.

🟧 AWS: Metric Sources
  • Lambda · Invocations/Errors/Duration
  • EKS / EC2 · CPU, Memory, Network
  • RDS / Aurora · DBConnections, Latency
  • API Gateway · 4xx/5xx, Latency
🟦 AWS: Ingestion Layer
  • CloudWatch · Namespaces
  • CW Metric Streams · ~2-3s latency, Firehose
  • Kinesis Firehose · JSON/OTel0.7 format
🟨 AWS: Transform & Forward
  • Bridge Lambda · OTLP transform + retry
  • SQS DLQ · failed batches
  • KMS CMK · payload encryption
🔵 External: Observability Backend
  • OTel Collector · OTLP/gRPC :4317
  • Datadog / Grafana · / Honeycomb

Anatomia do Padrão: Dois Caminhos, Um Trade-off Fundamental

O padrão tem dois sabores de ingestão, e a escolha entre eles define tudo que vem depois.

CloudWatch Metric Streams + Kinesis Firehose é o caminho de baixa latência. Streams entregam dados em formato OpenTelemetry 0.7 (protobuf) ou JSON com latência de 2–3 segundos. O custo é previsível: $0.003 por 1.000 atualizações de métrica. Para uma conta com 100k séries ativas, isso é aproximadamente $300/mês antes do custo do Firehose. A vantagem arquitetural crítica é que você não está fazendo polling, o dado flui, e a Lambda no destino do Firehose recebe batches, não chamadas individuais.

Polling via GetMetricData é o caminho de controle granular. Você escolhe exatamente quais métricas, com qual resolução e qual período de lookback. Mas a API tem quota de 50 métricas por request e 500 requests por segundo por conta (soft limit). Em uma conta grande, atingir esse limite é questão de minutos se o código de polling não implementar backoff exponencial com jitter e não batchear corretamente. Vi sistemas financeiros em produção quebrarem alertas críticos porque o poller entrou em throttling às 09:00 de uma segunda-feira, exatamente quando o mercado abre e o volume de transações explode.

A Lambda de transformação precisa de três capacidades não-negociáveis: (1) idempotência: Firehose pode re-entregar batches em caso de falha; a Lambda deve detectar duplicatas via hash do payload; (2) circuit breaker para o endpoint OTel externo, se o coletor estiver down, a Lambda não pode ficar em loop consumindo concorrência; (3) DLQ com alarme: batches que falham após 3 tentativas vão para SQS DLQ e um alarme CloudWatch deve disparar em menos de 5 minutos.

Quando Este Padrão Faz Sentido

Você tem um backend de observabilidade externo (Datadog, Grafana Cloud, Honeycomb) que fala OTLP e precisa de métricas de serviços AWS gerenciados que não têm agente instalável.
O volume de métricas justifica Metric Streams (>10k séries ativas), abaixo disso, o custo fixo do stream raramente se paga versus polling seletivo.
Seu SLO de freshness de métricas é ≤60 segundos: Metric Streams entrega em 2–3s; polling com intervalo de 1 minuto tem latência efetiva de até 90s.
A equipe de plataforma quer desacoplar o backend de observabilidade da AWS sem reescrever instrumentação de aplicação, o bridge é transparente para os times de produto.
Você precisa de correlação de traces e métricas em um único backend: OTel permite enriquecer métricas com resource attributes (account ID, cluster, service) que o CloudWatch nativo não propaga.

Segurança e Guardrails: O que os Tutoriais Não Contam

Em ambientes financeiros, o bridge de observabilidade é um vetor de exfiltração de dados subestimado. Métricas de negócio, volume de transações, latência de pagamentos, taxa de erros de autenticação, são informação sensível. Um endpoint OTel mal configurado pode vazar esses dados para fora da conta AWS sem nenhum alarme.

As três camadas de controle que implemento em todo deployment desse padrão:

IAM com condições de recurso: A role da Lambda deve ter permissão cloudwatch:GetMetricData e cloudwatch:ListMetrics com condição aws:ResourceTag/Environment: production, nunca um wildcard. Para Metric Streams, a role do Firehose precisa de cloudwatch:PutMetricStream e firehose:PutRecord, mas a role da Lambda de destino deve ser separada e ter apenas s3:GetObject no bucket de buffer (se usar S3 como fallback) e permissão de invocação.

KMS CMK para payload em trânsito: O Firehose deve ser configurado com ServerSideEncryption usando uma CMK gerenciada pelo time de segurança. A Lambda de transformação deve descriptografar com a mesma chave. Isso garante que mesmo um acesso não autorizado ao stream do Firehose não expõe dados legíveis.

VPC Endpoint para o coletor OTel: Se o coletor roda em ECS dentro da VPC, a Lambda deve estar na mesma VPC e usar DNS privado. Se o coletor é externo (SaaS), o tráfego deve sair por um NAT Gateway com IP fixo whitelistado no firewall do fornecedor, nunca por Internet Gateway sem controle de saída. Adicione um WAF rule no API Gateway se o coletor externo expõe um endpoint HTTP.

Um detalhe que queimou um cliente meu: a Lambda de bridge rodando com timeout de 15 minutos (máximo) e sem reserva de concorrência pode consumir todo o pool de concorrência da conta em um pico de ingestão, derrubando funções de negócio críticas. Reserve concorrência explícita, tipicamente 10–20 instâncias são suficientes para um Firehose com batch de 5MB.

Anti-Padrões: Quando Este Bridge Vai Explodir em Produção

  • Polling ingênuo sem backoff: Chamar GetMetricData em loop com intervalo fixo de 60s para centenas de namespaces. Em contas com muitos serviços, você atinge o rate limit em minutos e perde dados de observabilidade exatamente quando mais precisa, durante incidentes.
  • Lambda sem DLQ e sem alarme de erro: Falhas silenciosas de transformação ou export significam que métricas somem sem nenhum sinal. Em ambientes financeiros, isso pode mascarar degradação de serviço por horas.
  • Encaminhar todas as métricas de todos os namespaces: O CloudWatch tem mais de 200 namespaces. Encaminhar tudo para o backend externo multiplica o custo de ingestão do SaaS por 5–10x sem valor proporcional. Filtre por namespace e dimensão no próprio Metric Stream.
  • Sem idempotência na Lambda de transformação: Firehose garante entrega at-least-once. Sem deduplicação por hash do payload, você injeta séries duplicadas no backend OTel, corrompendo agregações e alertas baseados em soma/contagem.
  • Usar este padrão para traces e logs: O bridge CloudWatch → OTel é projetado para métricas. Tentar encaminhar CloudWatch Logs Insights ou X-Ray traces pelo mesmo canal cria um sistema frágil de propósito múltiplo. Use o OTel Collector diretamente nas aplicações para traces e logs.
  • Sem reserva de concorrência na Lambda: Em picos de ingestão (abertura de mercado, batch noturno), a Lambda de bridge pode esgotar o pool de concorrência da conta e throttlear funções de negócio críticas.

Design de Referência: O que Realmente Funciona em Produção Financeira

Depois de implementar e depurar esse padrão em três ambientes financeiros diferentes, o design que funciona tem estas características concretas:

Ingestão via Metric Streams com filtro de namespace: Configure o stream para incluir apenas os namespaces relevantes: AWS/Lambda, AWS/EKS, AWS/RDS, AWS/ApiGateway, AWS/MSK, e exclua explicitamente namespaces de custo alto e baixo valor como AWS/Billing e AWS/CloudFront (a menos que você monitore CDN). O formato deve ser opentelemetry0.7 (protobuf), não JSON, para reduzir o tamanho do payload em ~40%.

Firehose com buffer de 60s/5MB e S3 como fallback: Configure BufferingHints com IntervalInSeconds: 60 e SizeInMBs: 5. O S3 de fallback deve ter lifecycle policy para expirar objetos em 7 dias, ele existe apenas para replay manual em caso de falha do coletor externo, não como storage permanente.

Lambda de transformação em Python/Rust com SDK OTel: Use o opentelemetry-sdk para construir o payload OTLP. Adicione resource attributes fixos no momento da transformação: cloud.account.id, cloud.region, deployment.environment. Esses atributos permitem correlação cross-account no backend. O timeout deve ser 3 minutos (não 15), se a transformação de um batch leva mais de 3 minutos, há um problema de volume que precisa ser resolvido no filtro do stream, não no timeout.

Observabilidade do próprio bridge: Instrumente a Lambda com métricas customizadas: bridge.metrics.transformed.count, bridge.export.latency.p99, bridge.export.errors.count. Crie um dashboard CloudWatch para o bridge em si, é irônico mas necessário: você precisa observar o sistema de observabilidade. Defina um SLO de bridge.export.errors.count < 0.1% com alarme de 5 minutos de burn rate.

Números Reais de Produção

2–3s
Latência de Metric Streams
Da emissão no serviço AWS até o Firehose. Polling com 1min de intervalo tem latência efetiva de 60–90s.
~$0.30
Custo por 100k séries/mês
$0.003/1k updates × ~100k séries × ~1 update/min × 43.200 min/mês ≈ $13k/mês, filtre agressivamente.
50
Métricas por request na API GetMetricData
Quota hard. Com 500 req/s soft limit, polling de 25k métricas requer 500 requests, atinge o limite em 1 segundo.

Filtre no Stream, Não na Lambda

O CloudWatch Metric Stream suporta filtros por namespace e por dimensão. Use-os. Cada métrica que você não encaminha economiza custo de Firehose, custo de Lambda e custo de ingestão no backend externo. A Lambda de transformação deve ser burra e rápida, transformar formato, adicionar resource attributes e exportar. Lógica de filtragem na Lambda é um anti-padrão: você já pagou pelo dado ao chegar no Firehose.

Lentes Well-Architected para Este Padrão

Segurança

IAM com condições de tag de recurso, KMS CMK no Firehose, Lambda em VPC privada, egress controlado via NAT com IP fixo. A role da Lambda nunca deve ter cloudwatch:*, escopo mínimo por namespace.

Confiabilidade

DLQ no destino do Firehose, circuit breaker para o endpoint OTel externo, alarme de burn rate no SLO do bridge. Teste de falha do coletor externo deve ser parte do runbook de DR.

FA
Minha Nota de Curadoria
Arquiteto de TI Especialista

Implementei esse padrão pela primeira vez em 2022 em um ambiente de pagamentos e aprendi da forma difícil que o bridge de observabilidade precisa de observabilidade própria, parece óbvio, mas na prática é sempre o último item da lista. O que mais me preocupa nesse padrão não é a complexidade técnica, mas o falso senso de segurança que ele cria: times assumem que porque as métricas estão 'fluindo', a observabilidade está funcionando. Não está, até você ter SLOs de freshness, alarmes de erro no bridge e um runbook de falha do coletor externo. Em ambientes financeiros, eu sempre exijo que o time demonstre o que acontece quando o endpoint OTel externo fica indisponível por 10 minutos antes de ir para produção. A resposta a essa pergunta revela se o design tem guardrails reais ou apenas boa intenção.

Veredicto: Use com Cirurgia, Não com Entusiasmo

O padrão CloudWatch → OTel Bridge via Lambda e Metric Streams é tecnicamente sólido e resolve um problema real de fragmentação de observabilidade. Mas ele tem um custo operacional não trivial e um envelope de validade estreito. Use-o quando: (a) você tem >10k séries de métricas ativas de serviços AWS gerenciados que precisam estar em um backend OTLP externo; (b) seu SLO de freshness é ≤60 segundos; (c) a equipe de plataforma tem capacidade para operar e observar o próprio bridge. Não use quando: você está tentando consolidar traces e logs pelo mesmo canal; quando o volume não justifica o custo fixo do Metric Stream; ou quando não há maturidade operacional para manter um sistema que observa outros sistemas. O risco mais alto não é técnico, é organizacional: times que deployam esse padrão e depois não o monitoram criam um ponto cego de observabilidade disfarçado de solução de observabilidade.

Referências

CloudWatch Metric Streams: AWS DocumentationOpenTelemetry Collector: Official DocsKinesis Data Firehose Lambda TransformationGetMetricData API: Quotas and LimitsAWS Well-Architected Framework: Operational Excellence PillarOTLP Specification: OpenTelemetryObservability Engineering: Charity Majors, Liz Fong-Jones, George Miranda
#observability#opentelemetry#cloudwatch#lambda#otel-collector#financial-grade#platform-engineering#aws
Compartilhar:LinkedInWhatsAppXBaixar em Markdown
Fonte analisada: CloudWatch metrics to OTel collectors
Próximo passo
Trilha Arquiteto de IA, gratuitaFundamentos, LLMs, RAG, tools, MCP e arquitetura na AWS, em aulas curtas e interativas.Começar a trilhaAgentes de IA em produção na AWSComo eu desenho, oriento e audito agentes que vão ao ar, com os números e as fontes.Ver o IA Builder

Continue lendo

AWS & CloudCloudWatch Alarm Warm-Up: Fim do Ruído de Startup em Pipelines CI/CDO CloudWatch agora suporta períodos de warm-up para alarmes, resolvendo um problema clássico de ruído operacional em deploys automatizados. A feature parece simples, mas tem implicações sérias para SLOs, on-call fatigue e design de pipelines em ambientes financeiros. Neste artigo, analiso o mecanismo, os trade-offs reais e como integrar isso de forma responsável em stacks de produção.Ler AWS & CloudIngestão Gerenciada de Syslog no CloudWatch: Anatomia de um PadrãoO CloudWatch Logs agora aceita syslog diretamente via endpoint de VPC, sem agentes, com parsing automático de RFC 5424, RFC 3164 e Cisco FTD/ASA. Isso muda o padrão de coleta de logs para dispositivos de rede e servidores Linux em ambientes regulados. Neste artigo, desmonto a anatomia do padrão, seus limites reais e os anti-padrões que já vi queimar equipes em produção.Ler AWS & CloudStreaming de Respostas com Lambda: Precificação em Tempo RealLambda response streaming muda fundamentalmente o contrato de execução serverless ao permitir que bytes sejam enviados ao cliente antes que a função termine, o que tem implicações profundas para motores de precificação em tempo real. Nesta análise, desmonto o mecanismo interno, os modos de falha que a documentação não enfatiza, e as decisões de arquitetura que separam um protótipo de um sistema financeiro em produção.Ler
AnteriorMigração para Plataformas Stateful Cloud Native no AWS EKSPróximoRAG Agêntico com OpenSearch Serverless: Anatomia de um Padrão
Gostou desta análise? Receba a próxima.

Deep dives de arquitetura, AWS, IA e mercado: direto no seu email. Grátis.

Sem spam · cancele quando quiser

Pergunte ao Fernando sobre isto

Uma resposta focada sobre este artigo, do meu assistente de IA, baseada no meu trabalho.

Participe da conversa

Entre para comentar

Confirme seu e-mail para participar, você também recebe a newsletter. Sem senha.

Neste artigo
O Problema Real: Fragmentação de Observabilidade em Ambientes AWS-NativeArquiteturaAnatomia do Padrão: Dois Caminhos, Um Trade-off FundamentalSegurança e Guardrails: O que os Tutoriais Não ContamAntipadrõesDesign de Referência: O que Realmente Funciona em Produção FinanceiraWell-ArchitectedVeredicto: Use com Cirurgia, Não com EntusiasmoReferências