Overview¶
PerfShop is a pedagogical chaos engineering platform: an e-commerce shop deliberately instrumented so that an instructor can inject performance, security, business, functional or scripting anomalies on the fly, and so that students can observe the consequences in real time through a complete observability stack.
This page gives the level 1 view: who interacts with what, and what the major functional blocks are. The following pages (stack, deployment, database, auth, multi-session, docker, network) progressively dive into the details.
Source of truth
This entire section reflects the actual state of the deployment Docker Compose files (docker-compose.desktop.yml for Docker Desktop, docker-compose.build.yml for Linux/VPS), the JPA backend entities, and the configuration files of the observability and QA services. No information has been invented; every detail is verifiable in the source code.
Actors and systems¶
C4Context
title PerfShop — Functional context (C4 level 1)
Person(student, "Student", "Follows a pedagogical journey<br/>(BAC1 to BAC5)")
Person(instructor, "Instructor", "Activates chaos types, follows sessions,<br/>analyzes metrics")
Person(client, "End customer<br/>(role played)", "Browses the shop,<br/>places an order")
System_Boundary(perfshop, "PerfShop") {
System(shop, "E-commerce shop", "Spring Boot + React<br/>Catalog, cart, checkout")
System(chaos, "Chaos Engine", "6 anomaly families<br/>injectable on the fly")
System(obs, "Observability", "Prometheus, Grafana,<br/>Loki, Tempo, Pyroscope,<br/>OpenSearch")
System(qa, "QA stack", "Squash TM, Selenium,<br/>JMeter, Forgejo,<br/>Polyglot Test Runner")
System(ped, "Pedagogical engine", "Enigmas, sessions,<br/>agent code, stars")
}
Rel(client, shop, "Buys", "HTTPS")
Rel(student, ped, "Plays the enigmas", "HTTPS")
Rel(student, obs, "Watches metrics", "Student Grafana")
Rel(instructor, chaos, "Activates / deactivates", "X-Admin-Token")
Rel(instructor, obs, "Analyzes", "Instructor Grafana")
Rel(instructor, qa, "Runs tests", "Web UI")
Rel(chaos, shop, "Injects anomalies", "Spring Interceptor")
Rel(shop, obs, "Metrics + traces + logs", "Prometheus / OTLP / Docker")
Rel(qa, shop, "Selenium / JMeter tests", "HTTP")
Three usages cross paths in the same platform:
- The end customer is a character played by the student or by a test script: they browse the e-commerce shop, add products to the cart, place an order. This is the "normal user role".
- The student follows a pedagogical journey structured in 5 levels (BAC1 → BAC5). They have their own page (
chaos student page) where they discover the enigmas, validate steps and observe the consequences of the chaos types activated by the instructor. They access the "Student" Grafana dashboards without authentication. - The instructor drives the entire session via the
chaos-admininterface and theadminportal. They activate anomalies, manage accounts, open/close access to the student page, analyze sessions and access the reserved "Instructor" Grafana dashboards.
Major functional blocks¶
flowchart TB
subgraph CORE["Application core"]
direction LR
FE["perfshop-frontend<br/>React 18 + Vite"]
BE["perfshop-app<br/>Spring Boot 3.2 + Java 21"]
DB[("perfshop-db<br/>MySQL 8")]
FE -->|REST + session cookies| BE
BE --> DB
end
subgraph CHAOS["Chaos control"]
direction LR
CADM["perfshop-chaos-admin<br/>static nginx"]
ADM["perfshop-admin<br/>static nginx"]
MON["perfshop-monitoring<br/>Node + Express"]
end
subgraph OBS["Observability"]
direction LR
PROM["Prometheus"]
GRAF["Grafana"]
LOKI["Loki + Promtail"]
TEMPO["Tempo"]
PYRO["Pyroscope"]
OS["OpenSearch + Vector"]
end
subgraph QA["QA stack"]
direction LR
SQ["Squash TM + Orchestrator"]
SEL["Selenium Grid"]
TR["Test Runner<br/>RF + pytest"]
JM["JMeter + JMeter UI"]
FG["Forgejo"]
SU["Scripts UI"]
end
CADM -->|X-Admin-Token| BE
ADM -->|X-Admin-Token| BE
MON -->|2s polling| BE
BE -->|"/actuator/prometheus<br/>5s scrape"| PROM
BE -->|OTLP gRPC 4317| TEMPO
BE -->|JFR push| PYRO
PROM --> GRAF
LOKI --> GRAF
TEMPO --> GRAF
PYRO --> GRAF
OS -->|Dashboards| GRAF
SQ --> SEL
SQ --> TR
TR -->|HTTP| FE
JM -->|HTTP| BE
SU --> FG
SU --> TR
Five blocks coexist on the same perfshop-network Docker network. Each block is documented on its own page:
| Block | Reference page | Number of services |
|---|---|---|
| Application core | Technical stack, Database schema | 3 |
| Chaos control | Authentication | 3 |
| Observability | Overview | 9 |
| QA stack | Overview | 8 |
| Cross-cutting tools | Docker Compose | 9 |
Main data flows¶
PerfShop handles four parallel telemetry flows, each with its own protocol and storage.
flowchart LR
APP["perfshop-app<br/>Spring Boot"]
APP -->|"/actuator/prometheus<br/>HTTP scrape 5s"| MET[("Prometheus<br/>retention 7d / 5GB")]
APP -->|"OTLP gRPC<br/>:4317"| TRC[("Tempo<br/>local blocks")]
APP -->|"JFR push HTTP<br/>:4040"| PRF[("Pyroscope<br/>filesystem")]
APP -->|"stdout / stderr"| DOC{"Docker<br/>logging driver"}
DOC --> PT["Promtail<br/>(docker SD)"] --> LOG[("Loki<br/>retention 7d")]
DOC --> VEC["Vector<br/>(VRL transform)"] --> OS[("OpenSearch<br/>perfshop-spring*")]
MET --> GRAF["Grafana<br/>dashboards"]
LOG --> GRAF
TRC --> GRAF
PRF --> GRAF
OS --> OSD["OpenSearch<br/>Dashboards"]
- Metrics: Prometheus scrapes
perfshop-app:9090/actuator/prometheusevery 5 seconds (perfshop-backendjob),perfshop-monitoring:3001/metricsfor Docker metrics (perfshop-dockerjob), andperfshop-jmeter:9270during JMeter test runs (jmeterjob). Details inobservability/prometheus.md. - Traces: the OpenTelemetry Java agent is embedded in the
perfshop-backendimage and exports spans via OTLP gRPC toperfshop-tempo:4317. Details inobservability/tempo.md. - Continuous profiling: the Pyroscope Java agent is also embedded in the image and pushes JFR-format profiles to
perfshop-pyroscope:4040. Details inobservability/pyroscope.md. - Logs: they are collected twice in parallel. Promtail reads the Docker socket to feed Loki; Vector reads the same socket to feed OpenSearch (with deeper VRL parsing that isolates the
chaos_family,chaos_level,scenario_idfields). The two sinks deliberately coexist as a pedagogical demonstration.
Request lifecycle¶
An HTTP request reaching the backend goes through several layers before reaching the business controller.
sequenceDiagram
autonumber
participant N as Browser
participant FE as perfshop-frontend<br/>(nginx)
participant BE as perfshop-app<br/>(Tomcat)
participant LI as LicenseInterceptor
participant CI as ChaosInterceptor
participant CT as Controller
participant DB as MySQL
participant T as Tempo / Pyroscope
N->>FE: GET /products
FE->>BE: GET /api/products
BE->>LI: handle()
alt License missing
LI-->>N: HTTP 402 Payment Required
else License valid
LI->>CI: handle()
CI->>CI: Inject active anomalies
CI->>CT: ProductController.list()
CT->>DB: SELECT (HikariCP)
DB-->>CT: rows
CT-->>N: 200 JSON
BE->>T: OTLP span + CPU sample
end
The interceptor order is locked in WebConfig.java:
LicenseInterceptor(order 1) — verifies that a valid license is present. Without a license, any request to/api/**is rejected with anHTTP 402 Payment Required. Only the/actuator/**endpoints are excluded from this check.ChaosInterceptor(order 2) — only reached if the license is valid. It inspects the state of the active chaos types and injects the anomalies (artificial latency, random exception, response corruption, etc.) before letting the request reach the controller.
CORS is handled separately by CorsConfig.java, which dynamically authorizes the origins listed in the CORS_ALLOWED_ORIGINS compose variable and explicitly exposes the headers used by Scripting Chaos (X-Session-Token, X-Action-Token, X-CSRF-Token, X-Step-Token, X-Signature, X-Request-ID, X-Key-Hint).
Pedagogical games hub¶
PerfShop also embeds a pedagogical games hub unlocked at the end of the BAC journey. It is a static web application separate from the shop, built in modern JavaScript (ES modules, Vite 5) and based on the Phaser 3.80 (2D games, e.g. Server Defender) and Three.js 0.160 (3D rendering) frameworks. The hub is served by nginx as a standalone container and has no backend dependency: all gameplay runs in the browser. See the future games-dedicated section for the details of the internal architecture.
To go further¶
- Detailed technical stack — exact versions, roles, Docker images
- Deployment topology — Docker Desktop, Linux/VPS and local builds
- Database schema — JPA entities and Flyway migrations
- Authentication flow — HTTP sessions, X-Admin-Token, X-Student-Token
- Pedagogical multi-session — DB write-through and optional memory cache
- Docker Compose — exhaustive analysis of the 32 services
- Network and domains — Docker bridge, reverse proxy, DNS conventions