feat: prometheus metrics endpoint on SN and DN nodes - #447
Conversation
|
Thanks for your contribution! Having a way to plug in tools like Grafana will be helpful for bother operators of the service and developers (e.g. to assist in determining where bottlenecks are). Also, the original intent of the /info endpoint was to be the path for fetching metrics, but you added a /metrics path. Can /info just be re-purposed? Or would it be better to have just /metrics and deprecate /info? Finally, how is(should) security handled? Some admins would prefer not to expose HSDS metric data to the outside world. Can the access be restricted to (say) just admin users? |
|
@jreadey, thanks for the heads up. I believe the multiproc concern doesn't apply to HSDS, as Gemini assumed we're using Gunicorn and firing multiple worker processes, which we're not. The About the dedicated Regarding security, specific internal routes are usually hidden through custom snippets in the Ingress resource or HTTPRouteFilters if you're using the Gateway API. I'll add it to the docs with a working example. |
|
Let's leave the /info path there for now -- I'll think about if it makes sense to remove or not after the merge. Have you tired this update with Grafana (or do you plan to do so)? I guess if there are any potential issues that would be a good way to tease them out. Should there be a prometheus.yml file as part of the PR? |
|
Good callout! We're actually running a custom build from this fork in production for about a week alongside the proposed metrics. I'll add an example dashboard and update the docs about how to run it locally in a few. |
- admin/docker/docker-compose.metrics.yml: Prometheus + Grafana overlay for any HSDS compose stack (Prometheus datasource pre-wired) - admin/prometheus/: example scrape config (relabels to the endpoint=sn|dn label the dashboard depends on) and promtool-checked alert rules - admin/grafana/hsds-dashboard.json: "HSDS" dashboard, 19 panels across cluster-internals and async/background-job rows - docs/prometheus_metrics.md + README: document the local stack, the endpoint-label dependency, and the dashboard; link the guide from the README - rename metric hsds_active_dn_count -> hsds_active_dns (the _count suffix is reserved for counters per Prometheus convention) - admin/kubernetes/k8s_deployment_aws.yml: declare the missing override configMap volume (kubectl apply would otherwise reject the manifest); drop a dead doc reference to a nonexistent singleton manifest Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@jreadey here's a screenshot of the Grafana dashboard that now lives in the admin/grafana folder |

Motivation
Running HSDS on Kubernetes, there's no machine-readable health signal beyond the
/infoJSON. This PR adds a Prometheus/metricsendpoint to every node, plus the Grafana dashboard, alert rules, and Kubernetes wiring to consume it — so operators can alert on health, saturation, and storage-backend problems with the usual Prometheus/Grafana stack.What changed
/metricsendpoint (hsds/metrics.py), via the officialprometheus_client:hsds_http_requests_total{method,status}and anhsds_http_request_duration_secondshistogram per request.hsds_node_ready), known DN count (hsds_active_dns), task saturation (hsds_tasks_active/hsds_tasks_max), WARN/ERROR log counts, LRU cache stats, and storage counters (errors, bytes read/written, by backend).process_*/python_gc_*come free;/metricsis served even when the node isn'tREADY.Async-internals instrumentation: SN→DN fan-out (
hsds_internal_requests_total,hsds_internal_request_duration_secondsvia a ClientSession TraceConfig), crawler saturation (hsds_crawler_queue_depth,hsds_crawler_active_workers), and housekeeping liveness/duration.Storage stats bug fixes (found while validating metrics live):
fileClient._file_stats_incrementwas missing its final increment, so every POSIX storage counter stayed at zero.bytes_inwas never incremented; now recorded onget_objectin the file, s3, and azure clients.Kubernetes / deployment:
prometheus.io/scrapeannotations and named container ports (sn,dn) on the deployment manifests./metrics,/info,/aboutto in-cluster callers (403 at the edge) — examplek8s_ingress_nginx.ymlandk8s_gateway_envoy.yml. These metrics let a standard HPA/KEDA replace the custom 503 autoscaler.overrideconfigMap volume (previously mounted but never defined).Observability tooling (
admin/):docker/docker-compose.metrics.yml: Prometheus + Grafana overlay for local runs (datasource pre-wired).prometheus/prometheus.yml(example scrape, relabeled to theendpoint=sn|dnlabel the dashboard needs) andprometheus/alert.rules.yml.grafana/hsds-dashboard.json: "HSDS" dashboard, 19 panels.Docs:
docs/prometheus_metrics.md(metric reference, rationale, annotation-vs-PodMonitor scraping, endpoint restriction, alerts, local stack, dashboard) and a README link.Dependency:
prometheus-clientadded topyproject.toml/requirements.txt.Testing
tests/unit/metrics_test.py(middleware, exposition, cache/storage/node/async metrics, handler, and a fileClient stats regression test);python testall.pypasses;flake8clean./metrics, Prometheus scrapes all targets withendpointlabels,promtoolvalidates the config and rules, and all 19 dashboard panel queries resolve against a live Prometheus.