From a04c54e2dc9a5663c060aac841bb02fe3f96d5e3 Mon Sep 17 00:00:00 2001 From: Sam Batschelet Date: Sun, 4 Oct 2026 21:33:15 -0400 Subject: [PATCH] fix(praxis-gateway): let the metrics ServiceMonitor set a scrape timeout Prometheus's default scrape timeout must not exceed the interval, so an interval under that default is rejected and the scrape never runs. The listener's ServiceMonitor had no way to set one, unlike grid-operator's. Unset leaves Prometheus's default. Signed-off-by: Sam Batschelet --- charts/praxis-gateway/README.md | 1 + .../templates/servicemonitor.yaml | 3 +++ .../tests/metrics_listener_test.yaml | 24 +++++++++++++++++++ charts/praxis-gateway/values.schema.json | 3 +++ charts/praxis-gateway/values.yaml | 4 ++++ 5 files changed, 35 insertions(+) diff --git a/charts/praxis-gateway/README.md b/charts/praxis-gateway/README.md index 673db027..d57138ca 100644 --- a/charts/praxis-gateway/README.md +++ b/charts/praxis-gateway/README.md @@ -251,6 +251,7 @@ Praxis AI image; these values may advance independently. | `metricsListener.existingSecret` | string | `""` | Secret with `tls.crt` and `tls.key`. On OpenShift, request it with `metricsListener.service.annotations` `service.beta.openshift.io/serving-cert-secret-name`. The listener reloads the cert when the Secret changes. | | `metricsListener.fromNamespaces` | list | `[]` | Namespace names allowed to reach the metrics port, for example `openshift-user-workload-monitoring`. | | `metricsListener.serviceMonitor.enabled` | bool | `false` | Render a ServiceMonitor that verifies the cert against `caConfigMap` (for example `openshift-service-ca.crt`, key `service-ca.crt`) and renames Praxis's `cluster` label to `backend`, since ACM uses `cluster` for the managed cluster. | +| `metricsListener.serviceMonitor.scrapeTimeout` | string | `""` | Scrape timeout. Unset leaves Prometheus's default of 10s, which Prometheus refuses when it exceeds the interval, so an interval under 10s needs this set to at most the interval. | | `gatewayConfig.upstreamCA.secretName` | string | `""` | CA bundle for backend TLS without a per-cluster CA (`upstream_ca_file`). | | `gatewayConfig.listenerTls.enabled` | bool | `false` | Terminate TLS at the listener from `existingSecret`, in render consumer or BYO mode. Render providers reject this setting and use `tls.existingSecret` for listener TLS. Names the port `https`. The cert mounts at `listenerTls.mountPath` (`/etc/praxis/listener-tls`), so a BYO config moving off `tls.enabled` must point its listener `cert_path`/`key_path` there. On OpenShift, annotate the Service with `service.beta.openshift.io/serving-cert-secret-name`. | | `port.containerPort` | int | `8080` | Container port. | diff --git a/charts/praxis-gateway/templates/servicemonitor.yaml b/charts/praxis-gateway/templates/servicemonitor.yaml index 8355592a..1f2b59a1 100644 --- a/charts/praxis-gateway/templates/servicemonitor.yaml +++ b/charts/praxis-gateway/templates/servicemonitor.yaml @@ -18,6 +18,9 @@ spec: scheme: https path: /metrics interval: {{ .serviceMonitor.interval }} + {{- with .serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . | quote }} + {{- end }} tlsConfig: serverName: {{ printf "%s.%s.svc" $name $.Release.Namespace }} ca: diff --git a/charts/praxis-gateway/tests/metrics_listener_test.yaml b/charts/praxis-gateway/tests/metrics_listener_test.yaml index 0cbd4899..6a6556ab 100644 --- a/charts/praxis-gateway/tests/metrics_listener_test.yaml +++ b/charts/praxis-gateway/tests/metrics_listener_test.yaml @@ -109,6 +109,30 @@ tests: - action: labeldrop regex: cluster + - it: leaves the scrape timeout to Prometheus unless it is set + template: templates/servicemonitor.yaml + set: + metricsListener.serviceMonitor.enabled: true + metricsListener.serviceMonitor.caConfigMap: {name: openshift-service-ca.crt, key: service-ca.crt} + asserts: + - notExists: + path: spec.endpoints[0].scrapeTimeout + + - it: scrapes with the timeout it is given, for an interval under Prometheus's default + template: templates/servicemonitor.yaml + set: + metricsListener.serviceMonitor.enabled: true + metricsListener.serviceMonitor.caConfigMap: {name: openshift-service-ca.crt, key: service-ca.crt} + metricsListener.serviceMonitor.interval: 5s + metricsListener.serviceMonitor.scrapeTimeout: 5s + asserts: + - equal: + path: spec.endpoints[0].interval + value: 5s + - equal: + path: spec.endpoints[0].scrapeTimeout + value: "5s" + - it: refuses the listener without the NetworkPolicy template: templates/deployment.yaml set: diff --git a/charts/praxis-gateway/values.schema.json b/charts/praxis-gateway/values.schema.json index dead5da8..5deea67e 100644 --- a/charts/praxis-gateway/values.schema.json +++ b/charts/praxis-gateway/values.schema.json @@ -784,6 +784,9 @@ "interval": { "type": "string" }, + "scrapeTimeout": { + "type": "string" + }, "caConfigMap": { "type": "object", "additionalProperties": false, diff --git a/charts/praxis-gateway/values.yaml b/charts/praxis-gateway/values.yaml index 66b3503c..fd0b7590 100644 --- a/charts/praxis-gateway/values.yaml +++ b/charts/praxis-gateway/values.yaml @@ -339,6 +339,10 @@ metricsListener: enabled: false # -- Scrape interval. interval: 30s + # -- Scrape timeout. Unset leaves Prometheus's default of 10s, which Prometheus + # refuses when it exceeds the interval, so an interval under 10s needs this set + # to at most the interval. + scrapeTimeout: "" # -- ConfigMap holding the CA that signed the metrics cert. Required when enabled. caConfigMap: name: ""