This is a sample microservices setup demonstrating observability using OpenTelemetry and Jaeger with a Spring Boot architecture.
The goal is to show how to enable tracing across multiple services, visualize those traces via Jaeger, and use Docker Compose for a quick local environment.
This repo contains several microservices + support infrastructure:
- service-registry β Eureka / Consul or similar for service discovery
- configserver β Central configuration server for all services
- api-gateway β Entry point (REST API) routing to downstream services
- inventory-service β Handles inventory related operations
- order-service β Manages orders
- cart-service β Shopping cart logic
Plus:
docker-compose.yamlto bring up Jaeger.- Distributed tracing setup using OpenTelemetry to send trace data to Jaeger
Make sure you have the following installed:
- Java 17 (or whichever version the services are using)
- Maven / Gradle (depending on how the projects are built)
- Docker & Docker Compose
- Git
These steps will get the project up and running locally.
-
Clone the repo
git clone https://github.com/moshclouds/OpenTelemetry-And-Jaeger-With-Springboot.git cd OpenTelemetry-And-Jaeger-With-Springboot -
Build the services
For each microservice, you might run something like:
cd <service-folder> mvn clean package # or ./gradlew build
-
Start everything with Docker Compose
docker-compose up --build
This will bring up:
- Jaeger (UI + collector)
- All microservices
- Service registry
- Config server
- Gateway
-
Verify
- Go to Jaeger UI, usually at:
http://localhost:16686 - Make some requests to the API Gateway or services via e.g.
curlor Postman - Observe traces appearing in Jaeger UI
- Go to Jaeger UI, usually at:
Some key configuration items:
-
application.properties / application.yml in each service must have:
- Service name (e.g.
spring.application.name) - OpenTelemetry exporter endpoint (e.g. OTLP or Jaeger collector)
- Sampling probability (e.g. send all vs some traces)
- Service name (e.g.
-
Docker Compose:
- Ports for Jaeger UI (e.g. 16686)
- Ports for OTLP / gRPC if needed
Hereβs roughly how the repo is organized:
/
βββ api-gateway/
βββ cart-service/
βββ inventory-service/
βββ order-service/
βββ configserver/
βββ service-registry/
βββ docker-compose.yaml
βββ README.md
βββ LICENSE
Each folder represents a Spring Boot service with its source, configs, etc.
After everything is up:
- Hit endpoints through the
api-gateway(for example:GET /orders/{id}, or whatever the exposed endpoints are) - Watch how the trace spans propagate through
api-gateway β order-service β inventory-service(or similar flow) - In Jaeger, you should see a trace UI showing each span, timings, response times, etc.
- Use high sampling probability during development; lower it in production to reduce overhead
- Tag spans with useful metadata (HTTP method, status code, service names)
- Use correlation IDs in your logs so that logs + traces together help diagnose issues
- Secure your Jaeger / OTLP endpoints if used in non-local environments
| Problem | Possible Causes | Solutions |
|---|---|---|
| No traces showing in Jaeger | Exporter misconfigured or wrong endpoint | Check application.yml / OTLP / jaeger config |
| Services not registering with registry | Registry address wrong or service not started after registry | Ensure service-registry is up and reachable |
| Docker ports conflict | Another service using same port | Modify ports in docker-compose.yaml |
This project is licensed under the MIT License. See LICENSE for details.
- OpenTelemetry community
- Jaeger project
- Spring Boot / Spring Cloud
If you have suggestions or improvements, pull requests are very welcome! π¬


