A production-ready Quarkus REST API with comprehensive OpenTelemetry instrumentation, featuring distributed tracing, metrics collection, and structured logging. Built with clean architecture principles and designed for cloud-native deployments.
- Features
- Prerequisites
- Quick Start
- Deployment Options
- API Documentation
- Configuration
- Observability
- Development
- Testing
- Contributing
- π Quarkus Framework - Supersonic Subatomic Java with fast startup times
- β‘ GraalVM Native Support - Build native executables with 10-100x faster startup and 3-5x lower memory usage
- π Full Observability - Distributed tracing, metrics, and structured logging
- π OpenTelemetry Native - Built-in OTLP exporter support for traces, metrics, and logs
- ποΈ Clean Architecture - Repository pattern with Panache for simplified data access
- π³ Docker Ready - Multi-stage Dockerfile with security best practices
- π Security First - Non-root user, minimal attack surface, vulnerability scanning
- π§ͺ Well Tested - Comprehensive test coverage with JUnit 5 and REST-assured
- π API Documentation - OpenAPI/Swagger UI automatically generated
- πΎ MySQL Integration - JDBC with full OpenTelemetry instrumentation
- π₯ Dual Runtime Modes - Run in JVM or native mode depending on your requirements
- Java 21+ (for local development)
- Maven 3.9+
- Docker & Docker Compose
- MySQL 8.0+ (or use the provided docker-compose)
- OpenTelemetry Collector (optional - included in full setup)
# Clone the repository
git clone https://github.com/devops-thiago/otel-example-quarkus.git
cd otel-example-quarkus
# Start everything with docker-compose
docker-compose up -d
# Check if services are running
docker-compose psAccess points:
- API: http://localhost:8080
- API Docs (Swagger): http://localhost:8080/q/swagger-ui
- Health: http://localhost:8080/q/health
- Metrics: http://localhost:8080/q/metrics
- Grafana: http://localhost:3000 (admin/admin)
- Alloy UI: http://localhost:12345
# Install dependencies and run in dev mode
./mvnw quarkus:dev
# Or build and run
./mvnw clean package
java -jar target/quarkus-app/quarkus-run.jarIf you already have an OpenTelemetry infrastructure:
# Use the app-only compose file
docker-compose -f docker-compose.app-only.yml up -dRequired environment variables:
# OpenTelemetry Configuration
OTEL_EXPORTER_OTLP_ENDPOINT=your-collector:4320
OTEL_SERVICE_NAME=otel-quarkus-crud
# Database Configuration
DB_HOST=your-mysql-host
DB_PORT=3306
DB_USER=your-db-user
DB_PASSWORD=your-db-password
DB_NAME=your-db-nameapiVersion: apps/v1
kind: Deployment
metadata:
name: otel-quarkus-api
spec:
replicas: 3
selector:
matchLabels:
app: otel-quarkus-api
template:
metadata:
labels:
app: otel-quarkus-api
spec:
containers:
- name: api
image: otel-example-quarkus:latest
ports:
- containerPort: 8080
env:
- name: QUARKUS_OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://otel-collector:4320"
- name: DB_HOST
value: "mysql-service"
livenessProbe:
httpGet:
path: /q/health/live
port: 8080
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /q/health/ready
port: 8080
initialDelaySeconds: 10# Build the image locally
docker build -t otel-example-quarkus:latest .
# Build with Maven
./mvnw clean package -Dquarkus.container-image.build=true
# Build multi-platform image
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t otel-example-quarkus:latest .Build native executables for 10-100x faster startup and 3-5x lower memory usage:
# Build manually
docker build -f Dockerfile.native -t otel-example-quarkus:native .
# Run native image with docker-compose
docker-compose -f docker-compose.native.yml up -dNative mode benefits:
- Startup time: ~0.05s vs ~3s (JVM)
- Memory usage: ~100MB vs ~350MB (JVM)
- No JVM warmup required
- Perfect for serverless, Kubernetes, and microservices
| Method | Endpoint | Description |
|---|---|---|
| GET | /q/health |
Overall health check |
| GET | /q/health/live |
Liveness probe |
| GET | /q/health/ready |
Readiness probe |
| GET | /q/metrics |
Prometheus-compatible metrics |
| Method | Endpoint | Description | Request Body |
|---|---|---|---|
| GET | /api/users |
List all users | - |
| GET | /api/users/{id} |
Get user by ID | - |
| GET | /api/users/email/{email} |
Get user by email | - |
| GET | /api/users/search?name={name} |
Search users by name | - |
| GET | /api/users/recent?days={days} |
Get recent users | - |
| GET | /api/users/count |
Get user count | - |
| POST | /api/users |
Create new user | {"name": "John", "email": "john@example.com", "bio": "Developer"} |
| PUT | /api/users/{id} |
Update user | {"name": "John Updated"} |
| DELETE | /api/users/{id} |
Delete user | - |
# Create a user
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com", "bio": "Software Engineer"}'
# Get all users
curl http://localhost:8080/api/users
# Get user by ID
curl http://localhost:8080/api/users/1
# Search users
curl http://localhost:8080/api/users/search?name=John
# Get recent users (last 7 days)
curl http://localhost:8080/api/users/recent?days=7
# Update user
curl -X PUT http://localhost:8080/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name": "John Updated", "bio": "Senior Engineer"}'
# Delete user
curl -X DELETE http://localhost:8080/api/users/1| Variable | Description | Default |
|---|---|---|
| OpenTelemetry | ||
QUARKUS_OTEL_ENABLED |
Enable OpenTelemetry | true |
QUARKUS_OTEL_EXPORTER_OTLP_ENDPOINT |
OTLP collector endpoint | http://localhost:4320 |
QUARKUS_OTEL_LOGS_ENABLED |
Enable OTLP log export | true |
QUARKUS_OTEL_TRACES_ENABLED |
Enable distributed tracing | true |
QUARKUS_OTEL_METRICS_ENABLED |
Enable metrics collection | true |
| Database | ||
DB_HOST |
MySQL host | localhost |
DB_PORT |
MySQL port | 3306 |
DB_USER |
MySQL user | user |
DB_PASSWORD |
MySQL password | password |
DB_NAME |
MySQL database name | userdb |
| Server | ||
QUARKUS_HTTP_PORT |
API server port | 8080 |
QUARKUS_HTTP_HOST |
API server host | 0.0.0.0 |
This project includes a complete observability stack using the LGTM (Loki, Grafana, Tempo, Mimir) stack:
- Trace all HTTP requests and database queries
- Correlate logs with traces using trace IDs
- View spans in Grafana with trace context
- HTTP server metrics (request duration, status codes, etc.)
- JVM metrics (memory, threads, GC)
- Database connection pool metrics
- Custom business metrics
- Structured JSON logs
- Automatic trace correlation
- Log levels and filtering
- Full-text search capabilities
Pre-configured dashboards for:
- Application overview
- HTTP request metrics
- JVM performance
- Trace exploration
Access Grafana: http://localhost:3000 (admin/admin)
.
βββ src/
β βββ main/
β β βββ java/br/com/arquivolivre/otelquarkus/
β β β βββ model/ # JPA entities
β β β βββ repository/ # Data access layer
β β β βββ resource/ # REST endpoints
β β β βββ service/ # Business logic
β β βββ resources/
β β βββ application.properties # Configuration
β β βββ import.sql # Initial data
β βββ test/
β βββ java/ # Unit and integration tests
βββ config/ # Observability stack configs
β βββ alloy.alloy # Grafana Alloy configuration
β βββ tempo.yaml # Tempo tracing backend
β βββ mimir.yaml # Mimir metrics backend
β βββ loki.yaml # Loki logging backend
β βββ grafana/ # Grafana provisioning
βββ docker-compose.yml # Full stack deployment
βββ Dockerfile # Multi-stage Docker build
βββ pom.xml # Maven dependencies
βββ README.md # This file
Quarkus provides a development mode with hot-reload:
./mvnw quarkus:devThis enables:
- Live reload of code changes
- Dev UI at http://localhost:8080/q/dev
- Debugging on port 5005
# Format code
./mvnw spotless:apply
# Check code style
./mvnw spotless:check
# Run static analysis
./mvnw verify# The app automatically creates/updates schema on startup
# Initial data is loaded from src/main/resources/import.sql# Run all tests
./mvnw test
# Run with coverage
./mvnw verify
# Run specific test class
./mvnw test -Dtest=UserResourceTest
# Run integration tests only
./mvnw verify -Dskip.unit.tests=true- Unit Tests: Repository, Service, and Resource layers
- Integration Tests: Full API endpoint testing
- Coverage Target: >80% line coverage, >75% branch coverage
View coverage report: target/site/jacoco/index.html
# Build the Docker image
docker build -t otel-quarkus-api .
# Run the container
docker run -d \
-p 8080:8080 \
-e DB_HOST=mysql \
-e QUARKUS_OTEL_EXPORTER_OTLP_ENDPOINT=http://alloy:4320 \
otel-quarkus-api# Start full stack
docker-compose up -d
# View logs
docker-compose logs -f app
# Stop services
docker-compose down
# Rebuild and restart
docker-compose up -d --build app- Prometheus metrics: http://localhost:8080/q/metrics
- Health check: http://localhost:8080/q/health
- OpenAPI spec: http://localhost:8080/q/openapi
- Application Overview: Real-time metrics and request rates
- JVM Metrics: Memory, GC, and thread monitoring
- Trace Analysis: Distributed tracing visualization
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Java code conventions
- Add tests for new features
- Update documentation as needed
- Run
./mvnw spotless:applybefore committing
This project is licensed under the MIT License - see the LICENSE file for details.