From b8cb5f458a61b94ab51bb0adb0d574a22b3697ce Mon Sep 17 00:00:00 2001 From: Michal Vavrinec Date: Tue, 4 Aug 2026 12:42:10 +0200 Subject: [PATCH] HYPERFLEET-1363 - refactor: unify observability values under monitoring section Consolidate all observability configuration under a single monitoring: section for consistency across HyperFleet charts. - Move serviceMonitor and tracing from top-level to monitoring section - Add honorLabels, metricRelabeling, namespaceSelector to serviceMonitor - Add dashboard toggle for future Grafana sidecar provisioning - Default sampler to parentbased_always_on --- charts/Chart.yaml | 2 +- charts/README.md | 37 ++-- charts/templates/configmap-dashboard.yaml | 12 ++ charts/templates/deployment.yaml | 2 +- charts/templates/servicemonitor.yaml | 24 ++- charts/values.schema.json | 209 +++++++++++++++------- charts/values.yaml | 69 ++++--- docs/config.md | 4 +- docs/deployment.md | 26 +-- docs/logging.md | 23 +-- scripts/test-helm.sh | 4 +- 11 files changed, 259 insertions(+), 153 deletions(-) create mode 100644 charts/templates/configmap-dashboard.yaml diff --git a/charts/Chart.yaml b/charts/Chart.yaml index 50903267..61bdc1d4 100644 --- a/charts/Chart.yaml +++ b/charts/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: hyperfleet-api description: HyperFleet API - Cluster Lifecycle Management Service type: application -version: 1.1.0 +version: 1.2.0 appVersion: "0.0.0-dev" maintainers: - name: HyperFleet Team diff --git a/charts/README.md b/charts/README.md index 4a1f2f56..cca98a83 100644 --- a/charts/README.md +++ b/charts/README.md @@ -1,6 +1,6 @@ # hyperfleet-api -![Version: 1.1.0](https://img.shields.io/badge/Version-1.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.0.0-dev](https://img.shields.io/badge/AppVersion-0.0.0--dev-informational?style=flat-square) +![Version: 1.2.0](https://img.shields.io/badge/Version-1.2.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.0.0-dev](https://img.shields.io/badge/AppVersion-0.0.0--dev-informational?style=flat-square) HyperFleet API - Cluster Lifecycle Management Service @@ -149,7 +149,7 @@ helm install hyperfleet-api oci://REGISTRY/hyperfleet-api \ | database.postgresql.persistence.enabled | bool | `false` | Enable persistent storage (uses emptyDir when disabled) | | database.postgresql.persistence.size | string | `"1Gi"` | Volume size | | database.postgresql.persistence.storageClass | string | `""` | StorageClass name (empty for cluster default) | -| monitoring | object | `{"podMonitoring":{"additionalLabels":{},"enabled":false,"interval":"30s","metricRelabeling":[],"tlsConfig":{"insecureSkipVerify":false}},"prometheusRule":{"additionalLabels":{},"enabled":false,"namespace":"","rules":{"reconciliationStuck":{"for":"5m","runbookUrl":""},"reconciliationTimeout":{"durationSeconds":1800,"for":"5m","runbookUrl":""}}}}` | Monitoring and alerting configuration | +| monitoring | object | `{"dashboard":{"enabled":false},"podMonitoring":{"additionalLabels":{},"enabled":false,"interval":"30s","metricRelabeling":[],"tlsConfig":{"insecureSkipVerify":false}},"prometheusRule":{"additionalLabels":{},"enabled":false,"namespace":"","rules":{"reconciliationStuck":{"for":"5m","runbookUrl":""},"reconciliationTimeout":{"durationSeconds":1800,"for":"5m","runbookUrl":""}}},"serviceMonitor":{"enabled":false,"honorLabels":true,"interval":"30s","labels":{},"metricRelabeling":[],"namespace":"","namespaceSelector":{},"scrapeTimeout":"10s"},"tracing":{"enabled":false,"otlpEndpoint":"","otlpProtocol":"grpc","propagators":"tracecontext,baggage","sampler":"parentbased_always_on","samplerArg":"","serviceName":"hyperfleet-api"}}` | Monitoring and alerting configuration | | monitoring.podMonitoring | object | `{"additionalLabels":{},"enabled":false,"interval":"30s","metricRelabeling":[],"tlsConfig":{"insecureSkipVerify":false}}` | PodMonitoring for Google Managed Prometheus (GMP) scraping | | monitoring.podMonitoring.enabled | bool | `false` | Create a PodMonitoring resource | | monitoring.podMonitoring.interval | string | `"30s"` | Scrape interval | @@ -169,20 +169,25 @@ helm install hyperfleet-api oci://REGISTRY/hyperfleet-api \ | monitoring.prometheusRule.rules.reconciliationTimeout.durationSeconds | int | `1800` | Stuck duration in seconds that triggers the critical alert | | monitoring.prometheusRule.rules.reconciliationTimeout.for | string | `"5m"` | Stabilization window before firing (short — the duration check is the real gate) | | monitoring.prometheusRule.rules.reconciliationTimeout.runbookUrl | string | `""` | Runbook URL included in the alert | -| serviceMonitor | object | `{"enabled":false,"interval":"30s","labels":{},"namespace":"","scrapeTimeout":"10s"}` | ServiceMonitor for Prometheus Operator scrape configuration | -| serviceMonitor.enabled | bool | `false` | Create a ServiceMonitor resource | -| serviceMonitor.interval | string | `"30s"` | Scrape interval | -| serviceMonitor.scrapeTimeout | string | `"10s"` | Scrape timeout | -| serviceMonitor.labels | object | `{}` | Additional labels for ServiceMonitor discovery | -| serviceMonitor.namespace | string | `""` | Namespace to create the ServiceMonitor in (defaults to release namespace) | -| tracing | object | `{"enabled":false,"otlpEndpoint":"","otlpProtocol":"grpc","propagators":"tracecontext,baggage","sampler":"parentbased_traceidratio","samplerArg":"1.0","serviceName":"hyperfleet-api"}` | Distributed tracing configuration (OpenTelemetry) | -| tracing.enabled | bool | `false` | Enable trace export | -| tracing.serviceName | string | `"hyperfleet-api"` | Service name reported in traces | -| tracing.otlpEndpoint | string | `""` | OTLP exporter endpoint (traces go to stdout when empty) | -| tracing.otlpProtocol | string | `"grpc"` | OTLP protocol (`grpc` or `http/protobuf`) | -| tracing.sampler | string | `"parentbased_traceidratio"` | Sampler type | -| tracing.samplerArg | string | `"1.0"` | Sampling rate (`1.0` for dev, `0.01` for production) | -| tracing.propagators | string | `"tracecontext,baggage"` | Context propagation formats | +| monitoring.serviceMonitor | object | `{"enabled":false,"honorLabels":true,"interval":"30s","labels":{},"metricRelabeling":[],"namespace":"","namespaceSelector":{},"scrapeTimeout":"10s"}` | ServiceMonitor for Prometheus Operator scrape configuration | +| monitoring.serviceMonitor.enabled | bool | `false` | Create a ServiceMonitor resource | +| monitoring.serviceMonitor.interval | string | `"30s"` | Scrape interval | +| monitoring.serviceMonitor.scrapeTimeout | string | `"10s"` | Scrape timeout (must be less than interval) | +| monitoring.serviceMonitor.labels | object | `{}` | Additional labels for ServiceMonitor discovery | +| monitoring.serviceMonitor.honorLabels | bool | `true` | Honor labels from the target to avoid overwriting | +| monitoring.serviceMonitor.metricRelabeling | list | `[]` | Metric relabel configs applied before ingestion | +| monitoring.serviceMonitor.namespaceSelector | object | `{}` | Namespace selector for cross-namespace monitoring | +| monitoring.serviceMonitor.namespace | string | `""` | Namespace to create the ServiceMonitor in (defaults to release namespace) | +| monitoring.dashboard | object | `{"enabled":false}` | Grafana dashboard provisioning via sidecar ConfigMap | +| monitoring.dashboard.enabled | bool | `false` | Create a ConfigMap with the Grafana dashboard JSON | +| monitoring.tracing | object | `{"enabled":false,"otlpEndpoint":"","otlpProtocol":"grpc","propagators":"tracecontext,baggage","sampler":"parentbased_always_on","samplerArg":"","serviceName":"hyperfleet-api"}` | Distributed tracing configuration (OpenTelemetry) | +| monitoring.tracing.enabled | bool | `false` | Enable trace export | +| monitoring.tracing.serviceName | string | `"hyperfleet-api"` | Service name reported in traces | +| monitoring.tracing.otlpEndpoint | string | `""` | OTLP exporter endpoint (traces go to stdout when empty) | +| monitoring.tracing.otlpProtocol | string | `"grpc"` | OTLP protocol (`grpc` or `http/protobuf`) | +| monitoring.tracing.sampler | string | `"parentbased_always_on"` | Sampler type | +| monitoring.tracing.samplerArg | string | `""` | Sampling rate (only used with ratio-based samplers) | +| monitoring.tracing.propagators | string | `"tracecontext,baggage"` | Context propagation formats | | nativeSidecars | list | `[]` | Native sidecar containers (Kubernetes 1.28+). Native sidecars are init containers with `restartPolicy: Always` — they start before other init containers and keep running throughout the pod lifecycle. Use this for database proxies that must be available during `db-migrate`. Each entry is a full Kubernetes container spec. | | sidecars | list | `[]` | Regular sidecar containers. These start after init containers complete. Use `nativeSidecars` above for containers that must be available during init (e.g. database proxies). Each entry is a full Kubernetes container spec. | | validationSchema | object | `{"content":"","enabled":false,"existingConfigMap":""}` | Validation schema configuration. Supply a custom OpenAPI schema for resource spec validation. When enabled, the schema is mounted into the container and every create/update request is validated against it. The API will fail to start if the schema is invalid. | diff --git a/charts/templates/configmap-dashboard.yaml b/charts/templates/configmap-dashboard.yaml new file mode 100644 index 00000000..52318362 --- /dev/null +++ b/charts/templates/configmap-dashboard.yaml @@ -0,0 +1,12 @@ +{{- if .Values.monitoring.dashboard.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "hyperfleet-api.fullname" . }}-grafana-dashboard + labels: + {{- include "hyperfleet-api.labels" . | nindent 4 }} + grafana_dashboard: "1" +data: + hyperfleet-api.json: |- + {{- .Files.Get "dashboards/hyperfleet-api.json" | nindent 4 }} +{{- end }} diff --git a/charts/templates/deployment.yaml b/charts/templates/deployment.yaml index 819a14ef..a57c82cf 100644 --- a/charts/templates/deployment.yaml +++ b/charts/templates/deployment.yaml @@ -107,7 +107,7 @@ spec: # Config file from ConfigMap (generated from values) - name: HYPERFLEET_CONFIG value: /etc/hyperfleet/config.yaml - {{- with .Values.tracing }} + {{- with .Values.monitoring.tracing }} - name: HYPERFLEET_TRACING_ENABLED value: {{ .enabled | quote }} {{- if .enabled }} diff --git a/charts/templates/servicemonitor.yaml b/charts/templates/servicemonitor.yaml index f36e6176..dd582675 100644 --- a/charts/templates/servicemonitor.yaml +++ b/charts/templates/servicemonitor.yaml @@ -1,21 +1,26 @@ -{{- if .Values.serviceMonitor.enabled }} +{{- if .Values.monitoring.serviceMonitor.enabled }} apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: {{ include "hyperfleet-api.fullname" . }} - {{- if .Values.serviceMonitor.namespace }} - namespace: {{ .Values.serviceMonitor.namespace }} + {{- if .Values.monitoring.serviceMonitor.namespace }} + namespace: {{ .Values.monitoring.serviceMonitor.namespace }} + {{- else }} + namespace: {{ .Release.Namespace }} {{- end }} labels: {{- include "hyperfleet-api.labels" . | nindent 4 }} - {{- with .Values.serviceMonitor.labels }} + {{- with .Values.monitoring.serviceMonitor.labels }} {{- toYaml . | nindent 4 }} {{- end }} spec: selector: matchLabels: {{- include "hyperfleet-api.selectorLabels" . | nindent 6 }} - {{- if .Values.serviceMonitor.namespace }} + {{- if not (empty .Values.monitoring.serviceMonitor.namespaceSelector) }} + namespaceSelector: + {{- toYaml .Values.monitoring.serviceMonitor.namespaceSelector | nindent 4 }} + {{- else if .Values.monitoring.serviceMonitor.namespace }} namespaceSelector: matchNames: - {{ .Release.Namespace }} @@ -23,6 +28,11 @@ spec: endpoints: - port: metrics path: /metrics - interval: {{ .Values.serviceMonitor.interval }} - scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + interval: {{ .Values.monitoring.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.monitoring.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.monitoring.serviceMonitor.honorLabels }} + {{- with .Values.monitoring.serviceMonitor.metricRelabeling }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} {{- end }} diff --git a/charts/values.schema.json b/charts/values.schema.json index c6bf546f..60855401 100644 --- a/charts/values.schema.json +++ b/charts/values.schema.json @@ -188,12 +188,18 @@ "description": "HTTP header carrying a pre-authenticated identity (bypasses JWT claim when set)" } }, - "required": ["issuer_url"], + "required": [ + "issuer_url" + ], "if": { - "required": ["jwk_cert_ca_file"] + "required": [ + "jwk_cert_ca_file" + ] }, "then": { - "required": ["jwk_cert_url"] + "required": [ + "jwk_cert_url" + ] } } } @@ -416,7 +422,10 @@ "description": "Entity descriptors registered at startup. Each entry auto-generates REST endpoints, spec validation, and delete policies.", "items": { "type": "object", - "required": ["kind", "plural"], + "required": [ + "kind", + "plural" + ], "properties": { "kind": { "type": "string", @@ -432,7 +441,10 @@ }, "on_parent_delete": { "type": "string", - "enum": ["restrict", "cascade"], + "enum": [ + "restrict", + "cascade" + ], "description": "Child behavior when parent is deleted (restrict or cascade)" }, "spec_schema_name": { @@ -441,7 +453,9 @@ }, "required_adapters": { "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "description": "Adapters that must finalize before hard-delete" }, "name_min_len": { @@ -461,7 +475,10 @@ "description": "Non-ownership associations to other entity types (HYPERFLEET-1156)", "items": { "type": "object", - "required": ["ref_type", "target_kind"], + "required": [ + "ref_type", + "target_kind" + ], "properties": { "ref_type": { "type": "string", @@ -870,70 +887,130 @@ } } } - } - } - }, - "serviceMonitor": { - "type": "object", - "description": "ServiceMonitor resource for Prometheus Operator scrape configuration", - "properties": { - "enabled": { - "type": "boolean", - "description": "Create a ServiceMonitor resource" - }, - "interval": { - "type": "string", - "description": "Prometheus scrape interval (e.g. 30s)" - }, - "scrapeTimeout": { - "type": "string", - "description": "Prometheus scrape timeout (e.g. 10s)" }, - "labels": { + "serviceMonitor": { "type": "object", - "description": "Extra labels applied to the ServiceMonitor for Prometheus selector matching" - }, - "namespace": { - "type": "string", - "description": "Namespace for the ServiceMonitor; defaults to the release namespace" - } - } - }, - "tracing": { - "type": "object", - "description": "Distributed tracing via OpenTelemetry", - "properties": { - "enabled": { - "type": "boolean", - "description": "Enable OpenTelemetry tracing" - }, - "serviceName": { - "type": "string", - "description": "Service name reported in traces" - }, - "otlpEndpoint": { - "type": "string", - "description": "OTLP exporter endpoint; traces go to stdout if empty" - }, - "otlpProtocol": { - "type": "string", - "enum": [ - "grpc", - "http/protobuf" - ], - "description": "OTLP exporter transport protocol" + "description": "ServiceMonitor resource for Prometheus Operator scrape configuration", + "properties": { + "enabled": { + "type": "boolean", + "description": "Create a ServiceMonitor resource" + }, + "interval": { + "type": "string", + "description": "Prometheus scrape interval (e.g. 30s)" + }, + "scrapeTimeout": { + "type": "string", + "description": "Prometheus scrape timeout (e.g. 10s)" + }, + "labels": { + "type": "object", + "description": "Extra labels applied to the ServiceMonitor for Prometheus selector matching" + }, + "namespace": { + "type": "string", + "description": "Namespace for the ServiceMonitor; defaults to the release namespace" + }, + "honorLabels": { + "type": "boolean", + "description": "Honor labels from the target to avoid overwriting" + }, + "metricRelabeling": { + "type": "array", + "description": "Metric relabel configs applied before ingestion", + "items": { + "type": "object" + } + }, + "namespaceSelector": { + "type": "object", + "description": "Namespace selector for cross-namespace monitoring" + } + } }, - "sampler": { - "type": "string", - "description": "Trace sampler type (e.g. parentbased_traceidratio)" + "tracing": { + "type": "object", + "description": "Distributed tracing via OpenTelemetry", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable OpenTelemetry tracing" + }, + "serviceName": { + "type": "string", + "description": "Service name reported in traces" + }, + "otlpEndpoint": { + "type": "string", + "description": "OTLP exporter endpoint; traces go to stdout if empty" + }, + "otlpProtocol": { + "type": "string", + "enum": [ + "grpc", + "http/protobuf" + ], + "description": "OTLP exporter transport protocol" + }, + "sampler": { + "type": "string", + "description": "Sampler type" + }, + "samplerArg": { + "type": "string", + "description": "Sampling rate (only used with ratio-based samplers)" + }, + "propagators": { + "type": "string", + "description": "Comma-separated list of context propagators (e.g. tracecontext,baggage)" + } + } }, - "samplerArg": { - "type": "string", - "description": "Sampler argument; for traceidratio this is the sampling rate (0.0-1.0)" + "dashboard": { + "type": "object", + "description": "Grafana dashboard provisioning via sidecar ConfigMap", + "properties": { + "enabled": { + "type": "boolean", + "description": "Create a ConfigMap with the Grafana dashboard JSON" + } + } }, - "propagators": { - "type": "string", - "description": "Comma-separated list of context propagators (e.g. tracecontext,baggage)" + "podMonitoring": { + "type": "object", + "description": "PodMonitoring for Google Managed Prometheus (GMP) scraping", + "properties": { + "enabled": { + "type": "boolean", + "description": "Create a PodMonitoring resource" + }, + "interval": { + "type": "string", + "description": "Scrape interval (e.g. 30s)" + }, + "additionalLabels": { + "type": "object", + "description": "Additional labels for the PodMonitoring resource" + }, + "metricRelabeling": { + "type": "array", + "description": "Metric relabel configs applied before ingestion", + "items": { + "type": "object" + } + }, + "tlsConfig": { + "type": "object", + "description": "TLS configuration for metrics endpoint", + "properties": { + "insecureSkipVerify": { + "type": "boolean", + "description": "Disable target certificate validation" + } + } + } + } } } }, diff --git a/charts/values.yaml b/charts/values.yaml index db71b285..9d144668 100644 --- a/charts/values.yaml +++ b/charts/values.yaml @@ -432,35 +432,46 @@ monitoring: # -- Runbook URL included in the alert runbookUrl: "" -# -- ServiceMonitor for Prometheus Operator scrape configuration -serviceMonitor: - # -- Create a ServiceMonitor resource - enabled: false - # -- Scrape interval - interval: 30s - # -- Scrape timeout - scrapeTimeout: 10s - # -- Additional labels for ServiceMonitor discovery - labels: {} - # -- Namespace to create the ServiceMonitor in (defaults to release namespace) - namespace: "" - -# -- Distributed tracing configuration (OpenTelemetry) -tracing: - # -- Enable trace export - enabled: false - # -- Service name reported in traces - serviceName: "hyperfleet-api" - # -- OTLP exporter endpoint (traces go to stdout when empty) - otlpEndpoint: "" - # -- OTLP protocol (`grpc` or `http/protobuf`) - otlpProtocol: "grpc" - # -- Sampler type - sampler: "parentbased_traceidratio" - # -- Sampling rate (`1.0` for dev, `0.01` for production) - samplerArg: "1.0" - # -- Context propagation formats - propagators: "tracecontext,baggage" + # -- ServiceMonitor for Prometheus Operator scrape configuration + serviceMonitor: + # -- Create a ServiceMonitor resource + enabled: false + # -- Scrape interval + interval: 30s + # -- Scrape timeout (must be less than interval) + scrapeTimeout: 10s + # -- Additional labels for ServiceMonitor discovery + labels: {} + # -- Honor labels from the target to avoid overwriting + honorLabels: true + # -- Metric relabel configs applied before ingestion + metricRelabeling: [] + # -- Namespace selector for cross-namespace monitoring + namespaceSelector: {} + # -- Namespace to create the ServiceMonitor in (defaults to release namespace) + namespace: "" + + # -- Grafana dashboard provisioning via sidecar ConfigMap + dashboard: + # -- Create a ConfigMap with the Grafana dashboard JSON + enabled: false + + # -- Distributed tracing configuration (OpenTelemetry) + tracing: + # -- Enable trace export + enabled: false + # -- Service name reported in traces + serviceName: "hyperfleet-api" + # -- OTLP exporter endpoint (traces go to stdout when empty) + otlpEndpoint: "" + # -- OTLP protocol (`grpc` or `http/protobuf`) + otlpProtocol: "grpc" + # -- Sampler type + sampler: "parentbased_always_on" + # -- Sampling rate (only used with ratio-based samplers) + samplerArg: "" + # -- Context propagation formats + propagators: "tracecontext,baggage" # -- Native sidecar containers (Kubernetes 1.28+). Native sidecars are init # containers with `restartPolicy: Always` — they start before other init diff --git a/docs/config.md b/docs/config.md index febe0b64..02b5aca2 100644 --- a/docs/config.md +++ b/docs/config.md @@ -209,8 +209,8 @@ Once enabled, tracing is configured using standard OpenTelemetry variables: | `OTEL_SERVICE_NAME` | Service name in traces | `hyperfleet-api` | | `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint | stdout exporter | | `OTEL_EXPORTER_OTLP_PROTOCOL` | Export protocol (`grpc` or `http/protobuf`) | `grpc` | -| `OTEL_TRACES_SAMPLER` | Sampler type | `parentbased_traceidratio` | -| `OTEL_TRACES_SAMPLER_ARG` | Sampling rate (0.0-1.0) | `1.0` | +| `OTEL_TRACES_SAMPLER` | Sampler type | `parentbased_always_on` | +| `OTEL_TRACES_SAMPLER_ARG` | Sampling rate (only used with ratio-based samplers) | `""` | | `OTEL_RESOURCE_ATTRIBUTES` | Additional resource attributes (k=v,k2=v2) | - | **See:** [Logging Documentation](logging.md#opentelemetry-integration) for tracing configuration details and [Tracing Standard](https://github.com/openshift-hyperfleet/architecture/blob/main/hyperfleet/standards/tracing.md#configuration) for complete reference. diff --git a/docs/deployment.md b/docs/deployment.md index a7d6462b..7cfcfcdf 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -290,11 +290,11 @@ helm uninstall hyperfleet-api --namespace hyperfleet-system | `database.postgresql.enabled` | Enable built-in PostgreSQL | `true` | | `database.external.enabled` | Use external database | `false` | | `database.external.secretName` | Secret containing database credentials | `hyperfleet-db-external` | -| `serviceMonitor.enabled` | Enable Prometheus Operator ServiceMonitor | `false` | -| `serviceMonitor.interval` | Metrics scrape interval | `30s` | -| `serviceMonitor.scrapeTimeout` | Metrics scrape timeout | `10s` | -| `serviceMonitor.labels` | Additional labels for Prometheus selector | `{}` | -| `serviceMonitor.namespace` | Namespace for ServiceMonitor (if different) | `""` | +| `monitoring.serviceMonitor.enabled` | Enable Prometheus Operator ServiceMonitor | `false` | +| `monitoring.serviceMonitor.interval` | Metrics scrape interval | `30s` | +| `monitoring.serviceMonitor.scrapeTimeout` | Metrics scrape timeout | `10s` | +| `monitoring.serviceMonitor.labels` | Additional labels for Prometheus selector | `{}` | +| `monitoring.serviceMonitor.namespace` | Namespace for ServiceMonitor (if different) | `""` | | `replicaCount` | Number of API replicas | `1` | | `resources.limits.cpu` | CPU limit | `500m` | | `resources.limits.memory` | Memory limit | `512Mi` | @@ -369,11 +369,11 @@ helm install hyperfleet-api oci://quay.io/redhat-services-prod/hyperfleet-tenant | `resources.limits.memory` | Memory limit | `512Mi` | | `podDisruptionBudget.enabled` | Enable PodDisruptionBudget | `false` | | `podDisruptionBudget.minAvailable` | Minimum available pods during disruption | `1` | -| `serviceMonitor.enabled` | Enable Prometheus Operator ServiceMonitor | `false` | -| `serviceMonitor.interval` | Metrics scrape interval | `30s` | -| `serviceMonitor.scrapeTimeout` | Metrics scrape timeout | `10s` | -| `serviceMonitor.labels` | Additional labels for Prometheus selector | `{}` | -| `serviceMonitor.namespace` | Namespace for ServiceMonitor (if different) | `""` | +| `monitoring.serviceMonitor.enabled` | Enable Prometheus Operator ServiceMonitor | `false` | +| `monitoring.serviceMonitor.interval` | Metrics scrape interval | `30s` | +| `monitoring.serviceMonitor.scrapeTimeout` | Metrics scrape timeout | `10s` | +| `monitoring.serviceMonitor.labels` | Additional labels for Prometheus selector | `{}` | +| `monitoring.serviceMonitor.namespace` | Namespace for ServiceMonitor (if different) | `""` | See [Configuration Guide](config.md) for the complete application configuration reference and [`charts/values.yaml`](../charts/values.yaml) for all Helm-specific settings. @@ -445,13 +445,13 @@ helm install hyperfleet-api oci://quay.io/redhat-services-prod/hyperfleet-tenant --set image.registry=quay.io \ --set image.repository=redhat-services-prod/hyperfleet-tenant/hyperfleet/hyperfleet-api \ --set image.tag= \ - --set serviceMonitor.enabled=true + --set monitoring.serviceMonitor.enabled=true # With custom Prometheus selector labels ---set serviceMonitor.labels.release=prometheus +--set monitoring.serviceMonitor.labels.release=prometheus # ServiceMonitor in a different namespace ---set serviceMonitor.namespace=monitoring +--set monitoring.serviceMonitor.namespace=monitoring ``` --- diff --git a/docs/logging.md b/docs/logging.md index 2d7d35a8..3f951464 100644 --- a/docs/logging.md +++ b/docs/logging.md @@ -74,8 +74,8 @@ HyperFleet uses standard OpenTelemetry environment variables for tracing configu | `OTEL_SERVICE_NAME` | Service name in traces | `hyperfleet-api` | `hyperfleet-api-prod` | | `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint (if not set, uses stdout) | - | `http://otel-collector:4317` | | `OTEL_EXPORTER_OTLP_PROTOCOL` | OTLP protocol | `grpc` | `grpc`, `http/protobuf` | -| `OTEL_TRACES_SAMPLER` | Sampler type | `parentbased_traceidratio` | `always_on`, `traceidratio` | -| `OTEL_TRACES_SAMPLER_ARG` | Sampling rate (0.0-1.0) | `1.0` | `0.1` (10%) | +| `OTEL_TRACES_SAMPLER` | Sampler type | `parentbased_always_on` | `always_on`, `traceidratio` | +| `OTEL_TRACES_SAMPLER_ARG` | Argument passed to the sampler | - | `0.1` (10%) | | `OTEL_RESOURCE_ATTRIBUTES` | Additional resource attributes | - | `env=prod,region=us-east` | **Variable Precedence (highest to lowest):** @@ -389,26 +389,17 @@ The OTel middleware automatically: ### Sampling -Configure sampling using standard OpenTelemetry environment variables: +By default, all traces are sampled (`parentbased_always_on`). To reduce overhead, switch to ratio-based sampling: ```bash -# Sampler type (default: parentbased_traceidratio) export OTEL_TRACES_SAMPLER=parentbased_traceidratio - -# Sampling rate: 0.0-1.0 (default: 1.0) -export OTEL_TRACES_SAMPLER_ARG=0.1 # 10% of requests traced +export OTEL_TRACES_SAMPLER_ARG=0.1 # 10% of root spans ``` -**Sampling rate examples:** -- `0.0`: No traces (disabled) -- `0.1`: 10% of requests traced (recommended for production) -- `1.0`: All requests traced (development only) - **Sampler types:** -- `always_on`: Sample all requests -- `always_off`: Sample no requests -- `traceidratio`: Sample based on trace ID ratio (use with OTEL_TRACES_SAMPLER_ARG) -- `parentbased_traceidratio`: Respect parent decision, otherwise use trace ID ratio (default) +- `parentbased_always_on`: Sample all root spans (default) +- `parentbased_traceidratio`: Sample a percentage of root spans (set rate via `OTEL_TRACES_SAMPLER_ARG`) +- `always_on` / `always_off`: Sample all or none, ignoring parent context ## Data Masking diff --git a/scripts/test-helm.sh b/scripts/test-helm.sh index 37fe700f..e2da97fc 100755 --- a/scripts/test-helm.sh +++ b/scripts/test-helm.sh @@ -119,8 +119,8 @@ pass "PDB config template" run_test "template with ServiceMonitor enabled" render \ - --set serviceMonitor.enabled=true \ - --set serviceMonitor.interval=15s | kubeconform_validate + --set monitoring.serviceMonitor.enabled=true \ + --set monitoring.serviceMonitor.interval=15s | kubeconform_validate pass "ServiceMonitor config template" run_test "template with PodMonitoring enabled"