Monitorando um serviço com Jaeger e Open Telemetry
- Eduardo Nepomuceno da Rocha
- 11 de abr.
- 3 min de leitura
Em se tratando de boas práticas de desenvolvimento de software, aquelas referentes à observabilidade são cada vez mais necessárias diante das exigências de sistemas cada vez mais complexos e com maior carga de trabalho.
A arquitetura de microsserviços atualmente é a mais popular e utilizada dentro de projetos de diversas empresas. Uma única função de software pode envolver a comunicação de diversos microsserviços. Por muitas vezes torna-se necessário monitorar a cadeia de eventos nas interações de microsserviços, para que possa ser isolado um problema quando algo fora do normal acontece no sistema. O Jaeger, também chamado de Jaeger Tracing, é capaz de rastrear o caminho de uma solicitação por meio de uma série de interações desses microsserviços.
O Jaeger é capaz de monitorar transações distribuídas, analisando movimentos de dados entre os microsserviços. É uma ótima ferramenta para inspecionar o comportamento para avaliar questões de latência e identificar gargalos. Além disso, pode avaliar a dependência entre serviços e o caminho de uma solicitação. Deixarei um link para compreensão da ferramenta, pois meu objetivo aqui é ensinar como implementar e mostrar seu funcionamento em uma API. No caso, não subi uma arquitetura em microsserviços. Apresentarei a implementação em um monolito, mas obviamente a técnica se aplica a uma arquitetura dividida em muitos serviços. Apresentarei uma implementação para Spring Boot 3. Notei que existe uma carência de exemplos com essa versão do framework. O Java utilizado é 17 e a simulação é de uma aplicação executada em ambiente local, porém subindo o serviço do Jaeger e banco em container docker.
Docker-compose.yml

Neste arquivo vemos o mapeamento das portas mais essenciais do Jagger, o nome exato da imagem docker, informação sobre comunicação no environment e nome do container. Omiti as informações SQL por não ser o foco deste texto. O próximo passo é ter as dependências corretas no Pom. Aqui destacarei apenas as necessárias para subir essa aplicação com Jaeger, sem dar muita importância a outras focada em banco e migração como Flyway.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jdbc</artifactId>
<version>0.2.15</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
Há algumas dependências de bancos para o MySql, Flyway para migração de dados, JPA, Swagger, Lombok e outras práticas comuns de Spring Boot. Focando nas importantes para monitoramento, temos(olhando pelo artifactId): opentracing-jdbc, opentelemetry-exporter-otlp, micrometer-tracing-bridge-otel e também o spring-boot-starter-actuator. O primeiro é referente ao monitoramento inclusive de banco e query, os dois seguintes são necessários para estabelecer a comunicação entre Open Telemetry e Jaeger, enquanto a última já é do próprio Spring, também importante para termos o monitoramento correto. Em seguida, deve ser criado um bean de configuração para comunicação entre o serviço do Jaeger e o Open Telemetry. Veja
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OtlpConfiguration {
@Bean
OtlpHttpSpanExporter otlpHttpSpanExporter(@Value("${tracing.url}") String url){
return OtlpHttpSpanExporter.builder()
.setEndpoint(url)
.build();
}
}
Veja que é bem simples. Basicamente se configura o Exporter Otlp, passando para ele o endpoint que está no application.properties da aplicação.
server.port = 8099
spring.jpa.database=MYSQL
spring.datasource.driver-class-name=io.opentracing.contrib.jdbc.TracingDriver
spring.datasource.url=jdbc:tracing:mysql://localhost/nome_base_de_dados?useTimezone=true&serverTimezone=America/Sao_Paulo
spring.datasource.username=seu usuario
spring.datasource.password=sua senha
spring.jpa.show-sql=true
########## Configuration Tracing (OpenTelemetry + Jaeger) ############
management.tracing.sampling.probability=1.0
tracing.url=http://localhost:4318/v1/traces
logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]
No caso, optei por subir a aplicação na porta 8099. Considerando que a porta 8080 eventualmente pode estar ocupada, considero uma prática mais segura. Na configuração do banco, dois pontos são importantes: A necessidade de colocar o tracing entre jdbc e seu banco, assim como o driver-class-name do TracingDriver. Na parte referente à configuração de Tracing, o sampling probability define a probabilidade de amostragem dos laços. No caso, o valor 1.0 significa que todas as requisições serão coletadas para rastreamento. O tracing url define o endpoint de exportação de traços no protocolo OTLP/HTTP. O Open Telemetry SDK do Spring Boot 3 usa esse endpoint para enviar os traços coletados. Esse endpoint (4318/v1/traces) é exposto por pelos coletores OTEL e também por algumas versões recentes do Jaeger se configurado como receptor OTLP (o seu jaegertracing/all-in-one precisa ser recente e bem configurado pra isso funcionar). A última linha personaliza o padrão de log da aplicação. inserindo os IDS de trace e span no log, o que facilita a correlação entre os logs e os dados do tracing no Jaeger. Após essas configurações, você pode subir a aplicação e monitorar pelo Jaeger. O Jaeger é acessado por padrão na porta 16686. Teste subir o serviço e enviar requisições pelo Swagger ou Postman para verificar o funcionamento do Jaeger. Veja as imagens a seguir com dados apresentados na interface gráfica exposta na porta 16686, conforme citado anteriormente.


Commentaires