Skip to content

Docker container setup containing REST services for benchmarking with wrk2 and complete observability with Grafana stack

License

Notifications You must be signed in to change notification settings

George-C-Odes/Observability-Benchmarking

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Observability Benchmarking

License Java Spring Boot Quarkus Go Docker

A comprehensive Docker Compose-based environment for observability benchmarking and OpenTelemetry benchmarking of containerized REST services with full telemetry using the Grafana observability stack (LGTM: Loki, Grafana, Tempo, Mimir), continuous profiling (Pyroscope), OpenTelemetry collection (Alloy), and deterministic load generation (wrk2).


πŸ“‹ Table of Contents


🎯 Overview

This repository provides a production-ready Docker Compose environment for comprehensive performance benchmarking of REST service implementations. It enables you to:

  • Compare frameworks and runtimes: Evaluate Spring Boot, Quarkus (JVM & Native), Go, and more
  • Test concurrency models: Platform threads, virtual threads (Project Loom), and reactive programming
  • Collect full observability data: Logs, metrics, traces, and continuous profiling in one unified stack
  • Run deterministic benchmarks: Use wrk2 for controlled, reproducible load testing
  • Visualize performance: Pre-configured Grafana dashboards for deep performance insights

Perfect for developers, architects, and DevOps engineers looking to make data-driven decisions about technology stack choices, optimize application performance, or build a performance testing pipeline.

Why This Project?

  • All-in-one solution: No need to configure multiple observability tools separately
  • Framework agnostic: Easily add new language implementations
  • Real-world scenarios: Tests actual REST endpoints with caching, not synthetic benchmarks
  • Educational: Learn how different threading models and frameworks perform under load
  • Portfolio ready: Demonstrates expertise in performance engineering and observability

Search keywords (for reach)

If you’re searching for projects like this, these are the topics it covers:

  • OpenTelemetry (OTel) benchmarking
  • observability benchmarking / performance engineering
  • Grafana LGTM stack (Loki + Tempo + Mimir + Grafana)
  • continuous profiling (Grafana Pyroscope)
  • wrk2 constant-throughput load testing
  • Java virtual threads (Project Loom) vs platform threads vs reactive (WebFlux/Mutiny)
  • Quarkus vs Spring Boot performance
  • GraalVM native image benchmarking

✨ Features

πŸ—οΈ Complete Observability Stack (LGTM)

  • Loki: Centralized log aggregation and querying
  • Grafana: Pre-configured dashboards for metrics, logs, traces, and profiles
  • Tempo: Distributed tracing with OpenTelemetry
  • Mimir: Long-term metrics storage and querying

πŸ” Advanced Profiling

  • Pyroscope: Continuous profiling with multiple collection methods:
    • Java agent-based profiling (JVM builds)
    • eBPF-based sampling (system-wide)
    • HTTP scrape endpoints

πŸŽ›οΈ Orchestration Dashboard

  • Next.js Dashboard: Modern web UI for managing the benchmarking environment
    • Edit environment configuration (compose/.env) through intuitive UI
    • Execute IntelliJ IDEA run configurations from the browser
    • Professional MUI-based interface with switchable themes
    • Built with Next.js 16.1.4 and Material-UI 7.3.7

πŸš€ REST Service Implementations

Java (JDK 25 - Amazon Corretto)

  • Spring Boot 4.0.1 (3.5.9 also supported)
    • Platform threads (traditional)
    • Virtual threads (Project Loom)
    • Reactive (WebFlux)
  • Quarkus 3.30.7
    • JVM builds (all three thread modes)
    • Native builds with GraalVM (all three thread modes)

Go (1.25.6)

  • Fiber framework integration
  • Full observability setup

🎯 Load Generation

  • wrk2: Deterministic, constant-throughput HTTP benchmarking
  • Configurable via .env file
  • Scripts for reproducible test runs

🐳 Infrastructure

  • Docker Compose: Complete orchestration
  • Profile-based deployment: Run only what you need
    • OBS: Observability stack only
    • SERVICES: Include REST services
    • RAIN_FIRE: Add load generators
  • Resource controls: CPU and memory limits for fair comparisons

πŸ“Š OpenTelemetry Integration

  • Batched collection of logs, metrics, and traces
  • gRPC transport for efficiency
  • Alloy collector for flexible routing

πŸš€ Getting Started

Prerequisites

Before you begin, ensure you have the following installed:

  • Docker: Version 20.10 or higher
  • Docker Compose: Version 2.0 or higher (modern Compose CLI)

Required local path setting (HOST_REPO)

This repo is orchestrated via the compose/ project directory.

⚠️ Important: in compose/.env, you must set HOST_REPO to the absolute path of the repository root on your machine (for example: C:\Users\you\dev\Observability-Benchmarking).

If HOST_REPO is not set correctly, bind-mounts used by the dashboard/orchestrator and benchmark tooling won’t resolve and the environment won’t start cleanly.

System requirements

  • Minimum: 8 GB RAM, 4 CPU cores
  • Recommended: 16 GB RAM, 8 CPU cores
  • Storage: At least 10 GB free space

Installation

  1. Clone the repository

    git clone https://github.com/George-C-Odes/Observability-Benchmarking.git
    cd Observability-Benchmarking
  2. Configure environment variables (optional)

    cp .env.example .env
    # Edit .env to customize benchmark parameters

Quick Start

There are multiple supported ways to get up and running. All options ultimately use Docker Compose under compose/.

Option 1: IntelliJ IDEA Run/Debug scripts (recommended for development)

If you prefer a guided workflow and repeatable β€œone-click” scripts, use the provided IntelliJ Run/Debug configurations.

Tip: this is the smoothest way to build and run native-image services because the scripts already respect the repository’s resource and ordering constraints.

Option 2: Docker Compose directly (terminal)

Use profiles to control what gets deployed:

1. Start Only the Observability Stack

Perfect for exploring Grafana and the LGTM stack:

docker compose --project-directory compose --profile=OBS up --no-recreate --build -d

Access Grafana: Navigate to http://localhost:3000

  • Default credentials: a / a

Access Dashboard: Navigate to http://localhost:3001

  • Orchestration UI for managing environment and running scripts

2. Start Observability Stack + REST Services

Run the full stack with all implemented services:

docker compose --project-directory compose --profile=OBS --profile=SERVICES up --no-recreate --build -d

Services will be available on their configured ports (check compose/docker-compose.yml for details).

3. Start Everything Including Load Generators

Run the complete benchmarking environment:

docker compose --project-directory compose --profile=OBS --profile=SERVICES --profile=RAIN_FIRE up --no-recreate --build -d

4. Rerun Only Load Generators

To rerun benchmarks without rebuilding services:

docker compose --project-directory compose --profile=RAIN_FIRE up --force-recreate -d

IntelliJ IDEA Integration

Pre-configured run configurations are available in the .run/ directory for convenient development and testing within IntelliJ IDEA.

Build time and resource notes (native images)

⚠️ Native-image builds are slow and CPU intensive. On typical developer hardware, a single native image build can take up to ~10 minutes, and a first-time build of all services can take 30+ minutes.

To keep builds stable (especially on Windows + WSL2 / Docker Desktop), this repository defaults to serial image builds:

  • COMPOSE_PARALLEL_LIMIT=1

Building two native images in parallel can exhaust RAM/CPU and has been observed to crash Docker Engine (at least in WSL2).

Warming Up

⚠️ Important: Wait approximately 60 seconds after starting the stack to ensure:

  • All services are fully initialized
  • Grafana datasources are connected
  • Observability agents are registered

Testing

This project focuses primarily on performance benchmarking.

Load Testing & Benchmarking

  • wrk2-based deterministic load generation with fixed request rates
  • Benchmark scripts in utils/wrk2/ directory
  • Results captured in results/ directory with timestamps and metadata
  • See Benchmarking Methodology for detailed testing procedures

Service Validation

  • Health check endpoints (/actuator/health for Spring, /q/health for Quarkus)
  • Startup validation via Docker Compose health checks
  • Manual smoke testing with curl or browser

Observability Validation

  • Metrics collection verified in Grafana dashboards
  • Trace propagation checked in Tempo
  • Log aggregation validated in Loki
  • Profile data confirmed in Pyroscope

Traditional unit/integration testing is also present, see under integration-tests/ directory.

πŸ“Έ Visual Overview

Note: Screenshots and diagrams can be added to docs/images/ directory. This is where you can include:

  • Grafana dashboard screenshots showing metrics, traces, and logs
  • Architecture diagrams illustrating the LGTM stack integration
  • Performance charts comparing different implementations
  • Flamegraphs from Pyroscope profiling

See docs/images/README.md for guidelines on adding visual assets.

πŸ“Š Benchmarks

Running Benchmarks

Manual Benchmark Execution

You can run custom benchmarks using wrk2 directly:

# Example: 10 threads, 100 connections, 50000 requests/sec for 60 seconds
wrk -t10 -c100 -d60s -R50000 --latency http://localhost:8080/api/endpoint

Automated Benchmarking

The repository includes pre-configured load generation scripts accessible via Docker Compose profiles.

Configuration: Edit the .env file to adjust benchmark parameters:

  • WRK_THREADS: Number of worker threads
  • WRK_CONNECTIONS: Number of concurrent connections
  • WRK_RATE: Target requests per second
  • WRK_DURATION: Test duration

Best Practices:

  • Warm-up period: Run for ~30 seconds before collecting data
  • JVM workloads: Run for at least 3 minutes to allow JIT compilation
  • CPU affinity: For mixed P/E core CPUs, consider process affinity tools (e.g., Process Lasso on Windows)
  • Avoid saturation: Monitor host CPU/memory to ensure the host isn't the bottleneck

Results

The numbers below are a curated summary of a representative run (22/01/2026). For methodology and how to reproduce: see the docs site.

Requests Per Second (RPS) β€” 22/01/2026 (to closest thousand)

Implementation Mode RPS
Spring JVM Platform 32k
Spring JVM Virtual 29k
Spring JVM Reactive 22k
Spring Native Platform 20k
Spring Native Virtual 20k
Spring Native Reactive 16k
Quarkus JVM Platform 70k
Quarkus JVM Virtual 90k
Quarkus JVM Reactive 104k
Quarkus Native Platform 45k
Quarkus Native Virtual 54k
Quarkus Native Reactive 51k
Go (observability-aligned) β€” 52k

Note: The GitHub Pages landing page may show a β€œtop RPS” number; the table above is the most up-to-date reference.

Fairness note (Go vs go-simple)

You may notice a higher-RPS Go variant in the repo (go-simple) with results around ~120k RPS.

That implementation is intentionally kept out of the β€œlike-for-like” headline comparison because it does not run with an observability setup equivalent to the Java services.

The newer Go implementation targets a more apples-to-apples comparison (OpenTelemetry + the same pipeline), so it’s the one summarized here.

Test Environment

Hardware & Platform

  • CPU: Intel i9-14900HX (24 cores, 32 threads)
  • RAM: 32 GB DDR5
  • Storage: NVMe SSD
  • OS: Windows 11 with WSL2 (kernel 6.6.87.2-microsoft-standard-WSL2)
  • Container Runtime: Docker Desktop

Container Configuration

  • CPU Limit: 4 vCPUs per service container
  • Memory: Dynamically allocated
  • Network: Docker bridge network

Software Versions

  • Java JDK: Eclipse Temurin 25.0.1
  • Java Native: GraalVM Enterprise 25.0.1-ol10
  • Spring Boot: 4.0.1 (3.5.9 also supported)
  • Quarkus: 3.30.7
  • Go: 1.25.6 (Fiber v2.52.10)
  • Garbage Collector: G1GC (all Java implementations)

πŸ”’ Legal and license notes (read this)

This repository is licensed under Apache-2.0 (see LICENSE).

However, the environment pulls and builds third-party container images and dependencies that are governed by their own licenses.

In particular:

  • Native builds may use the Oracle GraalVM container image container-registry.oracle.com/graalvm/native-image:25.0.1-ol10.
  • If you build/run those images, you are responsible for reviewing and complying with Oracle’s applicable license terms.

Nothing in this repository’s Apache-2.0 license changes the license terms of third-party dependencies or container base images.

🧾 Attribution, provenance, and anti-plagiarism

You’re free to fork and build upon this repository under Apache-2.0.

If you redistribute modified versions, please follow the Apache-2.0 requirements (retain notices, mark modified files, include the license).

If you cite benchmark results or reuse documentation text, please attribute the original project.

πŸ” Observability & Profiling

This project provides comprehensive observability through the Grafana LGTM stack, enhanced with continuous profiling.

The LGTM Stack

Loki - Log Aggregation

  • Centralized log collection from all services
  • Efficient log querying with LogQL
  • Correlation with metrics and traces

Grafana - Visualization

  • Pre-configured dashboards for each service
  • Unified view of logs, metrics, traces, and profiles
  • Custom dashboard creation support
  • Access: http://localhost:3000 (credentials: a / a)

Tempo - Distributed Tracing

  • OpenTelemetry-based trace collection
  • End-to-end request visualization
  • Span-to-log correlation

Mimir - Metrics Storage

  • Long-term Prometheus metrics storage
  • High-performance querying
  • Cardinality management

Pyroscope - Continuous Profiling

Pyroscope collects CPU profiles through multiple methods:

  1. Java Agent Profiling (JVM builds)

    • Accurate method-level profiling
    • Disabled by default due to overhead
    • Enable via environment variables
  2. eBPF-based Sampling

    • System-wide profiling
    • Lower overhead
    • Works across all languages
  3. HTTP Scrape Endpoints

    • Pull-based profiling from exposed metrics

Profile-to-Span Correlation: Experimental feature linking profiles to specific traces (requires Java agent).

OpenTelemetry Integration

All telemetry data flows through Alloy (Grafana's OpenTelemetry collector):

  • Batched Collection: Efficient data aggregation
  • gRPC Transport: High-performance data transmission
  • Auto-instrumentation: Minimal code changes required
  • Multi-backend Support: Send data to multiple destinations

Interesting Metrics

Use these PromQL queries in Grafana to analyze performance:

# Total HTTP RPS across all services
http_server_request_duration_seconds_count{} by (service_name)

# JVM Memory Usage
jvm_memory_used_bytes{} by (jvm_memory_pool_name, area)

# Memory after last GC
jvm_memory_used_after_last_gc_bytes{} by (jvm_memory_pool_name)

# Free Heap (MB)
sum by (service_name) (jvm_memory_committed_bytes - jvm_memory_used_bytes) / 1024 / 1024

Correlation Features

  • Log-to-Trace: Click on log entries to view associated traces
  • Trace-to-Profile: Jump from trace spans to CPU profiles (when Java agent enabled)
  • Metric-to-Trace: Navigate from metric spikes to specific requests
  • Dashboard Links: Quick navigation between related views

πŸ” Code Quality & Security

This project implements comprehensive code quality and security practices to ensure maintainable, secure, and production-ready code.

Code Quality

Checkstyle Linting

  • Configuration: Enforces Google Java Style Guide with customizations
  • Version: maven-checkstyle-plugin 3.6.0 with Checkstyle 12.2.0
  • Coverage: All Java modules (Quarkus JVM, Spring JVM Netty, Spring JVM Tomcat)
  • Integration: Runs automatically during Maven validate phase
  • Results: 0 violations across all projects

Running Checkstyle:

# For any module
cd services/quarkus/jvm
mvn checkstyle:check

# Or across all modules
cd services/quarkus/jvm && mvn checkstyle:check
cd services/spring/jvm/netty && mvn checkstyle:check
cd services/spring/jvm/tomcat && mvn checkstyle:check

Code Standards Enforced

  • Line length: Maximum 120 characters
  • Naming conventions: PascalCase for classes, camelCase for methods/variables, UPPER_SNAKE_CASE for constants
  • Javadoc: Required for all public classes and methods (20+ classes documented)
  • Formatting: Consistent indentation (4 spaces), proper whitespace, brace placement
  • Imports: No wildcards, no unused imports
  • Code organization: Proper access modifiers, logical method ordering

Documentation

  • Comprehensive Javadoc: All public APIs documented with parameter descriptions and return values
  • Class-level documentation: Describes purpose, responsibility, and usage
  • Method-level documentation: Explains functionality, parameters, exceptions
  • Inline comments: For complex logic requiring clarification

For detailed linting setup and IDE integration, see docs/LINTING_AND_CODE_QUALITY.md.

Security

Container Security

  • Non-root execution: All containers run as non-root users (UID 1001)
  • OpenShift compatible: UID/GID chosen for OpenShift compatibility
  • Minimal attack surface: Multi-stage Docker builds exclude build tools from production images
  • Proper file permissions:
    • Application JARs: 0644 (owner read/write, group/others read)
    • OpenTelemetry agents: 0640 (owner read/write, group read, others none)
    • Directories: g+rX,o-rwx (group can read/execute, no access for others)

Example from Dockerfiles:

# Create non-root user
RUN groupadd -g 1001 spring \
    && useradd -u 1001 -g spring -M -d /nonexistent -s /sbin/nologin spring

# Set permissions
RUN chown 1001:1001 /app/app.jar && chmod 0644 /app/app.jar

# Run as non-root
USER 1001

Configuration Security

  • No hardcoded secrets: All sensitive data verified to be externalized
  • Environment variable configuration: Passwords, API keys, tokens via environment variables
  • Secure defaults: Configuration files contain only non-sensitive settings
  • Verified clean: Full repository scan performed, zero hardcoded credentials found

Code Security

  • CodeQL scanning: Automated security vulnerability detection (0 alerts)
  • Dependency management: All dependencies explicitly versioned and managed
  • Interrupt handling: Proper InterruptedException handling with interrupt status restoration
  • Input validation: Appropriate for the workload (cache retrieval with controlled input)

Build Security

  • Multi-stage builds: Separate builder and runtime stages minimize final image size
  • Base image selection: Trusted sources (Amazon Corretto, Eclipse Temurin)
  • Package cleanup: Build caches removed after installation
  • Minimal dependencies: install_weak_deps=False prevents unnecessary packages

Best Practices

  • Following OWASP guidelines: Common vulnerability prevention
  • CIS Docker Benchmark alignment: Container security hardening
  • Security documentation: Comprehensive security guide available
  • Incident response procedures: Documented security event handling

For comprehensive security guidelines, configuration recommendations, and incident response procedures, see docs/SECURITY.md.

Security Summary

Aspect Status Details
Non-root containers βœ… Implemented All JVM services run as UID 1001
File permissions βœ… Configured Restrictive permissions on all artifacts
Hardcoded secrets βœ… Clean Zero secrets found in code/config
CodeQL scan βœ… Passed 0 security alerts
Multi-stage builds βœ… Implemented All Dockerfiles use multi-stage
Documentation βœ… Complete Comprehensive security guide available

Development Standards

  • Testing: Unit and integration tests available (see PR #5)
  • Documentation: All public APIs documented with Javadoc
  • Code review: All changes reviewed before merge
  • Continuous improvement: Regular dependency updates and security patches

πŸ“ Project Structure

This repository is organized for maintainability, reproducibility, and ease of contribution.

Observability-Benchmarking/
β”œβ”€β”€ compose/                 # Docker Compose orchestration files
β”‚   β”œβ”€β”€ docker-compose.yml   # Main compose file with profiles
β”‚   β”œβ”€β”€ obs.yml              # Observability stack configuration
β”‚   └── utils.yml            # Utility services
β”œβ”€β”€ services/                # REST service implementations
β”‚   β”œβ”€β”€ spring/              # Spring Boot services
β”‚   β”‚   β”œβ”€β”€ jvm/             # JVM builds (tomcat, netty variants)
β”‚   β”‚   └── native/          # GraalVM Native builds
β”‚   β”œβ”€β”€ quarkus/             # Quarkus services
β”‚   β”‚   β”œβ”€β”€ jvm/             # JVM builds (platform, virtual, reactive)
β”‚   β”‚   └── native/          # GraalVM Native builds
β”‚   └── go/                  # Go services
β”œβ”€β”€ config/                  # Configuration files
β”‚   β”œβ”€β”€ grafana/             # Grafana dashboards and provisioning
β”‚   β”œβ”€β”€ loki/                # Loki configuration
β”‚   └── pyroscope/           # Pyroscope profiling config
β”œβ”€β”€ utils/                   # Load generation tools and scripts
β”œβ”€β”€ results/                 # Benchmark results and outputs
β”œβ”€β”€ docs/                    # Additional documentation
β”‚   β”œβ”€β”€ LINTING_AND_CODE_QUALITY.md
β”‚   β”œβ”€β”€ SECURITY.md
β”‚   └── STRUCTURE.md         # Detailed project structure documentation
β”œβ”€β”€ data/                    # Persistent data volumes
β”œβ”€β”€ .env.example             # Environment variable template
β”œβ”€β”€ .run/                    # IntelliJ IDEA run configurations
β”œβ”€β”€ LICENSE                  # Apache 2.0 License
└── README.md                # This file

Key Directories

  • services/: Each subdirectory contains a complete REST service implementation with Dockerfile, source code, and README
  • compose/: Docker Compose files using profiles for flexible deployment (OBS, SERVICES, RAIN_FIRE)
  • config/: Centralized configuration for all observability tools
  • utils/: wrk2 wrappers and benchmark automation scripts
  • results/: Stores benchmark outputs with timestamps for reproducibility

For a comprehensive breakdown of the directory structure with detailed notes, see docs/STRUCTURE.md.

βš™οΈ Configuration

Environment Variables

The project uses a .env file for configuration. Copy .env.example to .env and adjust as needed:

# Load Generator Configuration
WRK_THREADS=10              # Number of load generator threads
WRK_CONNECTIONS=100         # Concurrent connections
WRK_RATE=50000             # Target requests per second
WRK_DURATION=60s           # Test duration

# Container Resource Limits
CPU_LIMIT=4                # vCPU limit per service container
MEMORY_LIMIT=2g            # Memory limit per service container

# Observability Configuration
GRAFANA_PORT=3000          # Grafana web UI port
LOKI_PORT=3100             # Loki API port
TEMPO_PORT=3200            # Tempo API port
PYROSCOPE_PORT=4040        # Pyroscope web UI port

# Java Configuration
JAVA_OPTS=-XX:+UseG1GC     # JVM options
PYROSCOPE_AGENT_ENABLED=false  # Enable/disable Java profiling agent

Service Architecture Notes

Quarkus

  • Single deployment serves all three thread modes (platform, virtual, reactive)
  • Mode selection via endpoint routing
  • Simpler configuration, fewer containers

Spring Boot

  • Separate deployments for each mode
  • Three containers per implementation (JVM/Native)
  • More complex but mode-specific optimizations possible

Recommendations for Production

⚠️ This setup is optimized for local development and benchmarking. Do NOT use these configurations in production without modifications:

  • Increase retention periods for logs and metrics
  • Add authentication to all services
  • Configure resource limits based on production workload
  • Enable TLS/SSL for all communications
  • Implement proper secrets management
  • Set up backup strategies for persistent data
  • Configure alerting for critical metrics

Heap Dumps and OOM Handling

  • Out-of-memory events automatically trigger heap dump generation
  • Heap dumps are stored in the container's working directory
  • OOM events are logged and will cause container restart
  • Review heap dumps to diagnose memory issues

πŸ“š Comprehensive Documentation

Documentation is available on GitHub Pages: Full Documentation Site

Quick Links:

The documentation includes portfolio-oriented content highlighting the skills demonstrated, modern software practices, and technical capabilities of this project.

⚠️ Known Issues

OpenTelemetry & Spring Boot 4.0

Issue: Not all metrics are available for Spring Boot applications.

Cause: The OpenTelemetry Java agent and SDK are not fully compatible with Spring Boot 4.0 yet.

Workaround: Basic metrics are still collected. Full metric support expected in future OTel releases.

Tracking: opentelemetry-java-instrumentation#14906

Alloy eBPF Profiler on WSL2

Issue: eBPF profiling doesn't work with Alloy version >= 1.11.0 on Windows WSL2 Docker.

Cause: Kernel compatibility issues between WSL2 and newer Alloy eBPF implementations.

Workaround: Use Alloy version < 1.11.0 or disable eBPF profiling (other profiling methods still work).

Tracking: grafana/alloy#4921

Profile-to-Span Correlation Reliability

Issue: Grafana's profile-to-span correlation is experimental, doesn't always work and only supported via Java agent.

Cause: Feature maturity - correlation depends on precise timing and requires Pyroscope Java agent.

Workaround: Use profiles and traces separately for analysis. Manual correlation is still valuable.

Status: Grafana team is actively improving this feature.

Reference: pyroscope/latest/configure-client/trace-span-profiles/java-span-profiles

Cold Start Effects

Issue: First benchmark run may show significantly different results.

Cause: JVM JIT compilation, container initialization, cache warming.

Workaround:

  • Run a 30-60 second warm-up before collecting benchmark data
  • For JVM workloads, allow 2-3 minutes for optimal JIT compilation
  • Always cross-reference /results data with Grafana metrics

Connectivity Errors on Startup

Issue: Services may log connection errors immediately after stack startup.

Cause: Race condition as services attempt to connect before all infrastructure is ready.

Workaround: Wait approximately 60 seconds after starting the observability stack before starting services.

Status: Normal behavior, errors self-resolve as services come online.


For troubleshooting help, please see existing issues or open a new one with:

  • System information (OS, Docker version, hardware)
  • Complete error messages and logs
  • Steps to reproduce
  • Expected vs actual behavior

🚧 Future Plans

This project is actively evolving with ambitious goals for enhanced functionality and broader coverage.

🎯 Short-term Goals (Next 3-6 months)

Additional Framework Support

  • Micronaut: Another popular JVM framework with reactive and GraalVM support
  • Helidon: Oracle's microservices framework (SE and MP editions)
  • Ktor: Kotlin-based asynchronous framework
  • Rust: Actix-web or Axum framework with OTLP integration

Enhanced Observability

  • JFR (Java Flight Recorder) profiling for native builds
  • Custom Grafana dashboards with comparative views
  • Alerting rules for performance regressions
  • Trace exemplars linking metrics to specific traces

Profiling Improvements

  • Allocation profiling in addition to CPU profiling
  • Lock contention analysis for concurrent workloads
  • Better profile-to-span correlation (as Grafana matures)

🌐 Medium-term Goals (6-12 months)

Kubernetes & Cloud Native

  • Helm charts for easy Kubernetes deployment
  • ArgoCD manifests for GitOps workflows
  • Cluster-scale benchmarking with distributed load generation
  • Multi-node performance testing scenarios
  • Cloud provider integrations (AWS, GCP, Azure)

CI/CD Integration

  • GitHub Actions workflows for automated benchmarking
  • Performance regression detection in PRs
  • CSV/JSON export of benchmark results
  • Historical trend analysis and visualization
  • Automated Docker image builds and registry publishing

Protocol Support

  • HTTP/2 HTTP/3 benchmarking Successors of HTTP/1.1
  • gRPC benchmarking alongside HTTP REST
  • WebSocket performance testing
  • GraphQL endpoint support
  • Multiple payload sizes and complexity levels

πŸš€ Long-term Vision (12+ months)

Advanced Features

  • Machine learning-based performance anomaly detection
  • Cost analysis comparing cloud deployment scenarios
  • Energy efficiency metrics (especially for native vs JVM)
  • Multi-datacenter latency simulation
  • Chaos engineering integration (latency injection, failures)

Ecosystem Expansion

  • Python frameworks (FastAPI, Django, Flask)
  • Node.js frameworks (Express, Fastify, NestJS)
  • .NET implementations (ASP.NET Core minimal APIs)
  • Polyglot microservices benchmark scenarios

Community & Documentation

  • Interactive tutorials and workshops
  • Video walkthroughs of setup and analysis
  • Best practices guide for each framework
  • Community-contributed implementations
  • Academic paper on methodology and findings

🀝 How You Can Help

Interested in contributing to these goals? See the Contributing section below or open an issue to discuss:

  • Which frameworks/languages you'd like to see
  • Feature requests and improvements
  • Documentation enhancements
  • Bug reports and fixes

🀝 Contributing

Contributions are welcome and appreciated! Whether you're fixing bugs, adding features, improving documentation, or adding new framework implementations, your help makes this project better.

How to Contribute

  1. Fork the repository and clone your fork locally
  2. Create a feature branch: git checkout -b feature/your-feature-name
  3. Make your changes following the project's style and conventions
  4. Test your changes thoroughly
  5. Commit your changes: git commit -m "Add: brief description of changes"
  6. Push to your fork: git push origin feature/your-feature-name
  7. Open a Pull Request with a clear description of your changes

Adding a New Implementation

To add a new framework or language implementation, please include:

  • Source code in the appropriate services/<framework>/ directory
  • Dockerfile with clear base image and build instructions
  • README.md describing the implementation specifics
  • Docker Compose entry in the main compose file
  • Benchmark script or wrk2 configuration
  • Results from your benchmarking runs (if applicable)

Code Style Guidelines

  • Java: Follow Google Java Style Guide (enforced by Checkstyle)
  • Go: Use gofmt and follow standard Go conventions
  • Docker: Multi-stage builds preferred, pin versions explicitly
  • Documentation: Use clear headers, code examples, and practical explanations

Testing Contributions

Before submitting:

  • Ensure Docker Compose builds successfully
  • Test that services start without errors
  • Verify observability data flows to Grafana
  • Run a benchmark to confirm functionality
  • Check that no credentials or secrets are committed
  • Run Checkstyle on Java code: mvn checkstyle:check

Reporting Bugs

When reporting issues, please include:

  • System details: OS, Docker version, hardware specs
  • Steps to reproduce: Clear, minimal reproduction steps
  • Expected behavior: What should happen
  • Actual behavior: What actually happens
  • Logs: Relevant log excerpts (use code blocks)
  • Screenshots: If applicable, especially for UI issues

Feature Requests

We love new ideas! When proposing features:

  • Check existing issues to avoid duplicates
  • Describe the use case and benefit
  • Consider implementation complexity
  • Be open to discussion and refinement

Code of Conduct

  • Be respectful and inclusive
  • Focus on constructive feedback
  • Help newcomers and encourage questions
  • Give credit where credit is due

πŸ“„ License

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

License Summary

  • βœ… Commercial use allowed
  • βœ… Modification allowed
  • βœ… Distribution allowed
  • βœ… Patent use allowed
  • βœ… Private use allowed
  • ⚠️ License and copyright notice required
  • ⚠️ State changes required
  • ❌ Trademark use not allowed
  • ❌ Liability and warranty not provided

SPDX-License-Identifier: Apache-2.0


πŸ™ Acknowledgments

This project builds upon amazing open-source tools and frameworks. Special thanks to:

Observability Stack

  • Grafana - The open observability platform
  • Loki - Log aggregation system
  • Tempo - High-scale distributed tracing
  • Mimir - Scalable long-term Prometheus storage
  • Pyroscope - Continuous profiling platform
  • Alloy - OpenTelemetry distribution

Instrumentation

Frameworks & Tools

  • Spring Boot - Java application framework
  • Quarkus - Supersonic Subatomic Java
  • wrk2 - Constant throughput HTTP benchmarking tool
  • Docker - Containerization platform

Community

  • All contributors who have helped improve this project
  • The broader observability and performance engineering community

πŸ“§ Contact & Support

Getting Help

  • πŸ“– Read the docs/STRUCTURE.md for detailed architecture
  • πŸ› Check Known Issues for common problems
  • Open an issue for bugs or questions
  • 🌟 Star the repo if you find it useful!

About

Docker container setup containing REST services for benchmarking with wrk2 and complete observability with Grafana stack

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published