Cloud & Infraestrutura

OpenTelemetry com AWS Distro: Observabilidade Portável na AWS na Prática

7 min de leitura

OpenTelemetry com AWS Distro: Observabilidade Portável na AWS na Prática

O que é OpenTelemetry e por que usar com AWS Distro OpenTelemetry é um padrão aberto e agnóstico de fornecedor para coleta de telemetria (traces, métricas e logs). O AWS Distro for OpenTelemetry (ADOT) é a distribuição mantida pela Amazon com componentes otimizados nativamente para a plataforma AWS. A grande vantagem é a portabilidade: você escreve uma única instrumentação que funciona em qualquer lugar — desenvolvimento local, Kubernetes, Lambda, EC2 — sem lock-in de vendor. Com ADOT, você ativa observabilidade sem reescrever código quando migra entre ambientes. A arquitetura segue um padrão simples: sua aplicação envia telemetria para um coletor local (ou remoto), que processa, enriquece e exporta para backends AWS como X-Ray, CloudWatch e Prometheus. Isso reduz complexidade e custos comparado a múltiplas SDKs proprietárias. Instrumentação Prática com Node.js Instalação e configuração básica Comece instalando as dependências essenciais para Node.js. O pacote principal fornece a API, enquanto os instrumentos detectam automaticamente bibliotecas populares como Express, HTTP e banco de

<h2>O que é OpenTelemetry e por que usar com AWS Distro</h2>

<p>OpenTelemetry é um padrão aberto e agnóstico de fornecedor para coleta de telemetria (traces, métricas e logs). O AWS Distro for OpenTelemetry (ADOT) é a distribuição mantida pela Amazon com componentes otimizados nativamente para a plataforma AWS. A grande vantagem é a portabilidade: você escreve uma única instrumentação que funciona em qualquer lugar — desenvolvimento local, Kubernetes, Lambda, EC2 — sem lock-in de vendor. Com ADOT, você ativa observabilidade sem reescrever código quando migra entre ambientes.</p>

<p>A arquitetura segue um padrão simples: sua aplicação envia telemetria para um coletor local (ou remoto), que processa, enriquece e exporta para backends AWS como X-Ray, CloudWatch e Prometheus. Isso reduz complexidade e custos comparado a múltiplas SDKs proprietárias.</p>

<h2>Instrumentação Prática com Node.js</h2>

<h3>Instalação e configuração básica</h3>

<p>Comece instalando as dependências essenciais para Node.js. O pacote principal fornece a API, enquanto os instrumentos detectam automaticamente bibliotecas populares como Express, HTTP e banco de dados.</p>

<pre><code class="language-bash">npm install @opentelemetry/api \

@opentelemetry/sdk-node \

@opentelemetry/auto-instrumentations-node \

@opentelemetry/exporter-trace-otlp-http \

@opentelemetry/sdk-trace-node \

@opentelemetry/resources \

@opentelemetry/semantic-conventions</code></pre>

<p>Crie um arquivo <code>instrumentation.js</code> que deve ser carregado <strong>antes</strong> de qualquer outro código:</p>

<pre><code class="language-javascript">const { NodeSDK } = require(&#039;@opentelemetry/sdk-node&#039;);

const { getNodeAutoInstrumentations } = require(&#039;@opentelemetry/auto-instrumentations-node&#039;);

const { OTLPTraceExporter } = require(&#039;@opentelemetry/exporter-trace-otlp-http&#039;);

const { Resource } = require(&#039;@opentelemetry/resources&#039;);

const { SemanticResourceAttributes } = require(&#039;@opentelemetry/semantic-conventions&#039;);

const resource = Resource.default().merge(

new Resource({

[SemanticResourceAttributes.SERVICE_NAME]: &#039;minha-app&#039;,

[SemanticResourceAttributes.SERVICE_VERSION]: &#039;1.0.0&#039;,

environment: &#039;production&#039;

})

);

const traceExporter = new OTLPTraceExporter({

url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || &#039;http://localhost:4317&#039;

});

const sdk = new NodeSDK({

resource,

traceExporter,

instrumentations: [getNodeAutoInstrumentations()]

});

sdk.start();

console.log(&#039;OpenTelemetry iniciado&#039;);

process.on(&#039;SIGTERM&#039;, () =&gt; {

sdk.shutdown()

.then(() =&gt; process.exit(0))

.catch(err =&gt; process.exit(1));

});</code></pre>

<p>Execute sua aplicação com este arquivo carregado primeiro:</p>

<pre><code class="language-bash">node -r ./instrumentation.js app.js</code></pre>

<h3>Spans customizados</h3>

<p>Para adicionar contexto específico do negócio, crie spans manualmente:</p>

<pre><code class="language-javascript">const { trace } = require(&#039;@opentelemetry/api&#039;);

const tracer = trace.getTracer(&#039;meu-modulo&#039;, &#039;1.0.0&#039;);

app.get(&#039;/api/usuarios/:id&#039;, async (req, res) =&gt; {

const span = tracer.startSpan(&#039;buscar-usuario&#039;);

try {

span.setAttributes({

&#039;usuario.id&#039;: req.params.id,

&#039;http.method&#039;: &#039;GET&#039;

});

const usuario = await db.usuarios.findById(req.params.id);

span.addEvent(&#039;usuario-encontrado&#039;, { &#039;db.rows&#039;: 1 });

res.json(usuario);

} catch (error) {

span.recordException(error);

span.setStatus({ code: 2 }); // ERROR

res.status(500).json({ erro: &#039;Falha ao buscar usuário&#039; });

} finally {

span.end();

}

});</code></pre>

<h2>Deployment no AWS com ADOT Collector</h2>

<h3>Configuração do Coletor</h3>

<p>O ADOT Collector recebe traces da sua aplicação e os envia aos serviços AWS. Crie um arquivo <code>otel-collector-config.yaml</code>:</p>

<pre><code class="language-yaml">receivers:

otlp:

protocols:

grpc:

endpoint: 0.0.0.0:4317

http:

endpoint: 0.0.0.0:4318

processors:

batch:

timeout: 10s

send_batch_size: 1024

memory_limiter:

check_interval: 5s

limit_mib: 512

exporters:

awsxray:

region: us-east-1

awsemf:

namespace: MinhaApp

log_group_name: /aws/otel/minhaapp

service:

pipelines:

traces:

receivers: [otlp]

processors: [memory_limiter, batch]

exporters: [awsxray]

metrics:

receivers: [otlp]

processors: [batch]

exporters: [awsemf]</code></pre>

<h3>ECS/Fargate com ADOT</h3>

<p>Adicione um container sidecar de coletor à sua task definition (JSON):</p>

<pre><code class="language-json">{

&quot;name&quot;: &quot;aws-otel-collector&quot;,

&quot;image&quot;: &quot;public.ecr.aws/aws-observability/aws-for-opentelemetry-collector:latest&quot;,

&quot;portMappings&quot;: [

{

&quot;containerPort&quot;: 4317,

&quot;protocol&quot;: &quot;tcp&quot;

}

],

&quot;environment&quot;: [

{

&quot;name&quot;: &quot;AWS_REGION&quot;,

&quot;value&quot;: &quot;us-east-1&quot;

}

],

&quot;mountPoints&quot;: [

{

&quot;sourceVolume&quot;: &quot;otel-config&quot;,

&quot;containerPath&quot;: &quot;/etc/ot-collector-config.yaml&quot;

}

]

}</code></pre>

<p>Na sua aplicação Node.js, configure o endpoint para apontar ao coletor:</p>

<pre><code class="language-bash">export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317</code></pre>

<h2>Observabilidade End-to-End: Da Aplicação ao X-Ray</h2>

<h3>Visualização de Traces no X-Ray</h3>

<p>Após configurar a exportação, os traces aparecerão no console X-Ray da AWS. O CloudWatch também receberá métricas automaticamente graças ao EMF Exporter. A correlação entre logs, traces e métricas acontece via trace ID:</p>

<pre><code class="language-javascript">const { context, trace } = require(&#039;@opentelemetry/api&#039;);

app.use((req, res, next) =&gt; {

const span = trace.getActiveSpan();

if (span) {

const traceId = span.spanContext().traceId;

// Injete em logs estruturados

res.locals.traceId = traceId;

}

next();

});

// Nos seus logs estruturados:

console.log(JSON.stringify({

message: &#039;Processamento iniciado&#039;,

traceId: res.locals.traceId,

timestamp: new Date().toISOString()

}));</code></pre>

<h3>Análise e Troubleshooting</h3>

<p>No console X-Ray, procure por erros usando filtros como:</p>

<ul>

<li><code>service(&quot;minha-app&quot;) AND error</code> — traces com exceções</li>

<li><code>annotations.usuario.id = &quot;123&quot;</code> — busque por atributos customizados</li>

<li><code>duration &gt; 1</code> — identifique operações lentas</li>

</ul>

<p>A latência é quebrada automaticamente em cada span, mostrando exatamente qual chamada consumiu tempo.</p>

<h2>Conclusão</h2>

<p>OpenTelemetry com ADOT oferece três benefícios imediatos: <strong>portabilidade</strong> (mesma instrumentação em todo lugar), <strong>padronização</strong> (não depende de APIs AWS específicas) e <strong>custo-benefício</strong> (sem duplicação de SDKs). Comece simples com auto-instrumentação, adicione spans customizados conforme necessário e escale o coletor conforme o volume de traces cresce. A maioria dos problemas de produção se resolve mais rápido quando você consegue visualizar a jornada completa de uma requisição através de seus sistemas.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://aws-otel.github.io/" target="_blank" rel="noopener noreferrer">AWS Distro for OpenTelemetry - Documentação Oficial</a></li>

<li><a href="https://opentelemetry.io/docs/" target="_blank" rel="noopener noreferrer">OpenTelemetry - Especificação e SDKs</a></li>

<li><a href="https://aws-otel.github.io/docs/getting-started/collector/" target="_blank" rel="noopener noreferrer">ADOT Collector Configuration Guide</a></li>

<li><a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-instrumenting-your-application.html" target="_blank" rel="noopener noreferrer">AWS X-Ray Integration with ADOT</a></li>

<li><a href="https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/auto-instrumentations-node" target="_blank" rel="noopener noreferrer">Node.js Auto-Instrumentation</a></li>

</ul>

Comentários

Mais em Cloud & Infraestrutura

Boas Práticas de AWS WAF e Shield: Proteção contra DDoS e Ataques Web para Times Ágeis
Boas Práticas de AWS WAF e Shield: Proteção contra DDoS e Ataques Web para Times Ágeis

Fundamentos de AWS WAF e Shield para Proteção Web AWS WAF (Web Application Fi...

Guia Completo de Billing e Cost Explorer: Tags, Budgets e Alertas de Custo
Guia Completo de Billing e Cost Explorer: Tags, Budgets e Alertas de Custo

Introdução: Por que Gerenciar Custos na Cloud? Gerenciar custos em ambientes...

Nginx: o que é, como funciona e por que vale a pena usar
Nginx: o que é, como funciona e por que vale a pena usar

Servidor travando com poucos acessos simultâneos? O Nginx resolve. Entenda su...