Existe uma forma de ter traces, métricas e logs correlacionados no Kubernetes sem instalar agente Java, sem configurar sidecar manualmente e sem escrever uma linha de instrumentação. A maioria dos times ainda não habilitou o starter que o Spring Boot 4 trouxe. Uma dependência no pom.xml e o OpenTelemetry Operator cuida do resto.
Com o Spring Framework 7.0.7 (lançado em abril de 2026), o ecossistema Spring finalmente tem observabilidade de produção built-in. Neste artigo você vai ver como configurar do zero, com código funcional de um serviço Spring Boot 4 rodando em Kubernetes, sem mágica e sem ferramenta extra além do que o próprio starter já entrega.
O problema que o agente Java sempre criou
Quem trabalhou com observabilidade Java antes do Spring Boot 4 conhece bem o ciclo: instala o agente Java via -javaagent na JVM, configura variáveis de ambiente no Deployment do Kubernetes, testa se o agente não conflita com as outras libs, atualiza o agente quando a versão nova do Quarkus ou Spring quebra compatibilidade. Repete tudo isso para cada microsserviço.
Como Tech Leader em times com mais de 15 microsserviços Java, vi esse ciclo virar pesadelo de manutenção. Um upgrade de agente virava um projeto de 2 sprints. O pior: quando o agente conflitava com alguma lib de criptografia ou HTTP client customizado, o problema só aparecia em produção.
O modelo antigo tinha três dores principais:
- Acoplamento entre agente e JVM: cada versão Java nova exigia teste de compatibilidade do agente
- Configuração por variável de ambiente: dezenas de
OTEL_*espalhadas nos Deployments, difíceis de auditar - Logs desconectados de traces: sem correlation ID automático, correlacionar log com trace era trabalho manual
O Spring Boot 4 resolve os três com o starter nativo. Bora ver como funciona na prática.
O que mudou com o Spring Boot 4 e o starter OpenTelemetry
O spring-boot-starter-opentelemetry chegou com o Spring Boot 4 como parte da integração nativa com o OpenTelemetry Spring Boot Starter oficial. Ele faz três coisas automaticamente:
- Configura o SDK OpenTelemetry com exportador OTLP (HTTP ou gRPC)
- Instrumenta automaticamente chamadas HTTP, JDBC, cache e mensageria sem uma linha de código
- Injeta o trace ID e span ID nos logs via MDC, correlacionando logs com traces automaticamente
Para adicionar ao projeto, basta incluir a dependência:
<!-- pom.xml -- Spring Boot 4 com starter OpenTelemetry -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-opentelemetry</artifactId>
<!-- versão gerenciada pelo spring-boot-parent, sem precisar declarar -->
</dependency>
Sem mais nada. A instrumentação de chamadas HTTP com RestClient, queries JDBC via Spring Data, e publish/consume com Spring Kafka já vêm instrumentados. O starter detecta o que está no classpath e habilita os instrumentadores correspondentes.
A configuração vai toda para o application.yaml:
# application.yaml -- configuração OpenTelemetry para Kubernetes
management:
tracing:
enabled: true
sampling:
probability: 1.0 # 100% em dev; ajustar para 0.1 em produção com muito volume
spring:
application:
name: meu-servico-java # vira o service.name no trace
# Exportador OTLP -- aponta para o OpenTelemetry Collector no cluster
otel:
exporter:
otlp:
endpoint: http://otel-collector.observability.svc.cluster.local:4318
protocol: "http/protobuf"
logs:
exporter: otlp # envia logs estruturados junto com traces
Configurando o OpenTelemetry Operator no Kubernetes
O OpenTelemetry Operator é um Kubernetes Operator que gerencia o ciclo de vida do Collector e da instrumentação automática de pods. Com ele, você não precisa configurar sidecar manualmente nem gerenciar o DaemonSet do Collector a mão.
Instalação via Helm:
# Instalar o OpenTelemetry Operator via Helm
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
helm install opentelemetry-operator open-telemetry/opentelemetry-operator --namespace observability --create-namespace --set "manager.collectorImage.repository=otel/opentelemetry-collector-contrib"
Com o Operator instalado, você cria um recurso OpenTelemetryCollector que define como o Collector vai rodar e para onde vai exportar os dados:
# otel-collector.yaml -- Collector em modo Deployment para apps Java
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: otel-collector
namespace: observability
spec:
mode: deployment
config: |
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 5s
memory_limiter:
limit_mib: 256
exporters:
prometheus:
endpoint: 0.0.0.0:8889
loki:
endpoint: http://loki.observability.svc.cluster.local:3100/loki/api/v1/push
otlp/tempo:
endpoint: http://tempo.observability.svc.cluster.local:4317
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlp/tempo]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [prometheus]
logs:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [loki]
Verificando traces end-to-end em código real
Com o starter configurado, cada request ao seu serviço Spring Boot 4 gera automaticamente um trace com spans para cada operação:
@RestController
@RequestMapping("/api/pedidos")
public class PedidoController {
@Autowired
private PedidoService pedidoService;
@GetMapping("/{id}")
public ResponseEntity<Pedido> buscarPedido(@PathVariable Long id) {
return ResponseEntity.ok(pedidoService.buscar(id));
}
}
Para adicionar spans customizados em operações de negócio:
@Service
public class PedidoService {
@Observed(name = "pedido.calculo-frete",
contextualName = "calculando frete para pedido")
public BigDecimal calcularFrete(Pedido pedido) {
return freteCalculator.calcular(pedido.getDestino(), pedido.getPeso());
}
}
O que muda na prática para o time
A diferença mais imediata é na velocidade de diagnóstico. Com a stack configurada, o fluxo vira:
- Alerta dispara no Grafana (métrica de erro rate acima de 1%)
- Você filtra logs com
level=ERRORdo serviço - Clica no
trace_idno log e vai direto para o trace no Grafana Tempo - Identifica o span com erro, vê a exception e o stack trace
Do alerta ao diagnóstico: menos de 5 minutos. Antes, sem traces, esse caminho levava entre 30 e 90 minutos de kubectl logs e grep manual.
Outro ganho direto é no custo de infra. A remoção do agente Datadog (150MB a 300MB por pod) e a adoção do starter nativo reduziu o consumo de RAM em 20-25% por pod em testes com serviços Spring Boot de porte médio.
Para quem está migrando de Spring Boot 3 para 4 e já usa Micrometer Tracing: o starter substitui as configurações manuais do OpenTelemetryAutoConfiguration. Você pode remover as dependências explícitas de io.micrometer:micrometer-tracing-bridge-otel e io.opentelemetry:opentelemetry-exporter-otlp.
Links relacionados:
- Como configurar Spring Boot Actuator com Health Checks no Kubernetes
- HPA no Kubernetes com métricas personalizadas do Spring Boot
- Spring Boot 4: breaking changes e checklist de migração
Conclusão: observabilidade sem agente, do jeito certo
O spring-boot-starter-opentelemetry entrega observabilidade de produção sem acoplamento com agente externo, configurável via application.yaml, integrada com o Micrometer e compatível com qualquer backend OTLP.
Os três takeaways principais:
- Uma dependência no pom.xml instrumenta automaticamente HTTP, JDBC, cache e mensageria
- O OpenTelemetry Operator gerencia o Collector no Kubernetes sem YAML manual de sidecar
- Traces e logs correlacionados reduzem o tempo de diagnóstico de horas para minutos
Você já tem OpenTelemetry configurado nos seus microsserviços Java? Ainda usa agente ou já migrou para o starter nativo? Conta nos comentários como está sendo na prática do seu time.
No próximo artigo vou mostrar como configurar alertas inteligentes no Grafana baseados em métricas do Spring Boot Actuator no Kubernetes. Fica ligado.
Referências: OpenTelemetry Spring Boot Starter, OpenTelemetry Kubernetes Operator