Pular para o conteúdo

Configurando o OpenTelemetry Collector

O OpenTelemetry Collector é um componente central na arquitetura de observabilidade. Ele recebe dados de telemetria das suas aplicações, processa-os e exporta para um ou mais backends. Neste guia, vamos configurar o Collector do zero para um cenário real.

Você pode exportar dados diretamente da sua aplicação para o backend de observabilidade. Então, por que adicionar o Collector no meio?

Sem CollectorCom Collector
Cada aplicação precisa saber o endpoint do backendAplicações enviam para o Collector local
Trocar de backend exige mudar todas as aplicaçõesTroca apenas no Collector
Sem processamento intermediárioFiltragem, amostragem, enriquecimento
Cada linguagem precisa do exporter específicoCollector suporta todos os exporters
Sem buffer — se o backend cair, dados são perdidosCollector pode fazer retry e buffer

Recomendação: em produção, sempre use o Collector. Em desenvolvimento, exportar diretamente é aceitável.

O Collector funciona como um pipeline com três componentes:

┌──────────┐ ┌──────────────┐ ┌───────────┐
│ Receivers │ ──→ │ Processors │ ──→ │ Exporters │
└──────────┘ └──────────────┘ └───────────┘
  • Receivers — como os dados entram no Collector (OTLP, Jaeger, Prometheus, etc.)
  • Processors — transformações aplicadas aos dados (batch, filter, sampling, etc.)
  • Exporters — para onde os dados são enviados (OTLP, Jaeger, Prometheus, etc.)
Terminal window
docker run -d --name otel-collector \
-p 4317:4317 \
-p 4318:4318 \
-p 8888:8888 \
-v $(pwd)/otel-collector-config.yaml:/etc/otelcol/config.yaml \
otel/opentelemetry-collector-contrib:latest
docker-compose.yaml
services:
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
ports:
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
- "8888:8888" # Métricas do Collector
volumes:
- ./otel-collector-config.yaml:/etc/otelcol/config.yaml
jaeger:
image: jaegertracing/all-in-one:latest
ports:
- "16686:16686" # UI do Jaeger
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yaml:/etc/prometheus/prometheus.yml

Baixe da página de releases e execute:

Terminal window
./otelcol-contrib --config otel-collector-config.yaml

Aqui está uma configuração que recebe dados via OTLP e exporta traces para Jaeger e métricas para Prometheus:

otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 5s
send_batch_size: 1024
exporters:
otlp/jaeger:
endpoint: jaeger:4317
tls:
insecure: true
prometheus:
endpoint: 0.0.0.0:8889
logging:
verbosity: basic
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/jaeger, logging]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus, logging]
logs:
receivers: [otlp]
processors: [batch]
exporters: [logging]

receivers.otlp — aceita dados no protocolo OTLP via gRPC (porta 4317) e HTTP (porta 4318). Este é o protocolo nativo do OpenTelemetry.

processors.batch — agrupa dados em lotes antes de exportar. Isso reduz o número de chamadas de rede e melhora a performance. O timeout define o tempo máximo de espera e send_batch_size o tamanho máximo do lote.

exporters — cada exporter define um destino:

  • otlp/jaeger — envia traces para o Jaeger via OTLP
  • prometheus — expõe métricas em um endpoint para o Prometheus fazer scrape
  • logging — imprime dados no stdout (útil para debug)

service.pipelines — conecta receivers, processors e exporters em pipelines separados para traces, métricas e logs.

Remova spans ou métricas que você não precisa:

processors:
filter/traces:
error_mode: ignore
traces:
span:
- 'attributes["http.target"] == "/health"'
- 'attributes["http.target"] == "/ready"'

Isso remove spans de health checks que geralmente são ruído.

Em produção com alto volume, você provavelmente não precisa de 100% dos traces. O tail sampling permite decisões inteligentes:

processors:
tail_sampling:
decision_wait: 10s
policies:
# Sempre manter traces com erro
- name: errors
type: status_code
status_code:
status_codes: [ERROR]
# Sempre manter traces lentos (> 2s)
- name: slow-traces
type: latency
latency:
threshold_ms: 2000
# Amostrar 10% do resto
- name: sampling
type: probabilistic
probabilistic:
sampling_percentage: 10

Adicione atributos a todos os dados que passam pelo Collector:

processors:
resource:
attributes:
- key: deployment.environment
value: production
action: upsert
- key: service.region
value: sa-east-1
action: upsert

O padrão mais comum em produção:

┌─────────┐ ┌───────────────┐ ┌─────────────────┐ ┌─────────┐
│ App 1 │ ──→ │ Collector │ ──→ │ Collector │ ──→ │ Backend │
│ App 2 │ ──→ │ (Agent/Pod) │ ──→ │ (Gateway) │ ──→ │ │
│ App 3 │ ──→ │ │ │ - Sampling │ │ │
└─────────┘ └───────────────┘ │ - Enrichment │ └─────────┘
└─────────────────┘
  • Agent — roda ao lado de cada aplicação (sidecar/DaemonSet), faz batching básico
  • Gateway — centralizado, faz processamento pesado (sampling, filtragem, enriquecimento)
# DaemonSet para o Agent
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: otel-collector-agent
spec:
template:
spec:
containers:
- name: collector
image: otel/opentelemetry-collector-contrib:latest
env:
- name: K8S_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName

O Collector expõe suas próprias métricas na porta 8888 por padrão:

Terminal window
curl http://localhost:8888/metrics

Métricas importantes para monitorar:

  • otelcol_receiver_accepted_spans — spans recebidos com sucesso
  • otelcol_receiver_refused_spans — spans recusados
  • otelcol_exporter_sent_spans — spans exportados com sucesso
  • otelcol_exporter_send_failed_spans — falhas de exportação
  • otelcol_processor_dropped_spans — spans descartados por processors

Discussão

Tem alguma dúvida ou quer compartilhar sua experiência? Comente abaixo!