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
This commit is contained in:
@@ -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
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
providers:
|
||||||
|
- name: SciMesh
|
||||||
|
type: file
|
||||||
|
disableDeletion: false
|
||||||
|
allowUiUpdates: true
|
||||||
|
options:
|
||||||
|
path: /var/lib/grafana/dashboards
|
||||||
|
foldersFromFilesStructure: false
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Prometheus
|
||||||
|
uid: prometheus
|
||||||
|
type: prometheus
|
||||||
|
access: proxy
|
||||||
|
url: http://prometheus:9090
|
||||||
|
isDefault: true
|
||||||
|
editable: false
|
||||||
@@ -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"]
|
||||||
@@ -12,6 +12,8 @@ project=${DEMO_PROJECT:-scimesh-demo}
|
|||||||
postgres_port=${DEMO_POSTGRES_PORT:-55432}
|
postgres_port=${DEMO_POSTGRES_PORT:-55432}
|
||||||
coordinator_port=${DEMO_COORDINATOR_PORT:-18080}
|
coordinator_port=${DEMO_COORDINATOR_PORT:-18080}
|
||||||
userservice_port=${DEMO_USERSERVICE_PORT:-18081}
|
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}
|
ui_token=${DEMO_UI_TOKEN:-demo-ui-secret}
|
||||||
worker_token=${DEMO_WORKER_TOKEN:-demo-worker-token}
|
worker_token=${DEMO_WORKER_TOKEN:-demo-worker-token}
|
||||||
# Shared HS256 secret; the coordinator verifies userservice tokens with it. Must
|
# Shared HS256 secret; the coordinator verifies userservice tokens with it. Must
|
||||||
@@ -34,6 +36,8 @@ compose() {
|
|||||||
POSTGRES_PORT="$postgres_port" \
|
POSTGRES_PORT="$postgres_port" \
|
||||||
COORDINATOR_PORT="$coordinator_port" \
|
COORDINATOR_PORT="$coordinator_port" \
|
||||||
USERSERVICE_PORT="$userservice_port" \
|
USERSERVICE_PORT="$userservice_port" \
|
||||||
|
PROMETHEUS_PORT="$prometheus_port" \
|
||||||
|
GRAFANA_PORT="$grafana_port" \
|
||||||
UI_AUTH_TOKEN="$ui_token" \
|
UI_AUTH_TOKEN="$ui_token" \
|
||||||
WORKER_AUTH_TOKEN="$worker_token" \
|
WORKER_AUTH_TOKEN="$worker_token" \
|
||||||
JWT_SECRET="$jwt_secret" \
|
JWT_SECRET="$jwt_secret" \
|
||||||
@@ -41,7 +45,8 @@ compose() {
|
|||||||
BOOTSTRAP_ADMIN_PASSWORD="$admin_password" \
|
BOOTSTRAP_ADMIN_PASSWORD="$admin_password" \
|
||||||
docker compose -p "$project" \
|
docker compose -p "$project" \
|
||||||
-f "$coordinator_dir/docker-compose.yml" \
|
-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() {
|
stop_workers() {
|
||||||
@@ -152,6 +157,8 @@ SciMesh manual demo is ready.
|
|||||||
UI: http://localhost:$coordinator_port/ui (shows a login page)
|
UI: http://localhost:$coordinator_port/ui (shows a login page)
|
||||||
Admin login: $admin_email / $admin_password
|
Admin login: $admin_email / $admin_password
|
||||||
Userservice: http://localhost:$userservice_port
|
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
|
Workers: $workers local reference workers
|
||||||
|
|
||||||
Sign in with the admin above, or register a new account from the login page.
|
Sign in with the admin above, or register a new account from the login page.
|
||||||
|
|||||||
Reference in New Issue
Block a user