7.6 KiB
7.6 KiB
Plan: Grafana FARO + Alloy for FarmaFinder
Status: Approved (user answers 2026-06-30). Path note: User said
/root/Monitoring/but the stack lives at/home/f80ans0/Projects/Monitoring/.
User decisions
- Network: FarmaFinder runs on the same host as srv84-macos → use
host.docker.internal:4317/4318. - Auth: Open on
back-tieronly, no auth. - Existing otel-collector: Remove it. Alloy is the only collector.
- Faro env: Build-time via Vite
VITE_FARO_*build args.
Architecture
Browser (FarmaFinder PWA, Faro SDK)
│ OTLP HTTP
▼
┌─────────────────────────────────────────────┐
│ Grafana Alloy :4317 gRPC :4318 HTTP :8889│
│ otel.receiver → batch → exporters │
│ prometheus.exporter.self :12345 │
└──┬─────────────┬──────────────┬─────────────┘
│ traces │ logs │ metrics (:8889 scraped)
▼ ▼ ▼
Tempo:4317 Loki:3100/otlp Prometheus:9090
backend (Express) ── OTLP gRPC ─▶ Alloy:4317 (host.docker.internal)
pip-platform (FastAPI) ── OTLP gRPC ─▶ Alloy:4317 (host.docker.internal)
scraper (Puppeteer) ── OTLP gRPC ─▶ Alloy:4317 (host.docker.internal)
API helper (in-process, covered by backend OTel)
Files Changed
Monitoring (/home/f80ans0/Projects/Monitoring/)
- NEW
alloy-config.alloy— River config (otel receiver, batch, exporters to tempo/loki/prometheus, self-scrape on 12345) - MOD
docker-compose.yml— addalloyservice onback-tier(NO front-tier per Q2), bind 4317/4318/8889/12345 to0.0.0.0since same host; REMOVE theotel-collectorservice - MOD
prometheus/prometheus.yml— addalloyscrape job foralloy:12345 - MOD
grafana/provisioning/datasources/datasource.yml— add Tempo + Loki; fix Prometheus URL fromhttp://localhost:9090tohttp://prometheus:9090 - NEW
grafana/provisioning/dashboards/faro-web-vitals.json - NEW
grafana/provisioning/dashboards/faro-js-errors.json - NEW
grafana/provisioning/dashboards/faro-overview.json - NEW
README-FARO-ALLOY.md
Frontend (/home/f80ans0/Projects/Webs/FarmaFinder/frontend/)
- MOD
package.json— add@grafana/faro-react,faro-web-sdk,faro-web-tracing,faro-transport-otlp-http - NEW
src/utils/faro.js - MOD
src/main.jsx— callinitFaro()before render - MOD
Dockerfile— accept VITE_FARO_* build args - MOD
vite.config.js— no change needed (Vite reads VITE_* automatically) - NEW
.env.example
Backend Node (/home/f80ans0/Projects/Webs/FarmaFinder/backend/)
- MOD
package.json— add@opentelemetry/api,sdk-node,auto-instrumentations-node,exporter-trace-otlp-grpc,exporter-logs-otlp-grpc,instrumentation-pino,pino,pino-pretty - NEW
src/tracing.js— NodeSDK bootstrap (ESM) - MOD
server.js—import './src/tracing.js';as line 1; replace someconsole.*with pino - MOD root
docker-compose.yml:backend.environmentadd OTEL_* env varsfrontend.build.argsaddVITE_FARO_ENDPOINT,VITE_FARO_APP_NAME,VITE_FARO_ENV
pip-platform
- MOD
docker-compose.yml— changeOTEL_EXPORTER_OTLP_ENDPOINTfromhttp://otel-collector:4317tohttp://host.docker.internal:4317; remove the in-stackotel-collector,prometheus,grafanaservices (or comment out) since they're replaced by the shared stack - (For this phase, leave the pip-platform prometheus+grafana running to avoid disrupting the existing setup — change just the OTel endpoint. Document in README.)
scraper
- MOD
package.json— add OTel deps - NEW
tracing.js - MOD
index.js— wraprun()in a span
API helper
- No changes (in-process; covered by backend's auto-instrumentation).
Phases (8 total)
Phase 1: Add Grafana Alloy to monitoring stack
- Write
/home/f80ans0/Projects/Monitoring/alloy-config.alloy - Modify
/home/f80ans0/Projects/Monitoring/docker-compose.yml:- Add
alloyservice (imagegrafana/alloy:v1.6.1) - Remove the
otel-collectorservice
- Add
- Modify
/home/f80ans0/Projects/Monitoring/prometheus/prometheus.yml— addalloyscrape job - Verify:
docker compose config -q
Phase 2: Frontend Faro SDK
- Modify
frontend/package.json(add deps) - Create
frontend/src/utils/faro.js - Modify
frontend/src/main.jsx(call initFaro) - Modify
frontend/Dockerfile(build args) - Create
frontend/.env.example - Verify:
cd frontend && npm ci && npm run buildsucceeds
Phase 3: Backend Node OTel + pino
- Modify
backend/package.json(add OTel + pino deps) - Create
backend/src/tracing.js - Modify
backend/server.js(import tracing first; add pino) - Modify root
docker-compose.yml(backend env + frontend build args) - Verify:
cd backend && npm cisucceeds; container starts; trace appears in Tempo
Phase 4: pip-platform OTel re-route
- Modify
pip-platform/docker-compose.yml— changeOTEL_EXPORTER_OTLP_ENDPOINT - Verify: pip-api trace appears in Tempo
Phase 5: Scraper one-shot OTel
- Modify
scraper/package.json(add OTel deps) - Create
scraper/tracing.js - Modify
scraper/index.js(wrap run in span)
Phase 6: Grafana provisioning
- Modify
datasources/datasource.yml(add Tempo + Loki, fix Prometheus URL) - Create 3 dashboard JSONs (web vitals, js errors, overview)
- Verify: dashboards load in Grafana
Phase 7: Documentation
- Create
Monitoring/README-FARO-ALLOY.md
Phase 8: Verification
docker compose config -qfor both stacksdocker compose up -d alloyfrom Monitoring dircurl -sf http://localhost:12345/-/readyreturns 200curl -sf -X POST http://localhost:4318/v1/tracesreturns 200- Container logs show OTel init for backend + pip-platform
- Grafana Explore → Tempo shows traces tagged
service.name=farmafinder-backend - Grafana Explore → Loki shows
{app="farmafinder-frontend"}logs - Grafana Explore → Prometheus shows
farovitals_*metrics
Risks
- HIGH — None remaining (Q1 resolved: same host).
- MEDIUM — Backend uses ESM; OTel NodeSDK needs ESM-compatible setup via
--importflag in CMD, not justimport './tracing.js'. Use the OTel SDK'sregisterAPI in ESM, or use the--importNode flag withinstrumentation.mjsshim. - MEDIUM — Alloy config is River syntax, not YAML. Validate with
alloy fmtandalloy validateif available locally. - LOW — Dashboard JSON validity.
- INFO (security) —
alertmanager/config.ymlline 25 has a Telegram bot token in plain text. Do not fix in this PR; flag to user.
Complexity
8-12 hours end-to-end.
Verification commands
# Syntax
docker compose -f /home/f80ans0/Projects/Monitoring/docker-compose.yml config -q && echo "monitoring OK"
cd /home/f80ans0/Projects/Webs/FarmaFinder && docker compose config -q && echo "farmafinder OK"
# Start monitoring stack
cd /home/f80ans0/Projects/Monitoring && docker compose up -d alloy
curl -sf http://localhost:12345/-/ready && echo "alloy ready"
curl -sf -X POST http://localhost:4318/v1/traces -H 'Content-Type: application/x-protobuf' --data-binary @/dev/null -o /dev/null -w '%{http_code}\n'
# Start FarmaFinder
cd /home/f80ans0/Projects/Webs/FarmaFinder && docker compose up -d --build
docker logs farmafinder-frontend 2>&1 | grep -i faro
docker logs farmafinder-backend 2>&1 | grep -i opentelemetry
# Grafana Explore (manual):
# Tempo → service.name = farmafinder-backend
# Loki → {app="farmafinder-frontend"} | json
# Prometheus → farovitals_largest_contentful_paint