Skip to content

devops-thiago/otel-example-quarkus

Repository files navigation

OpenTelemetry Quarkus Example

CI Java Version Quarkus License Codecov Sonar Quality Gate Coverage OpenTelemetry Docker Docker Hub Docker Pulls

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.

πŸ“‹ Table of Contents

✨ Features

  • πŸš€ 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

πŸ“š Prerequisites

  • 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)

πŸš€ Quick Start

Option 1: Full Stack (App + Database + Observability)

# 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 ps

Access points:

Option 2: Run Locally

# Install dependencies and run in dev mode
./mvnw quarkus:dev

# Or build and run
./mvnw clean package
java -jar target/quarkus-app/quarkus-run.jar

🚒 Deployment Options

Using Your Own OpenTelemetry Collector

If you already have an OpenTelemetry infrastructure:

# Use the app-only compose file
docker-compose -f docker-compose.app-only.yml up -d

Required 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-name

Kubernetes Deployment

apiVersion: 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

Building Docker Image

JVM Mode (Default)

# 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 .

GraalVM Native Mode

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 -d

Native 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

πŸ“– API Documentation

Health Endpoints

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

User API

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 -

Example Requests

# 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

βš™οΈ Configuration

Environment Variables

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

πŸ”­ Observability

This project includes a complete observability stack using the LGTM (Loki, Grafana, Tempo, Mimir) stack:

Distributed Tracing (Tempo)

  • Trace all HTTP requests and database queries
  • Correlate logs with traces using trace IDs
  • View spans in Grafana with trace context

Metrics Collection (Mimir)

  • HTTP server metrics (request duration, status codes, etc.)
  • JVM metrics (memory, threads, GC)
  • Database connection pool metrics
  • Custom business metrics

Log Aggregation (Loki)

  • Structured JSON logs
  • Automatic trace correlation
  • Log levels and filtering
  • Full-text search capabilities

Visualization (Grafana)

Pre-configured dashboards for:

  • Application overview
  • HTTP request metrics
  • JVM performance
  • Trace exploration

Access Grafana: http://localhost:3000 (admin/admin)

πŸ—οΈ Project Structure

.
β”œβ”€β”€ 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

πŸ› οΈ Development

Running in Dev Mode

Quarkus provides a development mode with hot-reload:

./mvnw quarkus:dev

This enables:

Code Quality

# Format code
./mvnw spotless:apply

# Check code style
./mvnw spotless:check

# Run static analysis
./mvnw verify

Database Migrations

# The app automatically creates/updates schema on startup
# Initial data is loaded from src/main/resources/import.sql

πŸ§ͺ Testing

# 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

Test Coverage

  • 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

🐳 Docker

Build and Run

# 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

Docker Compose

# 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

πŸ“Š Monitoring

Metrics Endpoints

Grafana Dashboards

  1. Application Overview: Real-time metrics and request rates
  2. JVM Metrics: Memory, GC, and thread monitoring
  3. Trace Analysis: Distributed tracing visualization

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Code Standards

  • Follow Java code conventions
  • Add tests for new features
  • Update documentation as needed
  • Run ./mvnw spotless:apply before committing

πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •