From 779ff8c10e8235431101a2808a9e991071c3382d Mon Sep 17 00:00:00 2001 From: Efremenko Arhip Date: Sun, 26 Jul 2026 21:49:52 +0300 Subject: [PATCH] feat(demo): Prometheus + Grafana with a provisioned dashboard make demo-ui now also starts Prometheus (scrapes coordinator:8080/metrics) and Grafana with a provisioned datasource and a SciMesh Coordinator dashboard (request rate & p95 by route, status mix, goroutines, RSS). Grafana allows anonymous viewing so the dashboard opens without a login; admin/admin to edit. - monitoring/prometheus.yml + grafana provisioning + dashboard JSON - docker-compose.monitoring.yml overlay (third -f in demo-ui.sh) - demo prints the Grafana and Prometheus URLs --- coordinator/docker-compose.monitoring.yml | 30 +++++++ .../grafana/dashboards/coordinator.json | 88 +++++++++++++++++++ .../provisioning/dashboards/provider.yml | 10 +++ .../provisioning/datasources/prometheus.yml | 10 +++ coordinator/monitoring/prometheus.yml | 10 +++ coordinator/scripts/demo-ui.sh | 9 +- 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 coordinator/docker-compose.monitoring.yml create mode 100644 coordinator/monitoring/grafana/dashboards/coordinator.json create mode 100644 coordinator/monitoring/grafana/provisioning/dashboards/provider.yml create mode 100644 coordinator/monitoring/grafana/provisioning/datasources/prometheus.yml create mode 100644 coordinator/monitoring/prometheus.yml diff --git a/coordinator/docker-compose.monitoring.yml b/coordinator/docker-compose.monitoring.yml new file mode 100644 index 0000000..1833a98 --- /dev/null +++ b/coordinator/docker-compose.monitoring.yml @@ -0,0 +1,30 @@ +# Demo overlay: Prometheus scrapes the coordinator's /metrics, Grafana shows the +# provisioned SciMesh dashboard. Merged by scripts/demo-ui.sh with a third -f. +# Both share the coordinator's compose network, so Prometheus reaches it by name. + +services: + prometheus: + image: prom/prometheus:v2.54.1 + volumes: + - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro + ports: + - "${PROMETHEUS_PORT:-19090}:9090" + restart: unless-stopped + + grafana: + image: grafana/grafana:11.2.0 + depends_on: + - prometheus + environment: + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin} + # Anonymous viewing so the demo dashboard opens without a login. + GF_AUTH_ANONYMOUS_ENABLED: "true" + GF_AUTH_ANONYMOUS_ORG_ROLE: Viewer + GF_USERS_DEFAULT_THEME: dark + volumes: + - ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro + - ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro + ports: + - "${GRAFANA_PORT:-13000}:3000" + restart: unless-stopped diff --git a/coordinator/monitoring/grafana/dashboards/coordinator.json b/coordinator/monitoring/grafana/dashboards/coordinator.json new file mode 100644 index 0000000..65cd5ff --- /dev/null +++ b/coordinator/monitoring/grafana/dashboards/coordinator.json @@ -0,0 +1,88 @@ +{ + "annotations": { "list": [] }, + "editable": true, + "graphTooltip": 1, + "schemaVersion": 39, + "tags": ["scimesh"], + "time": { "from": "now-15m", "to": "now" }, + "refresh": "5s", + "title": "SciMesh Coordinator", + "uid": "scimesh-coordinator", + "panels": [ + { + "type": "timeseries", + "title": "HTTP request rate by route", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, + "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum by (route) (rate(scimesh_http_requests_total[1m]))", + "legendFormat": "{{route}}" + } + ] + }, + { + "type": "timeseries", + "title": "p95 latency by route", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, + "fieldConfig": { "defaults": { "unit": "s" }, "overrides": [] }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "histogram_quantile(0.95, sum by (le, route) (rate(scimesh_http_request_duration_seconds_bucket[5m])))", + "legendFormat": "{{route}}" + } + ] + }, + { + "type": "timeseries", + "title": "Requests by status", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 }, + "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum by (status) (rate(scimesh_http_requests_total[1m]))", + "legendFormat": "{{status}}" + } + ] + }, + { + "type": "timeseries", + "title": "Goroutines", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "gridPos": { "h": 8, "w": 6, "x": 12, "y": 8 }, + "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "go_goroutines{job=\"coordinator\"}", + "legendFormat": "goroutines" + } + ] + }, + { + "type": "timeseries", + "title": "Resident memory", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "gridPos": { "h": 8, "w": 6, "x": 18, "y": 8 }, + "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [] }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "process_resident_memory_bytes{job=\"coordinator\"}", + "legendFormat": "rss" + } + ] + } + ] +} diff --git a/coordinator/monitoring/grafana/provisioning/dashboards/provider.yml b/coordinator/monitoring/grafana/provisioning/dashboards/provider.yml new file mode 100644 index 0000000..efb8556 --- /dev/null +++ b/coordinator/monitoring/grafana/provisioning/dashboards/provider.yml @@ -0,0 +1,10 @@ +apiVersion: 1 + +providers: + - name: SciMesh + type: file + disableDeletion: false + allowUiUpdates: true + options: + path: /var/lib/grafana/dashboards + foldersFromFilesStructure: false diff --git a/coordinator/monitoring/grafana/provisioning/datasources/prometheus.yml b/coordinator/monitoring/grafana/provisioning/datasources/prometheus.yml new file mode 100644 index 0000000..00f9915 --- /dev/null +++ b/coordinator/monitoring/grafana/provisioning/datasources/prometheus.yml @@ -0,0 +1,10 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + uid: prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + editable: false diff --git a/coordinator/monitoring/prometheus.yml b/coordinator/monitoring/prometheus.yml new file mode 100644 index 0000000..2ebe7f7 --- /dev/null +++ b/coordinator/monitoring/prometheus.yml @@ -0,0 +1,10 @@ +# Prometheus scrape config for the SciMesh demo. Prometheus runs in the same +# compose network as the coordinator, so it reaches it by service name. +global: + scrape_interval: 5s + evaluation_interval: 5s + +scrape_configs: + - job_name: coordinator + static_configs: + - targets: ["coordinator:8080"] diff --git a/coordinator/scripts/demo-ui.sh b/coordinator/scripts/demo-ui.sh index 3024b09..3d58183 100755 --- a/coordinator/scripts/demo-ui.sh +++ b/coordinator/scripts/demo-ui.sh @@ -12,6 +12,8 @@ project=${DEMO_PROJECT:-scimesh-demo} postgres_port=${DEMO_POSTGRES_PORT:-55432} coordinator_port=${DEMO_COORDINATOR_PORT:-18080} userservice_port=${DEMO_USERSERVICE_PORT:-18081} +prometheus_port=${DEMO_PROMETHEUS_PORT:-19090} +grafana_port=${DEMO_GRAFANA_PORT:-13000} ui_token=${DEMO_UI_TOKEN:-demo-ui-secret} worker_token=${DEMO_WORKER_TOKEN:-demo-worker-token} # Shared HS256 secret; the coordinator verifies userservice tokens with it. Must @@ -34,6 +36,8 @@ compose() { POSTGRES_PORT="$postgres_port" \ COORDINATOR_PORT="$coordinator_port" \ USERSERVICE_PORT="$userservice_port" \ + PROMETHEUS_PORT="$prometheus_port" \ + GRAFANA_PORT="$grafana_port" \ UI_AUTH_TOKEN="$ui_token" \ WORKER_AUTH_TOKEN="$worker_token" \ JWT_SECRET="$jwt_secret" \ @@ -41,7 +45,8 @@ compose() { BOOTSTRAP_ADMIN_PASSWORD="$admin_password" \ docker compose -p "$project" \ -f "$coordinator_dir/docker-compose.yml" \ - -f "$coordinator_dir/docker-compose.users.yml" "$@" + -f "$coordinator_dir/docker-compose.users.yml" \ + -f "$coordinator_dir/docker-compose.monitoring.yml" "$@" } stop_workers() { @@ -152,6 +157,8 @@ SciMesh manual demo is ready. UI: http://localhost:$coordinator_port/ui (shows a login page) Admin login: $admin_email / $admin_password Userservice: http://localhost:$userservice_port + Grafana: http://localhost:$grafana_port (anonymous view; admin/${GRAFANA_PASSWORD:-admin} to edit) + Prometheus: http://localhost:$prometheus_port Workers: $workers local reference workers Sign in with the admin above, or register a new account from the login page.