Skip to content

Commit d44c8ab

Browse files
feat: add one-command demo that populates Grafana
compose.demo.yml runs a tiny auto-instrumented FastAPI service plus a curl load loop, emitting real OTLP traces, metrics, and trace-correlated logs. 'just demo' brings up the core stack with the overlay.
1 parent 93f14dc commit d44c8ab

4 files changed

Lines changed: 95 additions & 0 deletions

File tree

compose.demo.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Demo overlay: a tiny auto-instrumented FastAPI service plus a load
2+
# generator, so the stack has real traces, metrics, and correlated logs
3+
# to show. Not for production.
4+
#
5+
# just demo # core stack + this overlay
6+
# just demo-down
7+
8+
services:
9+
demo-api:
10+
build: ./demo
11+
restart: unless-stopped
12+
depends_on: [ otel-collector ]
13+
environment:
14+
OTEL_SERVICE_NAME: demo-api
15+
OTEL_RESOURCE_ATTRIBUTES: env=demo
16+
OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4318
17+
OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf
18+
OTEL_TRACES_EXPORTER: otlp
19+
OTEL_METRICS_EXPORTER: otlp
20+
OTEL_LOGS_EXPORTER: otlp
21+
# Ship Python log records via OTLP with trace context attached.
22+
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED: "true"
23+
OTEL_METRIC_EXPORT_INTERVAL: "10000"
24+
logging:
25+
driver: json-file
26+
options:
27+
max-size: "10m"
28+
max-file: "3"
29+
30+
demo-load:
31+
image: curlimages/curl:8.21.0
32+
restart: unless-stopped
33+
depends_on: [ demo-api ]
34+
command:
35+
- sh
36+
- -c
37+
- |
38+
while true; do
39+
curl -s -o /dev/null demo-api:8000/
40+
curl -s -o /dev/null demo-api:8000/work
41+
sleep 1
42+
done
43+
logging:
44+
driver: json-file
45+
options:
46+
max-size: "10m"
47+
max-file: "3"

demo/Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM python:3.13-slim
2+
3+
RUN pip install --no-cache-dir \
4+
fastapi==0.139.0 \
5+
uvicorn==0.49.0 \
6+
opentelemetry-distro==0.64b0 \
7+
opentelemetry-exporter-otlp==1.43.0 \
8+
opentelemetry-instrumentation-fastapi==0.64b0
9+
10+
WORKDIR /app
11+
COPY app.py .
12+
13+
CMD ["opentelemetry-instrument", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

demo/app.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Minimal FastAPI service for the demo overlay. All telemetry (traces,
2+
# metrics, logs with trace context) comes from OTel auto-instrumentation —
3+
# see compose.demo.yml. No OTel code needed here.
4+
import logging
5+
import random
6+
import time
7+
8+
from fastapi import FastAPI, HTTPException
9+
10+
log = logging.getLogger("demo-api")
11+
app = FastAPI()
12+
13+
14+
@app.get("/")
15+
def root():
16+
return {"ok": True}
17+
18+
19+
@app.get("/work")
20+
def work():
21+
time.sleep(random.uniform(0.02, 0.3))
22+
if random.random() < 0.1: # NOTE: fixed 10% error rate, enough to light up RED panels
23+
log.error("work failed: upstream flaked")
24+
raise HTTPException(status_code=500, detail="upstream flaked")
25+
log.info("work done")
26+
return {"ok": True}

justfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ up-tunnel:
1414
down:
1515
docker compose down --remove-orphans
1616

17+
# Core stack + a demo telemetry source (see compose.demo.yml), then look at
18+
# Grafana: http://localhost:3000
19+
demo:
20+
docker compose -f compose.yml -f compose.demo.yml up -d --build
21+
22+
demo-down:
23+
docker compose -f compose.yml -f compose.demo.yml down
24+
1725
logs service="":
1826
docker compose logs -f {{service}}
1927

@@ -29,3 +37,4 @@ pull:
2937
# Tail a service's logs as JSON, decoded. Useful before Grafana is set up.
3038
tail service:
3139
docker compose logs -f --no-log-prefix {{service}} | jq -R 'fromjson? // .'
40+

0 commit comments

Comments
 (0)