From 93f14dc6bbb34805cd73148fd93aec8f6bdf3426 Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 12:39:06 +0200 Subject: [PATCH 01/15] feat: run core stack without a tunnel token Move cloudflared into an optional compose.tunnel.yml overlay (pinned to 2026.6.1 instead of :latest) so a fresh clone + .env.example + 'just up' brings up Grafana locally. 'just up-tunnel' is the production path. --- .env.example | 1 + compose.tunnel.yml | 21 +++++++++++++++++++++ compose.yml | 12 ------------ justfile | 7 ++++++- 4 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 compose.tunnel.yml diff --git a/.env.example b/.env.example index a872972..7e9e6d9 100644 --- a/.env.example +++ b/.env.example @@ -6,5 +6,6 @@ GRAFANA_ADMIN_PASSWORD=change-me # GRAFANA_ROOT_URL=https://grafana.example.com GRAFANA_ROOT_URL=http://localhost:3000 +# Only needed for `just up-tunnel` (production exposure via Cloudflare Tunnel). # From: Cloudflare Zero Trust → Networks → Tunnels → → Configure → token CLOUDFLARE_TUNNEL_TOKEN= diff --git a/compose.tunnel.yml b/compose.tunnel.yml new file mode 100644 index 0000000..106896e --- /dev/null +++ b/compose.tunnel.yml @@ -0,0 +1,21 @@ +# Production overlay: expose Grafana (and the OTLP endpoints) via Cloudflare +# Tunnel. Requires CLOUDFLARE_TUNNEL_TOKEN in .env. +# +# just up-tunnel +# +# Token-based tunnel: routes are configured in the Cloudflare Zero Trust +# dashboard. Create a tunnel at dash.cloudflare.com → Zero Trust → Networks → +# Tunnels, then set the public hostnames there (e.g. grafana.example.com → +# http://grafana:3000, otlp.example.com → http://otel-collector:4318). + +services: + cloudflared: + image: cloudflare/cloudflared:2026.6.1 + restart: unless-stopped + depends_on: [ grafana, otel-collector ] + command: tunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN:?set CLOUDFLARE_TUNNEL_TOKEN in .env} + logging: + driver: json-file + options: + max-size: "10m" + max-file: "3" diff --git a/compose.yml b/compose.yml index e1089a7..a834601 100644 --- a/compose.yml +++ b/compose.yml @@ -82,18 +82,6 @@ services: GF_FEATURE_TOGGLES_ENABLE: traceqlEditor,metricsSummary,traceToProfiles logging: *default-logging - cloudflared: - image: cloudflare/cloudflared:latest - restart: unless-stopped - depends_on: [ grafana, otel-collector ] - # Token-based tunnel: routes are configured in the Cloudflare Zero Trust dashboard. - # Create a tunnel at dash.cloudflare.com → Zero Trust → Networks → Tunnels, - # then set the public hostnames there (e.g. grafana.example.com → http://grafana:3000, - # otlp.example.com → http://otel-collector:4318). - command: tunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN:?set CLOUDFLARE_TUNNEL_TOKEN in .env} - logging: *default-logging - pull_policy: always - volumes: loki_data: tempo_data: diff --git a/justfile b/justfile index f80ccdb..f03a9b6 100644 --- a/justfile +++ b/justfile @@ -3,11 +3,16 @@ set dotenv-load default: @just --list +# Core stack (no tunnel; Grafana at http://localhost:3000) up: docker compose up -d +# Core stack + Cloudflare Tunnel (production; needs CLOUDFLARE_TUNNEL_TOKEN) +up-tunnel: + docker compose -f compose.yml -f compose.tunnel.yml up -d + down: - docker compose down + docker compose down --remove-orphans logs service="": docker compose logs -f {{service}} From d44c8abc03a8d27c985c30aade97c1e54ecf43cb Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 12:46:58 +0200 Subject: [PATCH 02/15] 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. --- compose.demo.yml | 47 +++++++++++++++++++++++++++++++++++++++++++++++ demo/Dockerfile | 13 +++++++++++++ demo/app.py | 26 ++++++++++++++++++++++++++ justfile | 9 +++++++++ 4 files changed, 95 insertions(+) create mode 100644 compose.demo.yml create mode 100644 demo/Dockerfile create mode 100644 demo/app.py diff --git a/compose.demo.yml b/compose.demo.yml new file mode 100644 index 0000000..32f6136 --- /dev/null +++ b/compose.demo.yml @@ -0,0 +1,47 @@ +# Demo overlay: a tiny auto-instrumented FastAPI service plus a load +# generator, so the stack has real traces, metrics, and correlated logs +# to show. Not for production. +# +# just demo # core stack + this overlay +# just demo-down + +services: + demo-api: + build: ./demo + restart: unless-stopped + depends_on: [ otel-collector ] + environment: + OTEL_SERVICE_NAME: demo-api + OTEL_RESOURCE_ATTRIBUTES: env=demo + OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4318 + OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf + OTEL_TRACES_EXPORTER: otlp + OTEL_METRICS_EXPORTER: otlp + OTEL_LOGS_EXPORTER: otlp + # Ship Python log records via OTLP with trace context attached. + OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED: "true" + OTEL_METRIC_EXPORT_INTERVAL: "10000" + logging: + driver: json-file + options: + max-size: "10m" + max-file: "3" + + demo-load: + image: curlimages/curl:8.21.0 + restart: unless-stopped + depends_on: [ demo-api ] + command: + - sh + - -c + - | + while true; do + curl -s -o /dev/null demo-api:8000/ + curl -s -o /dev/null demo-api:8000/work + sleep 1 + done + logging: + driver: json-file + options: + max-size: "10m" + max-file: "3" diff --git a/demo/Dockerfile b/demo/Dockerfile new file mode 100644 index 0000000..d3c9bee --- /dev/null +++ b/demo/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.13-slim + +RUN pip install --no-cache-dir \ + fastapi==0.139.0 \ + uvicorn==0.49.0 \ + opentelemetry-distro==0.64b0 \ + opentelemetry-exporter-otlp==1.43.0 \ + opentelemetry-instrumentation-fastapi==0.64b0 + +WORKDIR /app +COPY app.py . + +CMD ["opentelemetry-instrument", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/demo/app.py b/demo/app.py new file mode 100644 index 0000000..2814482 --- /dev/null +++ b/demo/app.py @@ -0,0 +1,26 @@ +# Minimal FastAPI service for the demo overlay. All telemetry (traces, +# metrics, logs with trace context) comes from OTel auto-instrumentation — +# see compose.demo.yml. No OTel code needed here. +import logging +import random +import time + +from fastapi import FastAPI, HTTPException + +log = logging.getLogger("demo-api") +app = FastAPI() + + +@app.get("/") +def root(): + return {"ok": True} + + +@app.get("/work") +def work(): + time.sleep(random.uniform(0.02, 0.3)) + if random.random() < 0.1: # NOTE: fixed 10% error rate, enough to light up RED panels + log.error("work failed: upstream flaked") + raise HTTPException(status_code=500, detail="upstream flaked") + log.info("work done") + return {"ok": True} diff --git a/justfile b/justfile index f03a9b6..c242216 100644 --- a/justfile +++ b/justfile @@ -14,6 +14,14 @@ up-tunnel: down: docker compose down --remove-orphans +# Core stack + a demo telemetry source (see compose.demo.yml), then look at +# Grafana: http://localhost:3000 +demo: + docker compose -f compose.yml -f compose.demo.yml up -d --build + +demo-down: + docker compose -f compose.yml -f compose.demo.yml down + logs service="": docker compose logs -f {{service}} @@ -29,3 +37,4 @@ pull: # Tail a service's logs as JSON, decoded. Useful before Grafana is set up. tail service: docker compose logs -f --no-log-prefix {{service}} | jq -R 'fromjson? // .' + From 771bc81ee5c78a28aa53967b691757af00ce7ae8 Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 12:46:58 +0200 Subject: [PATCH 03/15] feat: add Prometheus alert rules Target-down, OTel export failures, and >5% span error rate (from Tempo span metrics). Evaluated by Prometheus, surfaced in Grafana Alerting; no Alertmanager to keep the stack minimal. --- compose.yml | 1 + config/alerts/stack.yaml | 41 ++++++++++++++++++++++++++++++++++++++++ config/prometheus.yaml | 3 +++ 3 files changed, 45 insertions(+) create mode 100644 config/alerts/stack.yaml diff --git a/compose.yml b/compose.yml index a834601..34be901 100644 --- a/compose.yml +++ b/compose.yml @@ -55,6 +55,7 @@ services: restart: unless-stopped volumes: - ./config/prometheus.yaml:/etc/prometheus/prometheus.yaml:ro + - ./config/alerts:/etc/prometheus/alerts:ro - prometheus_data:/prometheus command: - --config.file=/etc/prometheus/prometheus.yaml diff --git a/config/alerts/stack.yaml b/config/alerts/stack.yaml new file mode 100644 index 0000000..c8016e3 --- /dev/null +++ b/config/alerts/stack.yaml @@ -0,0 +1,41 @@ +# Prometheus alert rules for the stack itself plus RED-style alerts on the +# span metrics Tempo derives from traces. Evaluated by Prometheus; visible in +# Grafana under Alerting → Alert rules (Prometheus datasource). +# No Alertmanager: single-host stack, alerts are surfaced in Grafana. +# Validated by `just check` (promtool check rules). + +groups: + - name: stack-health + rules: + - alert: TargetDown + expr: up == 0 + for: 2m + labels: + severity: critical + annotations: + summary: "Scrape target {{ $labels.job }} is down" + description: "Prometheus cannot scrape {{ $labels.instance }} (job {{ $labels.job }}) for 2 minutes." + + - alert: OtelExportFailures + expr: sum by (exporter) (rate(otelcol_exporter_send_failed_spans_total[5m])) > 0 + or sum by (exporter) (rate(otelcol_exporter_send_failed_metric_points_total[5m])) > 0 + or sum by (exporter) (rate(otelcol_exporter_send_failed_log_records_total[5m])) > 0 + for: 5m + labels: + severity: warning + annotations: + summary: "OTel Collector failing to export via {{ $labels.exporter }}" + description: "The collector has been failing to deliver telemetry to a backend for 5 minutes. Check `just logs otel-collector`." + + - name: service-red + rules: + - alert: HighErrorRate + expr: > + sum by (service) (rate(traces_spanmetrics_calls_total{status_code="STATUS_CODE_ERROR"}[5m])) + / sum by (service) (rate(traces_spanmetrics_calls_total[5m])) > 0.05 + for: 5m + labels: + severity: warning + annotations: + summary: "{{ $labels.service }} error rate above 5%" + description: "More than 5% of spans from {{ $labels.service }} report errors (from Tempo span metrics)." diff --git a/config/prometheus.yaml b/config/prometheus.yaml index fab2400..1d4c137 100644 --- a/config/prometheus.yaml +++ b/config/prometheus.yaml @@ -4,6 +4,9 @@ global: external_labels: origin: monitoring-host +rule_files: + - /etc/prometheus/alerts/*.yaml + # Apps push metrics via OTLP (through the collector). Scrape only infra we host. scrape_configs: - job_name: prometheus From 50e84768b615aae460ecaf5f3a97549d5aafc27a Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 12:46:58 +0200 Subject: [PATCH 04/15] ci: add 'just check' quality gate and CI workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check validates compose files (incl. overlays), Prometheus config+rules via promtool, the collector config via otelcol validate, yamllint, actionlint, and dashboard JSON — all in pinned containers, no host installs. CI runs 'just check' plus a smoke job that waits for Grafana /api/health. Also fixes a trailing space yamllint caught in dependabot.yml. --- .github/dependabot.yml | 2 +- .github/workflows/ci.yml | 28 ++++++++++++++++++++++++++++ justfile | 14 ++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7a8dfc9..39e6d88 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,7 @@ version: 2 updates: - package-ecosystem: "docker-compose" - directory: "/" + directory: "/" schedule: interval: "weekly" groups: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..11fbdaf --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +# Thin wrapper around the `just` contract: everything CI runs, you can run +# locally with the same command. +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: extractions/setup-just@v4 + - run: cp .env.example .env + - run: just check + + smoke: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: extractions/setup-just@v4 + - run: cp .env.example .env + - run: just up + - name: Wait for Grafana to report healthy + run: timeout 120 sh -c 'until curl -sf http://localhost:3000/api/health; do sleep 3; done' + - run: just down diff --git a/justfile b/justfile index c242216..c86c931 100644 --- a/justfile +++ b/justfile @@ -38,3 +38,17 @@ pull: tail service: docker compose logs -f --no-log-prefix {{service}} | jq -R 'fromjson? // .' +# Validate everything. All validators run in containers — no host installs. +check: + docker compose config -q + CLOUDFLARE_TUNNEL_TOKEN=dummy docker compose -f compose.yml -f compose.tunnel.yml config -q + docker compose -f compose.yml -f compose.demo.yml config -q + docker run --rm -v ./config/prometheus.yaml:/etc/prometheus/prometheus.yaml:ro -v ./config/alerts:/etc/prometheus/alerts:ro --entrypoint promtool prom/prometheus:v3.11.2 check config /etc/prometheus/prometheus.yaml + docker run --rm -v ./config/otel-collector.yaml:/etc/otelcol/config.yaml:ro otel/opentelemetry-collector-contrib:0.150.1 validate --config=/etc/otelcol/config.yaml + docker run --rm -v .:/code:ro pipelinecomponents/yamllint:0.35.13 yamllint -d relaxed . + docker run --rm -v .:/repo:ro -w /repo rhysd/actionlint:1.7.12 -color + jq empty dashboards/*.json + +# Format YAML in place (needs yamlfmt on the host; optional). +fmt: + yamlfmt . From 15124d65c96f42abf4ba609019305121188e908b Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 12:51:42 +0200 Subject: [PATCH 05/15] fix: restore OTLP metrics ingestion into Prometheus Prometheus 3.x replaced the otlp-write-receiver feature flag with --web.enable-otlp-receiver; with the old flag the collector's metrics export 404ed and all OTLP metrics were silently dropped (surfaced by the new demo). Also add a Loki derived field so trace_id arriving as OTLP structured metadata links to Tempo, not just trace ids in the log body. --- compose.yml | 4 +++- config/grafana/datasources.yaml | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compose.yml b/compose.yml index 34be901..454c22f 100644 --- a/compose.yml +++ b/compose.yml @@ -62,7 +62,9 @@ services: - --storage.tsdb.path=/prometheus - --storage.tsdb.retention.time=30d - --web.enable-remote-write-receiver - - --enable-feature=native-histograms,otlp-write-receiver,exemplar-storage + # Prometheus 3.x: OTLP ingestion is its own flag, no longer a feature flag. + - --web.enable-otlp-receiver + - --enable-feature=native-histograms,exemplar-storage logging: *default-logging grafana: diff --git a/config/grafana/datasources.yaml b/config/grafana/datasources.yaml index 881abf3..5a2dcf4 100644 --- a/config/grafana/datasources.yaml +++ b/config/grafana/datasources.yaml @@ -25,6 +25,12 @@ datasources: matcherRegex: "[tT]race[_-]?[iI][dD][\"=:\\s]+([A-Fa-f0-9]+)" url: "$${__value.raw}" datasourceUid: tempo + # Same, for OTLP logs where trace_id is structured metadata, not body text. + - name: trace_id (otlp) + matcherType: label + matcherRegex: trace_id + url: "$${__value.raw}" + datasourceUid: tempo - name: Tempo type: tempo From b9b9353869481b1fe1c7640569545259e64acf8c Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 13:06:24 +0200 Subject: [PATCH 06/15] feat: add provisioned Service Health (RED) dashboard Request rate, error rate, and latency quantiles from Tempo span metrics (with exemplars linking to traces), p95 from the service's own OTLP SDK metrics, and a correlated logs panel. Works for any service that sends traces, selected via a service variable. Demo app now logs at INFO so non-error lines ship too. --- dashboards/service-health.json | 153 +++++++++++++++++++++++++++++++++ demo/app.py | 1 + 2 files changed, 154 insertions(+) create mode 100644 dashboards/service-health.json diff --git a/dashboards/service-health.json b/dashboards/service-health.json new file mode 100644 index 0000000..f056379 --- /dev/null +++ b/dashboards/service-health.json @@ -0,0 +1,153 @@ +{ + "title": "Service Health (RED)", + "uid": "service-health", + "schemaVersion": 39, + "version": 1, + "refresh": "30s", + "time": { "from": "now-1h", "to": "now" }, + "graphTooltip": 1, + "tags": ["red", "otlp"], + "templating": { + "list": [ + { + "name": "service", + "label": "Service", + "type": "query", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "definition": "label_values(traces_spanmetrics_calls_total, service)", + "query": { "qryType": 1, "query": "label_values(traces_spanmetrics_calls_total, service)", "refId": "var" }, + "refresh": 2, + "sort": 1, + "current": { "text": "demo-api", "value": "demo-api" }, + "options": [], + "hide": 0 + } + ] + }, + "panels": [ + { + "type": "timeseries", + "title": "Request Rate by Endpoint", + "description": "Server spans per second, from Tempo span metrics — works for any service that sends traces.", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, + "id": 1, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "expr": "sum by (span_name) (rate(traces_spanmetrics_calls_total{service=\"$service\", span_kind=\"SPAN_KIND_SERVER\"}[$__rate_interval]))", + "legendFormat": "{{span_name}}", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "unit": "reqps", + "custom": { "lineWidth": 2, "fillOpacity": 10 } + }, + "overrides": [] + } + }, + { + "type": "timeseries", + "title": "Error Rate", + "description": "Share of server spans with STATUS_CODE_ERROR.", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, + "id": 2, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "expr": "100 * sum(rate(traces_spanmetrics_calls_total{service=\"$service\", span_kind=\"SPAN_KIND_SERVER\", status_code=\"STATUS_CODE_ERROR\"}[$__rate_interval])) / sum(rate(traces_spanmetrics_calls_total{service=\"$service\", span_kind=\"SPAN_KIND_SERVER\"}[$__rate_interval]))", + "legendFormat": "errors", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "color": { "mode": "fixed", "fixedColor": "red" }, + "custom": { "lineWidth": 2, "fillOpacity": 10 }, + "thresholds": { "mode": "absolute", "steps": [{ "color": "red", "value": null }] } + }, + "overrides": [] + } + }, + { + "type": "timeseries", + "title": "Latency (from traces, with exemplars)", + "description": "Quantiles over Tempo span-metrics latency. Dots are exemplars — click one to open the exact trace in Tempo.", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 }, + "id": 3, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "expr": "histogram_quantile(0.50, sum by (le) (rate(traces_spanmetrics_latency_bucket{service=\"$service\", span_kind=\"SPAN_KIND_SERVER\"}[$__rate_interval])))", + "legendFormat": "p50", + "refId": "A", + "exemplar": true + }, + { + "expr": "histogram_quantile(0.95, sum by (le) (rate(traces_spanmetrics_latency_bucket{service=\"$service\", span_kind=\"SPAN_KIND_SERVER\"}[$__rate_interval])))", + "legendFormat": "p95", + "refId": "B", + "exemplar": true + }, + { + "expr": "histogram_quantile(0.99, sum by (le) (rate(traces_spanmetrics_latency_bucket{service=\"$service\", span_kind=\"SPAN_KIND_SERVER\"}[$__rate_interval])))", + "legendFormat": "p99", + "refId": "C", + "exemplar": true + } + ], + "fieldConfig": { + "defaults": { + "unit": "s", + "custom": { "lineWidth": 2, "fillOpacity": 5 } + }, + "overrides": [] + } + }, + { + "type": "timeseries", + "title": "HTTP Server Duration p95 (app SDK metrics)", + "description": "From the service's own OTLP metrics (OTel SDK), i.e. the collector → Prometheus OTLP path.", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 }, + "id": 4, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum by (le, http_target) (rate(http_server_duration_milliseconds_bucket{job=\"$service\"}[$__rate_interval])))", + "legendFormat": "{{http_target}}", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "unit": "ms", + "custom": { "lineWidth": 2, "fillOpacity": 10 } + }, + "overrides": [] + } + }, + { + "type": "logs", + "title": "Logs", + "description": "OTLP logs for the service. Expand a line and follow trace_id to jump to the trace in Tempo.", + "gridPos": { "h": 10, "w": 24, "x": 0, "y": 16 }, + "id": 5, + "datasource": { "type": "loki", "uid": "loki" }, + "targets": [ + { + "expr": "{service_name=\"$service\"}", + "refId": "A" + } + ], + "options": { + "showTime": true, + "wrapLogMessage": true, + "enableLogDetails": true, + "sortOrder": "Descending" + } + } + ] +} diff --git a/demo/app.py b/demo/app.py index 2814482..c53a5e7 100644 --- a/demo/app.py +++ b/demo/app.py @@ -7,6 +7,7 @@ from fastapi import FastAPI, HTTPException +logging.basicConfig(level=logging.INFO) # root logger defaults to WARNING; we want the INFO lines too log = logging.getLogger("demo-api") app = FastAPI() From 8eeb059c5e4a569b04265298c4a4059dbbb451ab Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 13:34:59 +0200 Subject: [PATCH 07/15] ci: replace inline smoke test with a just smoke recipe Keeps CI a thin wrapper around the just contract; the same boot test now runs locally with 'just smoke'. --- .github/workflows/ci.yml | 4 +--- justfile | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 11fbdaf..024130c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,5 @@ jobs: - uses: actions/checkout@v7 - uses: extractions/setup-just@v4 - run: cp .env.example .env - - run: just up - - name: Wait for Grafana to report healthy - run: timeout 120 sh -c 'until curl -sf http://localhost:3000/api/health; do sleep 3; done' + - run: just smoke - run: just down diff --git a/justfile b/justfile index c86c931..61116ac 100644 --- a/justfile +++ b/justfile @@ -52,3 +52,9 @@ check: # Format YAML in place (needs yamlfmt on the host; optional). fmt: yamlfmt . + +# Boot the core stack and wait until Grafana reports healthy. Used by CI. +smoke: + docker compose up -d + n=0; until curl -sf http://localhost:3000/api/health >/dev/null; do n=$((n+3)); [ $n -ge 120 ] && { echo "Grafana not healthy after 120s" >&2; exit 1; }; sleep 3; done + @echo "Grafana healthy" From 99420a58f2a37d1d3c8437602968d7a48e816d21 Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 13:34:59 +0200 Subject: [PATCH 08/15] docs: add architecture diagram, demo quickstart, screenshot, and changelog README gains a Mermaid diagram, a one-command demo section up top, a genuine screenshot of the Service Health dashboard rendered from the running demo, run/check/alerting docs, and a design-decisions section. CHANGELOG.md starts the release history at v0.1.0. --- CHANGELOG.md | 39 +++++++++++++++++++ README.md | 73 +++++++++++++++++++++++++++++++++++- docs/img/service-health.png | Bin 0 -> 157138 bytes 3 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 docs/img/service-health.png diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..49fb3b8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,39 @@ +# Changelog + +Notable changes to this stack. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); +versions follow [SemVer](https://semver.org/). + +## [0.1.0] - 2026-07-03 + +First tagged release: the stack is runnable, demoable, and validated in CI. + +### Added + +- `just demo`: one-command demo — an auto-instrumented FastAPI service under + constant load populates Grafana with correlated traces, metrics, and logs. +- `just check`: validation gate (compose syntax, Prometheus config + alert + rules, collector config, YAML, workflows, dashboard JSON), all in pinned + containers. Run by GitHub Actions on every push/PR, plus a `just smoke` + boot test. +- Provisioned **Service Health (RED)** dashboard driven by Tempo span + metrics — works for any service that sends traces. +- Prometheus alert rules: target down, OTel export failures, high span + error rate. +- README: architecture diagram, demo quickstart, screenshot, design + decisions. + +### Changed + +- `cloudflared` moved to an optional `compose.tunnel.yml` overlay and pinned + (was `:latest`); the core stack no longer needs a tunnel token to run. + +### Fixed + +- OTLP metrics ingestion: Prometheus 3.x renamed the OTLP receiver flag, + so the collector's metrics export 404ed and OTLP metrics were dropped. + +## [0.0.1] - 2026-06-30 + +Initial stack: OTel Collector → Loki / Tempo / Prometheus → Grafana wired +for cross-signal correlation, exposed via Cloudflare Tunnel, with RELab +dashboards. diff --git a/README.md b/README.md index 2805cab..a4853d4 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,55 @@ Central Grafana + Loki + Tempo + Prometheus + OTel Collector, wired together with logs ↔ traces ↔ metrics correlation. Meant to run on one host and receive telemetry from multiple projects over OTLP. +```mermaid +flowchart LR + apps["Project apps
(OTLP gRPC 4317 / HTTP 4318)"] --> otel["OTel Collector
(ingestion gateway)"] + otel -- logs --> loki[Loki] + otel -- traces --> tempo[Tempo] + otel -- metrics --> prom[Prometheus] + tempo -- "span metrics (RED)" --> prom + loki --> grafana[Grafana] + tempo --> grafana + prom --> grafana + grafana --- cf["Cloudflare Tunnel
(optional overlay)"] +``` + +## Demo: see it work in one command + +```sh +cp .env.example .env +just demo +``` + +This starts the full stack plus a small auto-instrumented FastAPI service +under constant load (`compose.demo.yml`). Give it a minute, then open +Grafana at (admin / change-me): + +- **Dashboards → Service Health (RED)** — request rate, error rate, and + latency for the demo service. Latency dots are exemplars: click one to + open that exact trace in Tempo. +- **Explore → Loki** — `{service_name="demo-api"}`; expand an error line + and follow its `trace_id` to the trace. +- **Alerting → Alert rules** — stack-health and error-rate rules, + evaluated by Prometheus. + +![Service Health (RED) dashboard](docs/img/service-health.png) + +Tear it down with `just demo-down`. + ## Layout ``` -compose.yml # all services +compose.yml # core services +compose.tunnel.yml # production overlay: Cloudflare Tunnel +compose.demo.yml # demo overlay: sample telemetry source +demo/ # the demo FastAPI service config/ otel-collector.yaml # ingestion gateway (OTLP in → Loki/Tempo/Prometheus out) loki.yaml # logs tempo.yaml # traces prometheus.yaml # metrics + alerts/ # Prometheus alert rules grafana/ # provisioned datasources + dashboard loader dashboards/ # drop JSON dashboards here; Grafana auto-loads them ``` @@ -21,11 +61,18 @@ dashboards/ # drop JSON dashboards here; Grafana auto-loads them ```sh cp .env.example .env # set GRAFANA_ADMIN_PASSWORD -just up +just up # core stack, local only +just up-tunnel # core stack + Cloudflare Tunnel (needs CLOUDFLARE_TUNNEL_TOKEN) ``` Grafana: (admin / whatever you set). +`just check` validates everything (compose files, Prometheus config and +alert rules, collector config, YAML, workflows, dashboard JSON) in pinned +containers — no host installs. CI runs the same command on every push and +PR, plus a smoke test that boots the stack and waits for Grafana to report +healthy. + ## Sending telemetry from a project ### Traces + metrics (OTLP) @@ -64,8 +111,30 @@ Logs carry labels for `service`, `env`, and `host` so you can filter in Grafana. Keep label cardinality low — don't add `user_id`, `request_id`, etc. as labels; use LogQL filters for those. +## Alerting + +Prometheus evaluates the rules in `config/alerts/` (target down, OTel +export failures, >5% span error rate) and Grafana surfaces them under +Alerting → Alert rules. There is deliberately no Alertmanager: on a +single-host stack, another service buys routing complexity before anyone +needs it. Add one (or a Grafana contact point) when alerts must page +someone. + ## Storage Everything persists to local Docker volumes (`loki_data`, `tempo_data`, `prometheus_data`, `grafana_data`). Swap Loki / Tempo storage to S3-compatible (Backblaze B2, Cloudflare R2, Hetzner, MinIO) when you outgrow local disk. + +## Design decisions + +Everything enters through **one OTLP gateway** (the collector), so projects +configure a single endpoint and the backends can be swapped without touching +any app. The stack is **single-host by design** — CML's telemetry volume +doesn't justify distributed ingest, and one compose file is auditable — with +a documented scale-out path (S3-backed Loki/Tempo above) when it stops +fitting. Logs keep **label cardinality low** (`service`, `env`, `host` only; +everything else is query-time filtering) because high-cardinality labels are +how Loki installs fall over. RED metrics are **derived from traces** by +Tempo's metrics generator, so any service that sends traces gets the +Service Health dashboard for free, instrumented or not. diff --git a/docs/img/service-health.png b/docs/img/service-health.png new file mode 100644 index 0000000000000000000000000000000000000000..a79f3642b9f795a79b4f003318c0664807842b88 GIT binary patch literal 157138 zcmd43XH-*N*Dj2TA}XLDMXFMzOP3l1=_T|QI?}6j0wFd)x`OoHMWpx86hwLnkxoE5 zp_f3Y;oEvY_j}%NjC20IW1O>pgtVQ#)?RbXdClvZlW;9fC6ZgTw+ILbNK}-c>kts! zkR>1>thjjGHS0*3cyvdc_o!LA4@L_ixNtKw{{k7S^{DDE-h(lZNW3%quZa*E{rfz7{Quqw z(ek~|9+Mm2;u$y&;!9Gy^V*c1LrYM#K!sPf2#W}n?0RLT z&(J$NJEwp7rnbL-@SIuOmio@AA>q~6s>RF+vN>AH2M1oB)z#His>gA?)5CYD(F((H zS}Gf#1wUD}B;94HtKuk7x*Z=MFJvX~0ORNxBA17}EB||Cfsv6>F`JMkbbim@z(Cad zp}6?R6=T9b1IS*^R^xG8(jv$4OUBd_Xq=uvq? z;13SHF$=3oBX%i@6us1B8n9Qib>Y`dk^v7#zkA!;3H32t@;&2$7(2DzADx~0WqPda z?A=SA@+#%odTUMzJuirfUwX%`{Qj-{cjiv4N*wm2Noo88T`D57j>ytbH%WTN@$Ws2 z$DEZp58~s>aXOr8uh_`LA5d{iOGnF+d`L}|>)=sSQ~PTXS{*k-m@~t}O@me!awgB-NJ~|TzR#hGkp)8 zI*a8I6}Hhohw_(J5gHZR6?!&C$wohl?{RQb{b!ssy1Kf;4p$$85DdstjK+|)ypTa> z`QP8~ocGYKbGo0P+ByGe<4wZf?}xr;ypcC#@oGPBT3di4VPZH+e{Z9urgtJ-^6%%s zgY2kmE$u%q-dfq&t*oriZ*IzkEiPE+*)Sg*91zPUeAb;F`u;tfs(oT2xd<$8t3TTK zA+oxppy0{VC1M6q0RbN$A1}Xy><$3|q(G(i1fkQ-f9?Lps{uQ*HL?5+Nokr;PWob` zgJy=z%iUe`1XTqBE)D6+Z;#%FN{Tn$kJ09$9LKj-1@4fhsH<{KHc1CIH8k*^Zl{sS ztj%p@WGaYViEz70M7s5z-4c7(vc)`4Q3HM)+$m`Wp}1hbA2C)wjc~s#V^Jc#`*$`^ zbVNn#C_ovT+uJXJ2E6>c`PuPlbGADd?lQDa4^1P?EF(=qRF{BJw1Kf<#y5A zFdPHuFJ4a=Dsi64-WPWz<1Y)#}D&zMc8d5TjS640HIlDGhzj3^kD~`c9 z5`NJt&ulq^J$)+8;yTpIkdyPh*wL{T<}Btsl?!XqY;6sm<4s9QOOxlKi0q^yR*0nL zt*)zUgl>&&Ns47jlTqIaVccdUp%czoF74F2Wu)Lc^d_b|R;GuF}L~MEEpi2|au9kQA^aS7AliGHrqx*YvY51T=_(=|n5sPxT=}|@*C8e|l z+Z5{>dyCn{S#JZ9Lgs9#BqVaxKm$B+FUH0 zUR6UYb8~OJsfTili>rvSi}FQ$QgJd-b#W1n{;8aD2QVG`SRB_AkKx=zCESMm zTN8&RrhMbk&3>1pEg6z<-;pE~J6ycwRxcy3wqT^E?L8H&K8M~8HhrznnRWTY3t*#Xswc`~$0LXv2i zA9wXVIJR9x?dQ*#9M@}t7ry`ltgf%m5`Zys64jc(@a-w9{O!ceq-HYJ_TZd7p}#@o z)w*s`-P};$SkP`T94!yk6kgBU<4!EEt*m5Q9%~vu%gmhJ5G&)6I@mn>P5?!b5M7rx zX?t0ll;j7Po=Ppb(M{8IbnE5Id0@1+lp+)iu=sMXq9dl6(kA4O*PnWpxv3NJHLU#n zv9ed3o#{+|{){>Kq?nEnfX(fI`yNH}Dqqj>Vifi;^7LF7+e*8QDv_HXYCqbXe%5D> zV&_%1)hVeRxTfLH4wz-5?WLK1MHMilRA{N0>$*q%x3L| z;cW9E4ne{Vgcaz~=arV{0eT)JJlvHDZ{IHd9B_6+w`wxU1m2rP*h0{{-eHp7yWOX+ zNl+uGqfPWn%)YoiM-s_K-9^B|gq<_^2ikz$IB3>}?BU_zS);y&HgWjmh3O5kfJ4B&Uo_H=c5oQO zrnNNL{foyFPe1d0mG&e`u`igulCPRPi( zmeCVo5geplv0+iO+x6}pp_kWzLFp8G5vxUu=gZZyQiSXAZccoO;iWge-S{6&GWxy9 zU`xe9qsV?7t9WaqWY2~})P3wt=5A7($*qnj=%$vy`Gv;eiVy7{c~(F^_vGZ>@>w)a zlx{S^)1RvL=Icj_W=Q(^y!5rNo`hSpH9O-(%`RtJW?^mmkz-?HzCAs}emisGo>EebGSQJAf1)o>9N??M?tI=k;Yl0C0 zrrQXTk~I|p>5Kc3rR?C;R+kgbWpvqoNXym~TFBPESvQ@W=!*1|Lo(FrsI9T@Q?Cal?T`flBBOM)aKXSiX3)NMQQNB!zyP=e7N=;|68s_^hre()OAr2EHU}n&ICwC)J3hk3W6ucV_bGuJW=9ru;%8 zQxt`_-L}2S4mM9vEJ|d^5lt-Q`uI0h6^)q4*sVEt(GQJ=ZZX(Ex4p5BIsGGF9Zukvh;yLa~{^d<5^ z^qOKU%FUV93R8|xmg-!mE?=H^uaAOI7n=(^iIfI~Fv^RmgM*TKr$caF*PQ|okNO4F zcU~8bXi=-5h*cty@pjk=VhV36$T(w`k zd~mpAEQ~+|?u_Bz209e(P7=CuND8I|O@h@_M>xTIYsPWK#Sbz9_Ttek@ac9rS+J@K zX7qrJUhGH+O0Ef>+eWvImbogKX(Udy249?#Mn%R>?@uGLe{<~M@D;`=s#r!e$lqw1 z=x)ng?OA>9LC??-yw;D47CszED^!ZNUG%#hym^KvNd4Gy&cxmf8lOO zlT#!B^R^$ENje+2t&i1m6hGwT?5T-D#*NjeL=rD@j8xU{d~-9=b8yVJjZ0M5aYJmF zDL!w`zFmY1ggHKV40WFUN(nns_~C_qk-#C!x6)lHkDwzV^iB{r_dMyn?&THP{`ku~ z@1j-V`+2w>Zw#`0=T-OTZU#v>%0W-JsNZcOTYz`Brhho@?tScg(svhW>b0&YJ}!xf z6=PwIz^&UobamP7AZcIhyXkuO*=CxY}xT6z4Df zXt$>zr&w#rC>5okk-@U0nj>F$47FwmThK|b$6MP$CfOR_akY|tZJbl56ZV++@SUYK zQ!3t0KTWheJSN-?*&MC)*raJYX*2!n0A#Gz85O>5>L8wtLOqriR;LRX*#$t%M|KNs z?R&!GcZf;&5amUI(g@d}CXX?6U_GWo(yxqzjSZv7hYt=m4Z72Uyl_by+bWxDP*p7l zKwFK}1@-{veY{ZMMbB41-gK!avpL&B4O>M>7_aiDi--tpO_dsIJ?k(m)d{|U}Z~w0gzJGFGTUmJWCA8Otf-yET)Mctlv(y0fDiqI{m6fG5` z{;E~WiSozYdmk_LVrT?5Z8(&uX&atj)^qCWJ=+R5nXM%!Ur^=@d3S@?NEoN^u5Pa@ zI&D12Y1H>6GPBt8=@f+`R4{1chy>aca3*n)hcyg9&*kFghi36tY&|=xSHX?++eaB~ z0Z{*z>E!5L%)eZ~fwYi}g<;-08}^6Cj*KfW7ew+baR4%O<{N6t2j5$GAl-sHEM}lM z@EkJc39a=!^h{6<*xKn6W;iI(txt~so;bom(CAAr3iOKfZtzUbiWqa2z~%MI#?Mn8Hp43I{M`4>t9}?mmHr)L8Fzm z!Y|Cied?m_(mw!!+uPdi`4{Go{MtXtQCW8GQ`c6xp7HhM_?VrY?L*ui7RxB$a-YF} z_cve5&Ttuv#`n6dVRNtFJ9LKB!DsSaq&w#|3uo9UZ8!)P$9DUJ5V>bK0@aY*EJ)$?_U|>n1mVl9 zS;B&mAnj)g#!OifrhLE&O(EqZ!~r@@52tBC!PaeLL>R>p3oa-QBX`T>Xe7g~&%o93 z&gS-t3P>=iFQKRA3KegN!rZsdv0W&bo3AfBr+^6`2KRk;o{8+iSJxsHp%rvsT~8zr z{BJJwIH8^DO@Eu~X)=6hcXT~s6P4P52YbkZ-@4D7g26fn5U#LSqcbn%lU(t!!w(~S zdqch?7Ai>RPe*XW8irC@jaF<06~iC_A|X55m~oU~<1DC#XXJ~acT1bI2P zrH0L(?dkCsV9ifS9638mgFWbg=M{kXN6Q!MqlTuk2BmakICS zOpF~Rc_iWZJJOHL_R;&p!ZB&LM1L-HeL$wj?XK1-afN3Yg$A(RSbvUBP}jNU80M7i%{n0<88RT2^>9 z3Ry6jyN*o#&aAqITInj&M3q8`Kpw|e<9gTeA|VGW;p-7(;ZwFycIEVonezfq9$qkfyF6`JJ{Ua+R1lg zWfX|+V+NuYFp+4z$0_QFKwRBNmY*Y55)TtpiT|3)Cw&8hm8#`Am~?<<!qpbamoY zPVS>xXgZ$olQfULejAt@skhntcYiQA5-Q&7wTAuWbp@`rV0+j)@Z#cA{{lZs%aJ`T<- zBC?&4PZc(2gF~6puq{H;qnK8iT7I)eWv*yGl8Sn-_wR$W&p)}B78J;judIuJP_J=k z*y{S~wyz~BdRm!oGtItRJKQ0-v!l^y%m4=WUn4_(Th_nTD6VxHf^5a`%k(`A`x%)R6g?b;A&c z%IQ|vLEToG#~$e)D|@wn8%~8sMeHnlij$Pyz|yJ5UXFh~TV5%p6V^S3?)UFogglXu zh#RbyKhx|4j}>?sN*H6gw>DLCt=_UbI&$7_OKS?;IZCU?uUtZG-wv&!+Rku?+yGf7 z?7EWVR9om%;#-g|cH+`*=xpFRR{Nag`l^VqOm~0p!vuN5>FnM7mWuJrr04h3Kc%EW zhK)YVIuu&k+GfP%4*c5O+@uq6fo{fj0HILbhO~0x%gaT(e0qR>X@dy5BmKNAwxG@F zF0Pw}FzLv|8alDd!h#s8SI@46j$k7a6;0UHM!p@Ct_8LREt8w=)HYkp<&AaU%X4({ z#pq0K6u0Ob8NJsj_D7j`czKoUPJ{ipdF(oMOY{(jt$uU9w{L$Z+HvMzQ;D?o^vo?S z&DiFIR@dBLPi3PjPo_5LrotLnXr4oVDe>bz4%k&XzCRL{`l_;6h;?0?RY$Q8WVPK) z>ZzeLb~-zqoRr+0xu8Suf-_{EMGipDpe4<5rgD^~*SN*m9FN3Mp=1{h>r2Mo7Q0x- zHL(Nx&!b$8riTOPjx3?ElMQYVIqP=(HA#$TQ0)yWpTjAI)QijDrEewRi<*Tnfjo9~ zn#+QOgwd>`m<*}IFt?>HmM+-Y0C}US@4?C;stEi+@Z?~rG7D~UHdz$!;HJ^$pDJ<& zA76pgxg?9*nEU$r$_1tS@n&f=#a`mi+|~R?+oGbPt`YgdPC9?_LdKBaKKDtYRi2?s z#x>Iu5}tt+E`#6J?;O`Yd#fl7Z8pRjBc$NxR?9u{@Z{7~Qrf5KtyVe)h(4CTbc1Y2 z_FmV>awG>_L}R?>&8+)GjcT5@h|6%px#1(dV!c(q^nfBS93uGejeKUaFYRgA)pe1l zJ}b{vQlmyo=)Q?9Qp=oQtiA5<$G(ETW{_--&-^&n>Z&B9D}>f{HK}J3ba)3Yox*L; zz4Y{6@N7hIJweP((TV&DM%34Z=D25SiU*8ffrK0xs|Bi<-vh;RMQnK#Ni8f`3keA| z`E3;Fl(035V|iM3i)Y?QurN&fg-6A_fA7yoPW!86x=AXN_~Pc)l&^zUo3@J!7GTY8 z95JaT6}7a;>*+o3qjGidCfDCCsZKb#>gBEgS}ENy6uU%d8Xm35Ll;gC_(2BUY&U%X zeoY~=E5E$3e6He)1BX^&pV;aLdI_nhT>{_%xjbzq$>4W4?)hwtsi|o2sc2~hur;#&$#wure`PQYzka-yyrvM@ z#wo$hCsSvbHOQ~wyE{CaB=Pjp!P`nnJD_BY2kr=!@Z373#47f#_QZ$H@g8xncUyFaoTQN-D+ED#LsNrpDN7; zx;*4nz#L}<r8 z{0YFwhmbj@Rs=6P={!5ynp-w3nr#rsa-C^j8NJgt2igTVy}VpzGWr=vT;pi5uAyHK zX9h^~9Djy<>+2iC5*8Z~9oYgs%vC-fVp|-_0NL2uq6>7#0bHO`aH15;fbh@`J7cQGptk-*(W`MlwwEN8}JbVwH zDIv2m*H>cJ2+dKbPGnJv!k?Y$BUlXq+9r4>*k|L0_ck`>d0bOKp9B!Zdwe%fqcfWh zVQnC!D2F;8(!Oas^rW#3wPfks&v+g9zPdz^VB|5A?^k;#!?0nA8 z)n>1_O+H@o^drL^AJ?0T4UGNVt_HX5d*JeWkS&3J?H%&s^fC4I;6+6Zh_E}u1IlOM zw!VNC@nP=265(R$^}MV2h$f{Vxp4fg0cnV^^VY`V#?q49L8?+L6Qd+PP+k33_UjIW z9}E{up+v^O$0tW=bW=|LjX7wQ+{Hn-AQihTEF^@V8|SxZ@aAJ)5JwZbe09Y%u2s1$Mcnpuu|e@%U_IE=vpu0CNqO1--rnX0#=;x( zt5&zD3~*9B^yO$mO@_;hweKfh)RZkw^fXNWOJGyf6Xtvh-TaVN5*8U5sVHx4W0Px> z`vq@(M8H1@_wdv4w03Z4EYmtM5KO`T=&`}B%x`1X*9TV*fL+3z$Ly2#ZM#LX7e1;m zY=5)jPDgqp>gM0w_RIg|1cXr$*uV6HqCN3;x=7Ftfvv$C<@2MLG@=V^aA zG)IU>mTsyT6Du&&TBacDZ67`>{%=}*ft91C=wD{#^CVA*-0P5n;uPbMth1%16(a~_ zQSZ8WTv8SXc{o>-_ z>*ORLfLw*x;*AZ*AG4_J_1MIcE4tW%Rl^7DAjZZ*Jc@A~+FS{LiVU(><~^RS1l^7{ z$;iws)G3ZgA@9=sb3@obzEIw}l$7h7Y!FGw1e1*Tv^;~7KXxn|{haLG3qj7XzRD-{ zAMT$)m}4^joS_=Li8U$MzScK0lm3J!oHgmso4@?0I{2ybq-CMk=q3Lw<$dTzB`WQc z#5cjkwAJN=%9cOd=G7j+_vR5PyF;n|xw--+d=txFKw9B1l_~e=&ol_MfFg_GYx%$~ z_&cpvxe>q!<8>?u!v^dq{(Rv$NimOeg@E|~_X}mO|Em&3E8%~v;v`z00GsyqZC*)a zQ%lRWN2&SwKh}~TL&3l(zA4X_Fadwf^~0}>jqwJ$y14jsV7nLh7S90S1Jss0I_;h8 zvF$*(BCHB@_Ra&22d2gTI6;FFl@JN&aew7vSp7L7^V4jT^cetpJJnc-?rdiyaXezP zao=gMT^s}$LHe`BC!EqBmCyUY8~o+~avCGak9*lTL%P)@{CVyJsr`!=!+~uQcq|^E zgQ)p3bc;U$i~a5WeQDnj@t6B+h(m6b<tyUy zM{ju%?Ae#$#@qISw`115*Pd|{bLkWdGw&;S>d5WI!=yZC{v_1vsFY8XX#)>Lmsp_m zmq0E>#)Jk6Zwgp=d3b1lxzAK7I8#%PGc?sL$O5%PQBm6y#k*F@4tI-RoO&(2Ee{4p z{8(}MhS47J%MfuS0Co<8%gf{Ay@G=1kv2G{*=e|ClAC`gctg^AP3PRowDuTC4Js<` z>M-PwoCEq?T<>^}8Apy*jbk68zyDIn2Wxb+UaJOv!w46))@!QU;s;nE;384VNSmTB zIUpsO<8>myO0D(Gn2a9fd>8)a>2;WWg(}NkCTQ)mVsvWq!NAUJTZ>Isd9foWqDP`; zXC^Pu-JRe4G=34NX>i;;#Qe}kBDFz0#^0AcIKUU`Vv~i3(>9CNt!7WtNShE1WDlg6 zv&}EkXEy1?%C;u!<@u5}e#X+Br6eVZbyUd7zxCajOpH%!vR%~tE4DhhUj+6pRaws- zpo(&&1Dm@R_tx%6`mT+X*faT&xs#^-QPxS)#=2jOScq*^ReL?WUW=fDgR=0J$Aw}C z);UTsX$vPnIIu0&-QFx!(MHE)zU4X6?_Zq6b@`ynG5juYy&Vtwr(RhgI!$@QZ1on2Z{PYhz zlk)e61Gw7QIK={-sW6`BR(byN97mF75U;b~8BpV&F6Gm_d-n*P3H#+l$sivlB!n6= zJ1z+v&jg^Q4%eO<4*>yMJyj3$2b8g<++4nQu#uK)ht0;&62UF~zc9_jetf#X5z=on)zJeBnE?AZR`h|a@= zp0$@od7&DG>ZuRtn3|jp_vysSePKoRm%;LDgrLiP8*gvc7G&e~>ma_Bf#!UT4bnRu zE;BWX#adB}hs4pZ_xD)=Db#5y|9WKSmN3MgGiB>35NERe^|h}> z+R*QEgsOQ;Yg|MpM8*Hd~;sL51#yb|W+L|zx!(ydeY z2|)g>z3AytLA(~5KN!H22LU>K3vBfU?06UXwnrCKbdcYX#FsUFSKE2V_afCJB+NOMf6HZaW2{t(h?&J=n9a1osP`Md$qVd(&@RXT!RNZ( z>eklG(h~)@Qve4_bDLI<0d#t4;0Z($1utfuU093vq~FUufe`TWiXFA+dJ)JN*%1nG zsR+-*tFYwsIP6JLJfKNKR|f}@3WMT%W%dKOgAT6&hOx&b_KgdAH!&l=#T&z1Yob3s zlr>-n&XP!)y;W3GTUmr7J<=SqkQy&A)N?S}gYq*P7ONKMJzf&Vz4XH^c{XB=cm>xL zif8-PbY%jm3h6%dpb`028!f9|%mE1soKw74?JUJUhT{luF3eq2?|6jW# zfzA>`+U{T~vb8Y@lq&+Rnm5R4<4EJ)y-N@|*XA{~;$wIlG5sKXj-rWv|bm6wO&SY#i0&dJN05VJYb zc=lt69Ta%<$<7H#qKL?7j|!98Fayo+I`QyDjpep+RE{{ZwvE5meLB2jzRm?1QE2Fn zXtta{eHiy!C_^^;LM2w)OO7hUH*H=N4}R)tAGbk^X}kh&P2Y7y02$jRF91khBm~1{HWRW>wwJL z+uOM9C1K5gh;Soj20p$S=zB2!E z0XvIbWZqjuYGpdHL9@3kE&%h_YUV=R%F!vFs9hDKeKX9$b?SkP3jji~I{ZbNWS|uq zaRq=KZ_A$1OOKe~53E((28*(SmRA;n&wpH&W6!(7S%6BLyk{4RLWKh)Wbo94LvR;( zQrs9QifRnpu>)f5VCD&L$A^%)0VIPc?}-(o^v_f8_9QPmUMrG? zFxIl~`}dq=96crF%e|3CKolO|KbmX_glO$jNR-4XMipqA=zT=&5s@J`RSpKy6@V%i z>H|A-Pt1sTY6k3ZSvYm!qRyuSX%luU3*mo4pXDBm>FuFALo+>%Fxb72qk^-W92)Rv=Qi*Kn}-$yoi`>P=mZGfQ2qo2z3^=`6o$v-gE?X%Vq%y@etyHtW5|;8x=7SiRUalqF_Iqbh~
    h&dD}S8Di+#!ls@3 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ℑL09U%8fqPb;d!`+f^T4#?@ogWW@ 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 Date: Fri, 3 Jul 2026 13:45:37 +0200 Subject: [PATCH 09/15] style: make the demo app pass ruff Docstrings, return annotations, a named ERROR_RATE constant, targeted S311 suppressions (randomness is jitter, not crypto), and an __init__.py so the demo dir isn't an implicit namespace package. --- demo/__init__.py | 1 + demo/app.py | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 demo/__init__.py diff --git a/demo/__init__.py b/demo/__init__.py new file mode 100644 index 0000000..fd3aec1 --- /dev/null +++ b/demo/__init__.py @@ -0,0 +1 @@ +"""Demo telemetry source for the monitoring stack (see compose.demo.yml).""" diff --git a/demo/app.py b/demo/app.py index c53a5e7..a43c6ac 100644 --- a/demo/app.py +++ b/demo/app.py @@ -1,26 +1,33 @@ -# Minimal FastAPI service for the demo overlay. All telemetry (traces, -# metrics, logs with trace context) comes from OTel auto-instrumentation — -# see compose.demo.yml. No OTel code needed here. +"""Minimal FastAPI service for the demo overlay. + +All telemetry (traces, metrics, logs with trace context) comes from OTel +auto-instrumentation — see compose.demo.yml. No OTel code needed here. +""" + import logging import random import time from fastapi import FastAPI, HTTPException +ERROR_RATE = 0.1 # fixed error rate, enough to light up RED panels + logging.basicConfig(level=logging.INFO) # root logger defaults to WARNING; we want the INFO lines too log = logging.getLogger("demo-api") app = FastAPI() @app.get("/") -def root(): +def root() -> dict[str, bool]: + """Fast, always-successful endpoint.""" return {"ok": True} @app.get("/work") -def work(): - time.sleep(random.uniform(0.02, 0.3)) - if random.random() < 0.1: # NOTE: fixed 10% error rate, enough to light up RED panels +def work() -> dict[str, bool]: + """Simulate variable-latency work that sometimes fails.""" + time.sleep(random.uniform(0.02, 0.3)) # noqa: S311 — not crypto, just jitter + if random.random() < ERROR_RATE: # noqa: S311 log.error("work failed: upstream flaked") raise HTTPException(status_code=500, detail="upstream flaked") log.info("work done") From 6acae3d8dc0e7596dd702142a5deb8e16ee99445 Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 13:59:39 +0200 Subject: [PATCH 10/15] docs: add ADR 0001 and storage scale-out stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR records the single-host OTLP-native architecture decision and its alternatives; compose.storage.s3.yml is a deliberately commented stub documenting the concrete Loki/Tempo → S3 path the README mentions. --- CHANGELOG.md | 3 ++ README.md | 4 ++- compose.storage.s3.yml | 54 ++++++++++++++++++++++++++++ docs/adr/0001-observability-stack.md | 50 ++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 compose.storage.s3.yml create mode 100644 docs/adr/0001-observability-stack.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 49fb3b8..82ccef6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ First tagged release: the stack is runnable, demoable, and validated in CI. error rate. - README: architecture diagram, demo quickstart, screenshot, design decisions. +- ADR 0001 recording the single-host OTLP-native architecture, and a + commented `compose.storage.s3.yml` stub documenting the storage + scale-out path. ### Changed diff --git a/README.md b/README.md index a4853d4..43c788c 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,9 @@ someone. Everything persists to local Docker volumes (`loki_data`, `tempo_data`, `prometheus_data`, `grafana_data`). Swap Loki / Tempo storage to S3-compatible -(Backblaze B2, Cloudflare R2, Hetzner, MinIO) when you outgrow local disk. +(Backblaze B2, Cloudflare R2, Hetzner, MinIO) when you outgrow local disk — +`compose.storage.s3.yml` documents the concrete shape of that change, and +`docs/adr/0001-observability-stack.md` records the architecture rationale. ## Design decisions diff --git a/compose.storage.s3.yml b/compose.storage.s3.yml new file mode 100644 index 0000000..86fd99e --- /dev/null +++ b/compose.storage.s3.yml @@ -0,0 +1,54 @@ +# STUB — the storage scale-out path (not wired up; see ADR 0001). +# +# When local volumes stop fitting, Loki and Tempo move their object storage +# to any S3-compatible backend (Cloudflare R2, Backblaze B2, Hetzner, MinIO) +# without touching the collector, Prometheus, or any client project. +# +# This is deliberately a commented stub: it documents the concrete shape of +# the change so the README's scale-out claim is real, but it is not meant to +# be started until credentials and a bucket exist. To activate: +# +# 1. Create s3 variants of the configs, e.g. config/loki.s3.yaml replacing +# `common.storage.filesystem` with: +# +# common: +# storage: +# s3: +# endpoint: ${S3_ENDPOINT} # e.g. .r2.cloudflarestorage.com +# bucketnames: cml-loki +# access_key_id: ${S3_ACCESS_KEY_ID} +# secret_access_key: ${S3_SECRET_ACCESS_KEY} +# s3forcepathstyle: true +# +# and config/tempo.s3.yaml replacing `storage.trace.backend: local` with: +# +# storage: +# trace: +# backend: s3 +# s3: +# endpoint: ${S3_ENDPOINT} +# bucket: cml-tempo +# access_key: ${S3_ACCESS_KEY_ID} +# secret_key: ${S3_SECRET_ACCESS_KEY} +# +# 2. Uncomment the overlay below and run: +# docker compose -f compose.yml -f compose.storage.s3.yml up -d +# +# services: +# loki: +# volumes: +# - ./config/loki.s3.yaml:/etc/loki/loki.yaml:ro +# - loki_data:/loki +# environment: +# S3_ENDPOINT: ${S3_ENDPOINT:?set S3_ENDPOINT in .env} +# S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?set S3_ACCESS_KEY_ID in .env} +# S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?set S3_SECRET_ACCESS_KEY in .env} +# +# tempo: +# volumes: +# - ./config/tempo.s3.yaml:/etc/tempo/tempo.yaml:ro +# - tempo_data:/var/tempo +# environment: +# S3_ENDPOINT: ${S3_ENDPOINT:?set S3_ENDPOINT in .env} +# S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?set S3_ACCESS_KEY_ID in .env} +# S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?set S3_SECRET_ACCESS_KEY in .env} diff --git a/docs/adr/0001-observability-stack.md b/docs/adr/0001-observability-stack.md new file mode 100644 index 0000000..a0fa886 --- /dev/null +++ b/docs/adr/0001-observability-stack.md @@ -0,0 +1,50 @@ +# ADR 0001: Single-host OTLP-native observability stack + +Date: 2026-07-03. Status: accepted (records a decision already in production). + +## Context + +CML runs several research platforms (RELab and others) that need logs, +traces, and metrics in one place. Telemetry volume is modest — a handful of +services, single-digit requests per second — but the projects are +long-lived, maintained by a very small team, and must stay cheap and +auditable. + +## Decision + +Run one Docker Compose stack on a single host: an OpenTelemetry Collector as +the only ingestion endpoint, fanning out to Loki (logs), Tempo (traces), and +Prometheus (metrics), with Grafana on top. Expose Grafana and the OTLP +endpoints via Cloudflare Tunnel; bind everything else to `127.0.0.1`. + +- **OTLP-native:** projects configure one endpoint and one protocol. + Backends can be swapped (or moved to hosted equivalents) without touching + any application. +- **Single-host:** one compose file is something one person can fully audit + and rebuild. Distributed ingest (Kubernetes, Mimir, multi-tenant Loki) + buys nothing at this volume and costs ongoing operational attention. +- **Traces as the primary signal:** Tempo's metrics generator derives RED + metrics and a service graph from spans, so a service that only sends + traces still gets dashboards and error-rate alerting. + +## Alternatives considered + +- **Grafana Cloud / hosted SaaS:** less to operate, but recurring cost, + data residency questions for research data, and less useful as + institutional infrastructure knowledge. +- **Per-project stacks:** no shared endpoint to maintain, but duplicates + storage and Grafana per project and makes cross-project correlation + impossible. +- **ELK / OpenSearch:** heavier to run, log-centric; weaker native OTLP and + trace correlation story than the Grafana stack. + +## Consequences + +- The host is a single point of failure; acceptable because the monitored + platforms degrade gracefully without telemetry (OTLP export is + fire-and-forget) and the stack rebuilds from this repo in minutes. +- Local disk bounds retention (30d logs/metrics, 7d traces). The documented + escape hatch is S3-compatible storage for Loki/Tempo — see + `compose.storage.s3.yml` — before any move to distributed ingest. +- Everything is pinned and validated by `just check` in CI, so the stack + stays reproducible. From 5d6e8c41aa8b1b5b6087489f8dff8d47958bf205 Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 15:20:15 +0200 Subject: [PATCH 11/15] fix: rename the s3 compose stub to align with docker compose file naming conventions --- compose.storage.s3.yml => compose.storage-s3.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename compose.storage.s3.yml => compose.storage-s3.yml (100%) diff --git a/compose.storage.s3.yml b/compose.storage-s3.yml similarity index 100% rename from compose.storage.s3.yml rename to compose.storage-s3.yml From d91b2c0d8aa47f37b0be20354f13d002022b8a7f Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 15:20:55 +0200 Subject: [PATCH 12/15] ci: add updates for demo Dockerfile --- .github/dependabot.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 39e6d88..a0ce903 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,6 +9,11 @@ updates: patterns: - "*" + - package-ecosystem: "docker" + directory: "/demo" + schedule: + interval: "monthly" + - package-ecosystem: "github-actions" directory: "/" schedule: From be6d97aed65b37d6a0b4aec75ca821064d0768c7 Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 15:21:14 +0200 Subject: [PATCH 13/15] feat: update metrics for stable HTTP semconv and adjust service health dashboard queries --- compose.demo.yml | 4 ++++ dashboards/service-health.json | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compose.demo.yml b/compose.demo.yml index 32f6136..0d1d317 100644 --- a/compose.demo.yml +++ b/compose.demo.yml @@ -21,6 +21,10 @@ services: # Ship Python log records via OTLP with trace context attached. OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED: "true" OTEL_METRIC_EXPORT_INTERVAL: "10000" + # Emit the *stable* HTTP semconv (http.server.request.duration in seconds, + # http.route) rather than the legacy names. Stable metric names are frozen, + # so the Service Health dashboard's app-SDK panel survives library bumps. + OTEL_SEMCONV_STABILITY_OPT_IN: http logging: driver: json-file options: diff --git a/dashboards/service-health.json b/dashboards/service-health.json index f056379..d0d6c73 100644 --- a/dashboards/service-health.json +++ b/dashboards/service-health.json @@ -116,14 +116,14 @@ "datasource": { "type": "prometheus", "uid": "prometheus" }, "targets": [ { - "expr": "histogram_quantile(0.95, sum by (le, http_target) (rate(http_server_duration_milliseconds_bucket{job=\"$service\"}[$__rate_interval])))", - "legendFormat": "{{http_target}}", + "expr": "histogram_quantile(0.95, sum by (le, http_route) (rate(http_server_request_duration_seconds_bucket{job=\"$service\"}[$__rate_interval])))", + "legendFormat": "{{http_route}}", "refId": "A" } ], "fieldConfig": { "defaults": { - "unit": "ms", + "unit": "s", "custom": { "lineWidth": 2, "fillOpacity": 10 } }, "overrides": [] From d078a75569642abbf72a74040905ddc9073a833f Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 15:39:18 +0200 Subject: [PATCH 14/15] docs: Improve wording --- README.md | 31 +++++++++-------- docs/adr/0001-observability-stack.md | 52 +++++++++++++--------------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 43c788c..bf00345 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Observability stack -Central Grafana + Loki + Tempo + Prometheus + OTel Collector, wired together -with logs ↔ traces ↔ metrics correlation. Meant to run on one host and -receive telemetry from multiple projects over OTLP. +One host running Grafana, Loki, Tempo, Prometheus, and an OpenTelemetry +Collector, wired so logs, traces, and metrics cross-link. Point any number of +projects at it over OTLP and their telemetry lands in one place. ```mermaid flowchart LR @@ -42,7 +42,7 @@ Tear it down with `just demo-down`. ## Layout -``` +```sh compose.yml # core services compose.tunnel.yml # production overlay: Cloudflare Tunnel compose.demo.yml # demo overlay: sample telemetry source @@ -130,13 +130,16 @@ Everything persists to local Docker volumes (`loki_data`, `tempo_data`, ## Design decisions -Everything enters through **one OTLP gateway** (the collector), so projects -configure a single endpoint and the backends can be swapped without touching -any app. The stack is **single-host by design** — CML's telemetry volume -doesn't justify distributed ingest, and one compose file is auditable — with -a documented scale-out path (S3-backed Loki/Tempo above) when it stops -fitting. Logs keep **label cardinality low** (`service`, `env`, `host` only; -everything else is query-time filtering) because high-cardinality labels are -how Loki installs fall over. RED metrics are **derived from traces** by -Tempo's metrics generator, so any service that sends traces gets the -Service Health dashboard for free, instrumented or not. +Everything enters through one gateway — the collector — so a project +configures a single OTLP endpoint, and a backend can be swapped without +touching any app. It runs on one host on purpose: CML's telemetry is a handful +of services at single-digit requests per second, so distributed ingest would +add operational weight for no gain, while one compose file stays auditable by a +single person. When local disk runs short, S3-backed Loki and Tempo (above) +are the documented way out. + +Logs carry only low-cardinality labels — `service`, `env`, `host` — and +everything else is a query-time filter; high-cardinality labels are the usual +way a Loki install falls over. And because Tempo's metrics generator derives +RED metrics from spans, any service that sends traces gets the Service Health +dashboard whether or not it emits metrics of its own. diff --git a/docs/adr/0001-observability-stack.md b/docs/adr/0001-observability-stack.md index a0fa886..3ca5ec8 100644 --- a/docs/adr/0001-observability-stack.md +++ b/docs/adr/0001-observability-stack.md @@ -4,11 +4,10 @@ Date: 2026-07-03. Status: accepted (records a decision already in production). ## Context -CML runs several research platforms (RELab and others) that need logs, -traces, and metrics in one place. Telemetry volume is modest — a handful of -services, single-digit requests per second — but the projects are -long-lived, maintained by a very small team, and must stay cheap and -auditable. +CML runs several long-lived research platforms (RELab and others) that need +their logs, traces, and metrics in one place. The volume is modest — a handful +of services at single-digit requests per second — but one small team maintains +all of it, so whatever we run must stay cheap and auditable. ## Decision @@ -17,34 +16,33 @@ the only ingestion endpoint, fanning out to Loki (logs), Tempo (traces), and Prometheus (metrics), with Grafana on top. Expose Grafana and the OTLP endpoints via Cloudflare Tunnel; bind everything else to `127.0.0.1`. -- **OTLP-native:** projects configure one endpoint and one protocol. - Backends can be swapped (or moved to hosted equivalents) without touching - any application. -- **Single-host:** one compose file is something one person can fully audit - and rebuild. Distributed ingest (Kubernetes, Mimir, multi-tenant Loki) - buys nothing at this volume and costs ongoing operational attention. +- **OTLP-native:** one endpoint, one protocol. Swap a backend or move it to a + hosted equivalent without touching any application. +- **Single-host:** one compose file one person can audit and rebuild. + Distributed ingest (Kubernetes, Mimir, multi-tenant Loki) would add operational + overhead for no benefit at this volume. - **Traces as the primary signal:** Tempo's metrics generator derives RED - metrics and a service graph from spans, so a service that only sends - traces still gets dashboards and error-rate alerting. + metrics and a service graph from spans, so a service that only sends traces + still gets dashboards and error-rate alerting. ## Alternatives considered -- **Grafana Cloud / hosted SaaS:** less to operate, but recurring cost, - data residency questions for research data, and less useful as - institutional infrastructure knowledge. -- **Per-project stacks:** no shared endpoint to maintain, but duplicates - storage and Grafana per project and makes cross-project correlation - impossible. -- **ELK / OpenSearch:** heavier to run, log-centric; weaker native OTLP and - trace correlation story than the Grafana stack. +- **Grafana Cloud / hosted SaaS:** less to operate, but a recurring bill, + data-residency questions for research data, and little institutional + infrastructure knowledge to show for it. +- **Per-project stacks:** no shared endpoint to maintain, but each project + duplicates its own storage and Grafana, and cross-project correlation + becomes impossible. +- **ELK / OpenSearch:** heavier to run and log-centric, with a weaker native + OTLP and trace-correlation story than the Grafana stack. ## Consequences -- The host is a single point of failure; acceptable because the monitored - platforms degrade gracefully without telemetry (OTLP export is +- The host is a single point of failure — acceptable, because the monitored + platforms degrade gracefully when telemetry stops (OTLP export is fire-and-forget) and the stack rebuilds from this repo in minutes. -- Local disk bounds retention (30d logs/metrics, 7d traces). The documented - escape hatch is S3-compatible storage for Loki/Tempo — see - `compose.storage.s3.yml` — before any move to distributed ingest. -- Everything is pinned and validated by `just check` in CI, so the stack +- Local disk bounds retention (30d logs/metrics, 7d traces). The escape hatch, + reached before any move to distributed ingest, is S3-compatible storage for + Loki and Tempo — see `compose.storage.s3.yml`. +- Every image is pinned and validated by `just check` in CI, so the stack stays reproducible. From f090c99726b90c731d74f479c76bcf345afb67ae Mon Sep 17 00:00:00 2001 From: Simon van Lierde Date: Fri, 3 Jul 2026 15:51:28 +0200 Subject: [PATCH 15/15] docs: update references to renamed compose.storage-s3.yml --- CHANGELOG.md | 2 +- README.md | 2 +- compose.storage-s3.yml | 2 +- docs/adr/0001-observability-stack.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82ccef6..79bc055 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ First tagged release: the stack is runnable, demoable, and validated in CI. - README: architecture diagram, demo quickstart, screenshot, design decisions. - ADR 0001 recording the single-host OTLP-native architecture, and a - commented `compose.storage.s3.yml` stub documenting the storage + commented `compose.storage-s3.yml` stub documenting the storage scale-out path. ### Changed diff --git a/README.md b/README.md index bf00345..810ea20 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ someone. Everything persists to local Docker volumes (`loki_data`, `tempo_data`, `prometheus_data`, `grafana_data`). Swap Loki / Tempo storage to S3-compatible (Backblaze B2, Cloudflare R2, Hetzner, MinIO) when you outgrow local disk — -`compose.storage.s3.yml` documents the concrete shape of that change, and +`compose.storage-s3.yml` documents the concrete shape of that change, and `docs/adr/0001-observability-stack.md` records the architecture rationale. ## Design decisions diff --git a/compose.storage-s3.yml b/compose.storage-s3.yml index 86fd99e..921a8f7 100644 --- a/compose.storage-s3.yml +++ b/compose.storage-s3.yml @@ -32,7 +32,7 @@ # secret_key: ${S3_SECRET_ACCESS_KEY} # # 2. Uncomment the overlay below and run: -# docker compose -f compose.yml -f compose.storage.s3.yml up -d +# docker compose -f compose.yml -f compose.storage-s3.yml up -d # # services: # loki: diff --git a/docs/adr/0001-observability-stack.md b/docs/adr/0001-observability-stack.md index 3ca5ec8..b69f096 100644 --- a/docs/adr/0001-observability-stack.md +++ b/docs/adr/0001-observability-stack.md @@ -43,6 +43,6 @@ endpoints via Cloudflare Tunnel; bind everything else to `127.0.0.1`. fire-and-forget) and the stack rebuilds from this repo in minutes. - Local disk bounds retention (30d logs/metrics, 7d traces). The escape hatch, reached before any move to distributed ingest, is S3-compatible storage for - Loki and Tempo — see `compose.storage.s3.yml`. + Loki and Tempo — see `compose.storage-s3.yml`. - Every image is pinned and validated by `just check` in CI, so the stack stays reproducible.