LearnCen Docs
Guides 4 min read v3

Observability-Driven Testing Environment

Enterprise-grade observability testing with OpenTelemetry, Jaeger, Prometheus, Grafana, and Tracetest.

What's Inside

Tool Version Purpose
OpenTelemetry SDK Latest Distributed tracing & metrics instrumentation (Python + JS)
Jaeger 1.57.0 Trace backend — visualize, search, and analyze distributed traces
Prometheus 2.53.0 Metrics collection, PromQL queries, SLO validation
Grafana 11.1.0 OSS Pre-provisioned dashboards for request rate, latency, errors
Tracetest 1.4.2 Trace-based testing — assert on spans and attributes
k6 0.52.0 Load testing with trace context propagation
Python 3.x + venv Flask demo app, pytest, Locust
Node.js 20 LTS OpenTelemetry JS SDK, json-server
Go 1.22 Go-based tooling support

Quick Start

# Start the observability stack (Jaeger + Prometheus + Grafana)
odt-stack-up

# Start the instrumented demo app
odt-demo-up

# Run trace-based tests
odt-test

# Validate SLOs against Prometheus
odt-slo

# Run k6 load test with trace propagation
odt-load

# Detect latency regressions
odt-regression

Helper Commands

Command What it does
odt-stack-up Start Jaeger + Prometheus + Grafana
odt-stack-down Stop the observability stack
odt-grafana Open/restart Grafana dashboards
odt-demo-up Start the instrumented Flask demo app
odt-test [file] Run trace-based tests (pytest)
odt-slo Validate SLOs against Prometheus metrics
odt-load Run k6 load test with trace propagation
odt-regression Detect latency regressions vs baselines
odt-chaos <mode> Inject faults: latency, errors, db-failure, stop
odt-traces [service] Query recent traces from Jaeger
odt-metrics [query] Query Prometheus with PromQL
odt-help Show all available commands

Accessing Services

Each service is exposed via a subdomain on your workspace URL. After running odt-stack-up, access them from the preview panel or directly:

Service Subdomain Purpose
Jaeger UI jaeger.{your-workspace-url} Trace visualization and search
Prometheus odt-prometheus.{your-workspace-url} Metrics queries and PromQL
Grafana odt-grafana.{your-workspace-url} Pre-built dashboards (login: admin/admin or skip)
Demo App odt-demoapp.{your-workspace-url} Instrumented Flask API

Note: The exact URLs are shown in the Preview panel on the right side of your workspace. Click any preview URL to open the service in a new tab.

Exercises

  1. Instrument Your First App — Add OpenTelemetry tracing, export to Jaeger, view in Grafana
  2. Trace-Based Testing — Assert on span attributes and trace structure
  3. SLO Validation — Define SLOs in YAML, validate against Prometheus, confirm in Grafana
  4. Latency Regression Detection — Define baselines, detect regressions, visualize spikes
  5. Load Testing with Observability — Run k6 while watching Grafana dashboards live
  6. Custom Metrics & Alerts — Add Prometheus metrics, write PromQL alert rules
  7. Distributed Tracing Across Services — Propagate context, validate end-to-end traces
  8. CI/CD Integration — Run observability tests in pipelines, fail on SLO violations
  9. Incident Simulation & Root Cause Analysis — Inject chaos (latency/errors/db-failure), diagnose with traces

Project Structure

workspace/
├── app/                    # Instrumented demo application
│   └── demo_app.py        # Flask + OpenTelemetry + Prometheus metrics
├── tests/                  # Trace-based test suites
│   ├── test_traces.py     # Jaeger trace assertions
│   ├── test_slo.py        # SLO validation against Prometheus
│   └── test_regression.py # Latency regression detection
├── slos/                   # SLO definitions
│   └── slo_definitions.yaml
├── load/                   # Load test scripts
│   └── k6_traces.js       # k6 with trace propagation
├── config/                 # Prometheus + OTel config
│   └── prometheus.yml
├── tracetest/              # Tracetest definitions
│   └── trace_test.yaml
├── reports/                # Test outputs
└── README.md

Grafana Dashboard

The workspace comes with a pre-provisioned Observability Overview dashboard (no login required). After running odt-stack-up, open the Grafana preview URL to see:

  • Request Rate — Total requests per second over time
  • Error Rate — Percentage of failed requests with threshold indicators
  • Latency P50 — Median response time in milliseconds
  • Latency P95 — 95th percentile response time
  • Latency P99 — 99th percentile response time
  • Requests by Endpoint — Breakdown of traffic per API route

Demo App Endpoints

The instrumented Flask app exposes these endpoints with full OpenTelemetry tracing:

Method Endpoint Description
GET / Homepage — lists all available endpoints
GET /users List all users (traced DB query)
GET /users/:id Get user by ID (traced)
POST /users Create a user (traced INSERT)
GET /health Health check
GET /metrics Prometheus metrics endpoint
GET /slow Intentionally slow (for regression testing)
POST /chaos/inject Inject chaos fault (mode: latency, errors, db-failure)
POST /chaos/stop Stop active chaos injection
GET /chaos/status Check current chaos state

Tips

  • Always run odt-stack-up before odt-demo-up — the app needs Jaeger and Prometheus running
  • Grafana dashboards update in real-time — open them before running load tests
  • Use odt-traces to quickly query Jaeger traces from the terminal
  • SLO definitions are in slos/slo_definitions.yaml — add your own and run odt-slo
  • The /slow endpoint is intentionally slow for regression testing exercises
  • Use Ctrl+Shift+B keyboard shortcut to start the observability stack
  • Traces take 2-3 seconds to appear in Jaeger after a request
  • All services communicate internally on localhost — the ingress subdomains proxy to the correct ports

Security

  • Root access is restricted. Use sudo apt install <package> for system packages.
  • pip, npm, python3, docker, apt, and apt-get are whitelisted for sudo access.