From 5ce1e11b47c0fd3c25315c8ecc889f70cba5e335 Mon Sep 17 00:00:00 2001 From: Thomas Taylor Date: Wed, 5 Nov 2025 22:02:28 -0800 Subject: [PATCH 1/9] Implement metrics collection for Plane Enterprise - Added metrics configuration to values.yaml, enabling metrics collection and telemetry. - Introduced ClusterRole and ClusterRoleBinding for metrics scraping in service-account.yaml. - Created metrics-config ConfigMap for OpenTelemetry agent configuration. - Added metrics-agent deployment template to manage the OpenTelemetry collector. - Implemented helper function for generating installation UUID in _helpers.tpl. This update enhances observability by integrating metrics collection capabilities into the Plane Enterprise Helm chart. --- .../plane-enterprise/templates/_helpers.tpl | 8 + .../config-secrets/metrics-config.yaml | 163 ++++++++++++++++++ .../templates/service-account.yaml | 59 ++++++- .../workloads/metrics-agent.deployment.yaml | 90 ++++++++++ charts/plane-enterprise/values.yaml | 31 ++++ 5 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 charts/plane-enterprise/templates/config-secrets/metrics-config.yaml create mode 100644 charts/plane-enterprise/templates/workloads/metrics-agent.deployment.yaml diff --git a/charts/plane-enterprise/templates/_helpers.tpl b/charts/plane-enterprise/templates/_helpers.tpl index 20af43c9..3429bc16 100644 --- a/charts/plane-enterprise/templates/_helpers.tpl +++ b/charts/plane-enterprise/templates/_helpers.tpl @@ -26,3 +26,11 @@ annotations: {{ toYaml . | nindent 4 }} {{- end }} {{- end }} + +{{- define "plane.metrics.installationUUID" -}} +{{- if .Values.metrics.installation.uuid -}} +{{- .Values.metrics.installation.uuid -}} +{{- else -}} +{{- uuidv4 -}} +{{- end -}} +{{- end -}} diff --git a/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml b/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml new file mode 100644 index 00000000..f45119d6 --- /dev/null +++ b/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml @@ -0,0 +1,163 @@ +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-metrics-config + labels: + app.kubernetes.io/name: plane-enterprise + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: metrics-agent +data: + agent-config.yaml: | + # OpenTelemetry Agent Configuration for Plane Enterprise + # Collects Kubernetes metrics and Plane API metrics + receivers: + # Kubernetes metrics collection + prometheus: + config: + global: + scrape_interval: {{ .Values.metrics.agent.scrape_interval | default "300s" }} + evaluation_interval: {{ .Values.metrics.agent.scrape_interval | default "300s" }} + external_labels: + # Multi-tenant identification + plane_installation_uuid: "{{ include "plane.metrics.installationUUID" . }}" + plane_installation_type: "{{ .Values.metrics.installation.type | default "kubernetes" }}" + plane_version: "{{ .Values.metrics.installation.plane_version | default .Values.planeVersion }}" + cluster_name: "{{ .Values.metrics.installation.cluster_name | default "default" }}" + + scrape_configs: + # cAdvisor metrics (container resource usage for this namespace only) + - job_name: 'kubernetes-cadvisor' + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor + # Filter metrics to only include containers in our namespace + metric_relabel_configs: + - source_labels: [namespace] + action: keep + regex: {{ .Release.Namespace }} + - source_labels: [namespace] + action: drop + regex: ^$ + + # Plane API /metrics endpoint - scrape service + - job_name: 'plane-api' + kubernetes_sd_configs: + - role: service + namespaces: + names: + - {{ .Release.Namespace }} + relabel_configs: + # Only scrape the API service + - source_labels: [__meta_kubernetes_service_name] + action: keep + regex: {{ .Release.Name }}-api + # Set metrics path to /metrics + - target_label: __metrics_path__ + replacement: /metrics + # Set port to 8000 (API service port) + - source_labels: [__address__] + target_label: __address__ + regex: ([^:]+)(?::\d+)? + replacement: $1:8000 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: kubernetes_service_name + + processors: + batch: + timeout: {{ .Values.metrics.agent.batch.timeout | default "60s" }} + send_batch_size: {{ .Values.metrics.agent.batch.send_batch_size | default 4096 }} + + memory_limiter: + limit_mib: {{ regexReplaceAll "Mi|Gi" (.Values.metrics.agent.memoryLimit | default "256Mi") "" | int }} + spike_limit_mib: {{ div (regexReplaceAll "Mi|Gi" (.Values.metrics.agent.memoryLimit | default "256Mi") "") 4 | int }} + check_interval: 0.1s + + # Resource processing to add tenant identification + resource: + attributes: + - key: plane.installation.uuid + value: "{{ include "plane.metrics.installationUUID" . }}" + action: upsert + - key: plane.installation.type + value: "{{ .Values.metrics.installation.type | default "kubernetes" }}" + action: upsert + - key: plane.installation.cluster + value: "{{ .Values.metrics.installation.cluster_name | default "default" }}" + action: upsert + + exporters: + # Export to remote telemetry server + {{- if .Values.metrics.telemetry.http_endpoint }} + {{- $cleanEndpoint := .Values.metrics.telemetry.http_endpoint | trimPrefix "https://" | trimPrefix "http://" | trimSuffix "/v1/traces" | trimSuffix "/v1/metrics" }} + {{- $endpointWithPort := $cleanEndpoint }} + {{- if not (contains ":" $cleanEndpoint) }} + {{- $endpointWithPort = printf "%s:443" $cleanEndpoint }} + {{- end }} + otlp/http: + endpoint: {{ $endpointWithPort }} + compression: gzip + tls: + insecure: true + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s + sending_queue: + enabled: true + num_consumers: 4 + queue_size: 100 + headers: + {{- range $key, $value := .Values.metrics.telemetry.headers }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + + {{- if .Values.metrics.agent.debug.enabled }} + # Debug logging (development only) + logging: + loglevel: debug + sampling_initial: 5 + sampling_thereafter: 200 + {{- end }} + + extensions: + health_check: + endpoint: 0.0.0.0:13133 + + pprof: + endpoint: 0.0.0.0:1777 + + service: + extensions: [health_check, pprof] + pipelines: + metrics: + receivers: [prometheus] + processors: [memory_limiter, resource, batch] + exporters: [ + {{- if .Values.metrics.telemetry.http_endpoint }}otlp/http{{- if .Values.metrics.agent.debug.enabled }},{{- end }}{{- end }} + {{- if .Values.metrics.agent.debug.enabled }}logging{{- end }} + ] +{{- end }} + diff --git a/charts/plane-enterprise/templates/service-account.yaml b/charts/plane-enterprise/templates/service-account.yaml index 6eed2f5f..e75430c1 100644 --- a/charts/plane-enterprise/templates/service-account.yaml +++ b/charts/plane-enterprise/templates/service-account.yaml @@ -7,4 +7,61 @@ metadata: {{- if .Values.dockerRegistry.enabled }} imagePullSecrets: - name: {{ .Release.Name }}-docker-registry-credentials -{{- end}} \ No newline at end of file +{{- end}} + +{{- if .Values.metrics.enabled }} +--- +# ClusterRole for Kubernetes metrics scraping +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Name }}-metrics-reader + labels: + app.kubernetes.io/name: plane-enterprise + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: metrics-agent +rules: +- apiGroups: [""] + resources: + - nodes + - nodes/proxy + - nodes/metrics + - services + - endpoints + - pods + verbs: ["get", "list", "watch"] +- apiGroups: ["apps"] + resources: + - deployments + - replicasets + - daemonsets + - statefulsets + verbs: ["get", "list", "watch"] +- apiGroups: ["extensions"] + resources: + - deployments + - replicasets + - daemonsets + verbs: ["get", "list", "watch"] +- nonResourceURLs: ["/metrics"] + verbs: ["get"] + +--- +# ClusterRoleBinding for metrics collection +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Release.Name }}-metrics-reader + labels: + app.kubernetes.io/name: plane-enterprise + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: metrics-agent +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Release.Name }}-metrics-reader +subjects: +- kind: ServiceAccount + name: {{ .Release.Name }}-srv-account + namespace: {{ .Release.Namespace }} +{{- end }} \ No newline at end of file diff --git a/charts/plane-enterprise/templates/workloads/metrics-agent.deployment.yaml b/charts/plane-enterprise/templates/workloads/metrics-agent.deployment.yaml new file mode 100644 index 00000000..afd5e439 --- /dev/null +++ b/charts/plane-enterprise/templates/workloads/metrics-agent.deployment.yaml @@ -0,0 +1,90 @@ +{{- if .Values.metrics.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-metrics-agent + labels: + app.kubernetes.io/name: plane-enterprise + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: metrics-agent +spec: + replicas: {{ .Values.metrics.agent.replicas | default 1 }} + selector: + matchLabels: + app.kubernetes.io/name: plane-enterprise + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: metrics-agent + template: + metadata: + labels: + app.kubernetes.io/name: plane-enterprise + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: metrics-agent + annotations: + checksum/config: {{ include (print $.Template.BasePath "/config-secrets/metrics-config.yaml") . | sha256sum }} + spec: + serviceAccountName: {{ .Release.Name }}-srv-account + containers: + - name: otel-agent + image: {{ .Values.metrics.agent.image }}:{{ .Values.metrics.agent.tag }} + imagePullPolicy: {{ .Values.metrics.agent.imagePullPolicy | default "IfNotPresent" }} + args: + - --config=/etc/otel-agent/agent-config.yaml + ports: + - name: metrics + containerPort: 8888 + protocol: TCP + - name: health + containerPort: 13133 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: health + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: / + port: health + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 3 + failureThreshold: 3 + resources: + limits: + memory: {{ .Values.metrics.agent.memoryLimit | default "256Mi" }} + cpu: {{ .Values.metrics.agent.cpuLimit | default "100m" }} + requests: + memory: {{ div (regexReplaceAll "Mi|Gi" (.Values.metrics.agent.memoryLimit | default "256Mi") "") 2 | printf "%dMi" }} + cpu: {{ div (regexReplaceAll "m" (.Values.metrics.agent.cpuLimit | default "100m") "") 2 | printf "%dm" }} + volumeMounts: + - name: agent-config + mountPath: /etc/otel-agent + readOnly: true + env: + - name: PLANE_INSTALLATION_UUID + value: {{ include "plane.metrics.installationUUID" . | quote }} + - name: PLANE_INSTALLATION_TYPE + value: {{ .Values.metrics.installation.type | default "kubernetes" | quote }} + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: KUBERNETES_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + volumes: + - name: agent-config + configMap: + name: {{ .Release.Name }}-metrics-config +{{- end }} + diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index 217d2e5a..70bc51e4 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -396,3 +396,34 @@ extraEnv: [] # value: "http://proxy.example.com:8080" # - name: NO_PROXY # value: "localhost,127.0.0.1,.example.com" + +# Metrics collection configuration +metrics: + enabled: true + + # Installation identification + installation: + uuid: "" # Auto-generated if empty + type: "kubernetes" + cluster_name: "default" + plane_version: "" # Optional + + # Telemetry server configuration + telemetry: + http_endpoint: "https://v2.metrics.plane.so/v1/traces" # Full URL (do not include :443) + headers: {} + + # Agent configuration + agent: + image: "otel/opentelemetry-collector-contrib" + tag: "0.110.0" + imagePullPolicy: "IfNotPresent" + replicas: 1 + memoryLimit: "256Mi" + cpuLimit: "100m" + scrape_interval: "300s" # 5 minutes + batch: + timeout: "60s" + send_batch_size: 4096 + debug: + enabled: false From 849aa2d987ab8d73aeb0eff354d51f10f472a57e Mon Sep 17 00:00:00 2001 From: Thomas Taylor Date: Tue, 25 Nov 2025 15:54:59 -0800 Subject: [PATCH 2/9] Update metrics configuration in Plane Enterprise - Increased the batch timeout in values.yaml from 60s to 300s for improved metrics publishing frequency. - Added license domain to metrics-config.yaml to enhance configuration clarity. These changes optimize metrics collection and provide better configuration management for the Plane Enterprise Helm chart. --- .../templates/config-secrets/metrics-config.yaml | 2 ++ charts/plane-enterprise/values.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml b/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml index f45119d6..6f8a901a 100644 --- a/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml +++ b/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml @@ -25,6 +25,7 @@ data: plane_installation_type: "{{ .Values.metrics.installation.type | default "kubernetes" }}" plane_version: "{{ .Values.metrics.installation.plane_version | default .Values.planeVersion }}" cluster_name: "{{ .Values.metrics.installation.cluster_name | default "default" }}" + license_domain: "{{ .Values.license.licenseDomain }}" scrape_configs: # cAdvisor metrics (container resource usage for this namespace only) @@ -118,6 +119,7 @@ data: endpoint: {{ $endpointWithPort }} compression: gzip tls: + # TODO: Add production TLS configuration insecure: true retry_on_failure: enabled: true diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index 70bc51e4..12c6baed 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -423,7 +423,7 @@ metrics: cpuLimit: "100m" scrape_interval: "300s" # 5 minutes batch: - timeout: "60s" + timeout: "300s" # Publish every 5 minutes send_batch_size: 4096 debug: enabled: false From aea4a381b8825d78260e4a02c088489954746fe9 Mon Sep 17 00:00:00 2001 From: Thomas Taylor Date: Mon, 1 Dec 2025 15:38:30 -0800 Subject: [PATCH 3/9] Add optional push interval for metrics telemetry - Introduced a new field `push_interval_minutes` in values.yaml for configuring the telemetry push interval. - Updated app-env.yaml to conditionally set the `METRICS_PUSH_INTERVAL_MINUTES` environment variable based on the new configuration. These changes enhance the flexibility of metrics collection in the Plane Enterprise Helm chart. --- .../plane-enterprise/templates/config-secrets/app-env.yaml | 7 +++++++ charts/plane-enterprise/values.yaml | 1 + 2 files changed, 8 insertions(+) diff --git a/charts/plane-enterprise/templates/config-secrets/app-env.yaml b/charts/plane-enterprise/templates/config-secrets/app-env.yaml index 0d8d1137..dfd04ea6 100644 --- a/charts/plane-enterprise/templates/config-secrets/app-env.yaml +++ b/charts/plane-enterprise/templates/config-secrets/app-env.yaml @@ -78,4 +78,11 @@ data: CORS_ALLOWED_ORIGINS: "http://{{ .Values.license.licenseDomain }},https://{{ .Values.license.licenseDomain }},{{ .Values.env.cors_allowed_origins }}" {{- else}} CORS_ALLOWED_ORIGINS: "http://{{ .Values.license.licenseDomain }},https://{{ .Values.license.licenseDomain }}" + {{- end }} + + {{- if .Values.metrics.enabled }} + OTLP_ENDPOINT: {{ .Values.metrics.telemetry.http_endpoint | default "" | quote }} + {{- if .Values.metrics.telemetry.push_interval_minutes }} + METRICS_PUSH_INTERVAL_MINUTES: {{ .Values.metrics.telemetry.push_interval_minutes | quote }} + {{- end }} {{- end }} \ No newline at end of file diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index 12c6baed..12bb5df0 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -412,6 +412,7 @@ metrics: telemetry: http_endpoint: "https://v2.metrics.plane.so/v1/traces" # Full URL (do not include :443) headers: {} + push_interval_minutes: "" # Optional interval for testing (e.g., "5") # Agent configuration agent: From 2a123d61b59454a1d993e75e3071525c77447776 Mon Sep 17 00:00:00 2001 From: Thomas Taylor Date: Wed, 3 Dec 2025 14:38:28 -0800 Subject: [PATCH 4/9] Remove metrics agent configuration from Plane Enterprise Helm chart - Deleted the metrics agent configuration from values.yaml, including the agent settings and deployment template. - Removed the associated metrics-config.yaml file, which contained the OpenTelemetry agent configuration. These changes streamline the Helm chart by eliminating the metrics agent, simplifying the configuration for users. --- .../config-secrets/metrics-config.yaml | 165 ------------------ .../workloads/metrics-agent.deployment.yaml | 90 ---------- charts/plane-enterprise/values.yaml | 15 -- 3 files changed, 270 deletions(-) delete mode 100644 charts/plane-enterprise/templates/config-secrets/metrics-config.yaml delete mode 100644 charts/plane-enterprise/templates/workloads/metrics-agent.deployment.yaml diff --git a/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml b/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml deleted file mode 100644 index 6f8a901a..00000000 --- a/charts/plane-enterprise/templates/config-secrets/metrics-config.yaml +++ /dev/null @@ -1,165 +0,0 @@ -{{- if .Values.metrics.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ .Release.Namespace }} - name: {{ .Release.Name }}-metrics-config - labels: - app.kubernetes.io/name: plane-enterprise - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/component: metrics-agent -data: - agent-config.yaml: | - # OpenTelemetry Agent Configuration for Plane Enterprise - # Collects Kubernetes metrics and Plane API metrics - receivers: - # Kubernetes metrics collection - prometheus: - config: - global: - scrape_interval: {{ .Values.metrics.agent.scrape_interval | default "300s" }} - evaluation_interval: {{ .Values.metrics.agent.scrape_interval | default "300s" }} - external_labels: - # Multi-tenant identification - plane_installation_uuid: "{{ include "plane.metrics.installationUUID" . }}" - plane_installation_type: "{{ .Values.metrics.installation.type | default "kubernetes" }}" - plane_version: "{{ .Values.metrics.installation.plane_version | default .Values.planeVersion }}" - cluster_name: "{{ .Values.metrics.installation.cluster_name | default "default" }}" - license_domain: "{{ .Values.license.licenseDomain }}" - - scrape_configs: - # cAdvisor metrics (container resource usage for this namespace only) - - job_name: 'kubernetes-cadvisor' - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - insecure_skip_verify: true - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - kubernetes_sd_configs: - - role: node - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor - # Filter metrics to only include containers in our namespace - metric_relabel_configs: - - source_labels: [namespace] - action: keep - regex: {{ .Release.Namespace }} - - source_labels: [namespace] - action: drop - regex: ^$ - - # Plane API /metrics endpoint - scrape service - - job_name: 'plane-api' - kubernetes_sd_configs: - - role: service - namespaces: - names: - - {{ .Release.Namespace }} - relabel_configs: - # Only scrape the API service - - source_labels: [__meta_kubernetes_service_name] - action: keep - regex: {{ .Release.Name }}-api - # Set metrics path to /metrics - - target_label: __metrics_path__ - replacement: /metrics - # Set port to 8000 (API service port) - - source_labels: [__address__] - target_label: __address__ - regex: ([^:]+)(?::\d+)? - replacement: $1:8000 - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_service_name] - action: replace - target_label: kubernetes_service_name - - processors: - batch: - timeout: {{ .Values.metrics.agent.batch.timeout | default "60s" }} - send_batch_size: {{ .Values.metrics.agent.batch.send_batch_size | default 4096 }} - - memory_limiter: - limit_mib: {{ regexReplaceAll "Mi|Gi" (.Values.metrics.agent.memoryLimit | default "256Mi") "" | int }} - spike_limit_mib: {{ div (regexReplaceAll "Mi|Gi" (.Values.metrics.agent.memoryLimit | default "256Mi") "") 4 | int }} - check_interval: 0.1s - - # Resource processing to add tenant identification - resource: - attributes: - - key: plane.installation.uuid - value: "{{ include "plane.metrics.installationUUID" . }}" - action: upsert - - key: plane.installation.type - value: "{{ .Values.metrics.installation.type | default "kubernetes" }}" - action: upsert - - key: plane.installation.cluster - value: "{{ .Values.metrics.installation.cluster_name | default "default" }}" - action: upsert - - exporters: - # Export to remote telemetry server - {{- if .Values.metrics.telemetry.http_endpoint }} - {{- $cleanEndpoint := .Values.metrics.telemetry.http_endpoint | trimPrefix "https://" | trimPrefix "http://" | trimSuffix "/v1/traces" | trimSuffix "/v1/metrics" }} - {{- $endpointWithPort := $cleanEndpoint }} - {{- if not (contains ":" $cleanEndpoint) }} - {{- $endpointWithPort = printf "%s:443" $cleanEndpoint }} - {{- end }} - otlp/http: - endpoint: {{ $endpointWithPort }} - compression: gzip - tls: - # TODO: Add production TLS configuration - insecure: true - retry_on_failure: - enabled: true - initial_interval: 5s - max_interval: 30s - max_elapsed_time: 300s - sending_queue: - enabled: true - num_consumers: 4 - queue_size: 100 - headers: - {{- range $key, $value := .Values.metrics.telemetry.headers }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- end }} - - {{- if .Values.metrics.agent.debug.enabled }} - # Debug logging (development only) - logging: - loglevel: debug - sampling_initial: 5 - sampling_thereafter: 200 - {{- end }} - - extensions: - health_check: - endpoint: 0.0.0.0:13133 - - pprof: - endpoint: 0.0.0.0:1777 - - service: - extensions: [health_check, pprof] - pipelines: - metrics: - receivers: [prometheus] - processors: [memory_limiter, resource, batch] - exporters: [ - {{- if .Values.metrics.telemetry.http_endpoint }}otlp/http{{- if .Values.metrics.agent.debug.enabled }},{{- end }}{{- end }} - {{- if .Values.metrics.agent.debug.enabled }}logging{{- end }} - ] -{{- end }} - diff --git a/charts/plane-enterprise/templates/workloads/metrics-agent.deployment.yaml b/charts/plane-enterprise/templates/workloads/metrics-agent.deployment.yaml deleted file mode 100644 index afd5e439..00000000 --- a/charts/plane-enterprise/templates/workloads/metrics-agent.deployment.yaml +++ /dev/null @@ -1,90 +0,0 @@ -{{- if .Values.metrics.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - namespace: {{ .Release.Namespace }} - name: {{ .Release.Name }}-metrics-agent - labels: - app.kubernetes.io/name: plane-enterprise - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/component: metrics-agent -spec: - replicas: {{ .Values.metrics.agent.replicas | default 1 }} - selector: - matchLabels: - app.kubernetes.io/name: plane-enterprise - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/component: metrics-agent - template: - metadata: - labels: - app.kubernetes.io/name: plane-enterprise - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/component: metrics-agent - annotations: - checksum/config: {{ include (print $.Template.BasePath "/config-secrets/metrics-config.yaml") . | sha256sum }} - spec: - serviceAccountName: {{ .Release.Name }}-srv-account - containers: - - name: otel-agent - image: {{ .Values.metrics.agent.image }}:{{ .Values.metrics.agent.tag }} - imagePullPolicy: {{ .Values.metrics.agent.imagePullPolicy | default "IfNotPresent" }} - args: - - --config=/etc/otel-agent/agent-config.yaml - ports: - - name: metrics - containerPort: 8888 - protocol: TCP - - name: health - containerPort: 13133 - protocol: TCP - livenessProbe: - httpGet: - path: / - port: health - initialDelaySeconds: 30 - periodSeconds: 30 - timeoutSeconds: 5 - failureThreshold: 5 - readinessProbe: - httpGet: - path: / - port: health - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 3 - failureThreshold: 3 - resources: - limits: - memory: {{ .Values.metrics.agent.memoryLimit | default "256Mi" }} - cpu: {{ .Values.metrics.agent.cpuLimit | default "100m" }} - requests: - memory: {{ div (regexReplaceAll "Mi|Gi" (.Values.metrics.agent.memoryLimit | default "256Mi") "") 2 | printf "%dMi" }} - cpu: {{ div (regexReplaceAll "m" (.Values.metrics.agent.cpuLimit | default "100m") "") 2 | printf "%dm" }} - volumeMounts: - - name: agent-config - mountPath: /etc/otel-agent - readOnly: true - env: - - name: PLANE_INSTALLATION_UUID - value: {{ include "plane.metrics.installationUUID" . | quote }} - - name: PLANE_INSTALLATION_TYPE - value: {{ .Values.metrics.installation.type | default "kubernetes" | quote }} - - name: KUBERNETES_NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - - name: KUBERNETES_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KUBERNETES_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - volumes: - - name: agent-config - configMap: - name: {{ .Release.Name }}-metrics-config -{{- end }} - diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index 12bb5df0..2471e7c2 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -413,18 +413,3 @@ metrics: http_endpoint: "https://v2.metrics.plane.so/v1/traces" # Full URL (do not include :443) headers: {} push_interval_minutes: "" # Optional interval for testing (e.g., "5") - - # Agent configuration - agent: - image: "otel/opentelemetry-collector-contrib" - tag: "0.110.0" - imagePullPolicy: "IfNotPresent" - replicas: 1 - memoryLimit: "256Mi" - cpuLimit: "100m" - scrape_interval: "300s" # 5 minutes - batch: - timeout: "300s" # Publish every 5 minutes - send_batch_size: 4096 - debug: - enabled: false From 3f9f03e68f753a3369377036cead69dd6ed7b6c7 Mon Sep 17 00:00:00 2001 From: Thomas Taylor Date: Thu, 4 Dec 2025 11:06:06 -0800 Subject: [PATCH 5/9] Add OTLP exporter protocol to app-env.yaml - Introduced the `OTEL_EXPORTER_OTLP_PROTOCOL` environment variable with a default value of "http/protobuf" to enhance OpenTelemetry configuration for metrics telemetry. This change improves the flexibility and compatibility of metrics collection in the Plane Enterprise Helm chart. --- charts/plane-enterprise/templates/config-secrets/app-env.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/plane-enterprise/templates/config-secrets/app-env.yaml b/charts/plane-enterprise/templates/config-secrets/app-env.yaml index dfd04ea6..385d2b25 100644 --- a/charts/plane-enterprise/templates/config-secrets/app-env.yaml +++ b/charts/plane-enterprise/templates/config-secrets/app-env.yaml @@ -82,6 +82,7 @@ data: {{- if .Values.metrics.enabled }} OTLP_ENDPOINT: {{ .Values.metrics.telemetry.http_endpoint | default "" | quote }} + OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf" {{- if .Values.metrics.telemetry.push_interval_minutes }} METRICS_PUSH_INTERVAL_MINUTES: {{ .Values.metrics.telemetry.push_interval_minutes | quote }} {{- end }} From daf6bec9a2abfe16a117f99ad4837da5168b3b85 Mon Sep 17 00:00:00 2001 From: Thomas Taylor Date: Tue, 9 Dec 2025 21:40:25 -0800 Subject: [PATCH 6/9] Enhance installation UUID handling in Plane Enterprise Helm chart - Updated values.yaml to provide detailed comments on the installation UUID configuration for better clarity on its usage and persistence. - Improved the installation UUID generation logic in _helpers.tpl to ensure consistent UUIDs across Helm renders and provide fallback mechanisms. - Introduced a new Secret template (installation-uuid.yaml) to store the installation UUID, ensuring it persists across upgrades and can be referenced securely in workloads. These changes enhance the telemetry correlation capabilities and improve the overall user experience when configuring metrics in the Plane Enterprise Helm chart. --- .../plane-enterprise/templates/_helpers.tpl | 33 ++++++++++++++++++- .../config-secrets/installation-uuid.yaml | 32 ++++++++++++++++++ charts/plane-enterprise/values.yaml | 6 +++- 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 charts/plane-enterprise/templates/config-secrets/installation-uuid.yaml diff --git a/charts/plane-enterprise/templates/_helpers.tpl b/charts/plane-enterprise/templates/_helpers.tpl index 3429bc16..e656d346 100644 --- a/charts/plane-enterprise/templates/_helpers.tpl +++ b/charts/plane-enterprise/templates/_helpers.tpl @@ -27,10 +27,41 @@ {{- end }} {{- end }} +{{/* +plane.metrics.installationUUID returns a stable installation UUID. +This template ensures the same UUID is used across ALL template invocations +within a single Helm render by caching the value. + +Priority: + 1. Explicitly provided .Values.metrics.installation.uuid + 2. Existing UUID from the installation-uuid Secret (survives upgrades) + 3. Newly generated UUID (cached for this render, stored in Secret for persistence) + +IMPORTANT: Workloads should prefer using secretKeyRef to read from the +{{ .Release.Name }}-installation-uuid Secret for environment variables. +This template is for use in ConfigMaps and other non-secret resources. +*/}} {{- define "plane.metrics.installationUUID" -}} {{- if .Values.metrics.installation.uuid -}} {{- .Values.metrics.installation.uuid -}} {{- else -}} -{{- uuidv4 -}} +{{- $secretName := printf "%s-installation-uuid" .Release.Name -}} +{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace $secretName -}} +{{- if and $existingSecret $existingSecret.data (index $existingSecret.data "uuid") -}} +{{- index $existingSecret.data "uuid" | b64dec -}} +{{- else -}} +{{- /* Fresh install: generate deterministic UUID from release info */ -}} +{{- /* This ensures consistency across all template invocations */ -}} +{{- $hash := printf "%s-%s-%s" .Release.Name .Release.Namespace .Chart.Name | sha256sum | trunc 32 -}} +{{- printf "%s-%s-%s-%s-%s" (substr 0 8 $hash) (substr 8 12 $hash) (substr 12 16 $hash) (substr 16 20 $hash) (substr 20 32 $hash) -}} {{- end -}} {{- end -}} +{{- end -}} + +{{/* +plane.metrics.installationUUIDSecretName returns the name of the Secret +containing the installation UUID. Use this for secretKeyRef in pod specs. +*/}} +{{- define "plane.metrics.installationUUIDSecretName" -}} +{{- printf "%s-installation-uuid" .Release.Name -}} +{{- end -}} diff --git a/charts/plane-enterprise/templates/config-secrets/installation-uuid.yaml b/charts/plane-enterprise/templates/config-secrets/installation-uuid.yaml new file mode 100644 index 00000000..5af8ddf8 --- /dev/null +++ b/charts/plane-enterprise/templates/config-secrets/installation-uuid.yaml @@ -0,0 +1,32 @@ +{{- if .Values.metrics.enabled -}} +{{/* +This Secret stores the installation UUID for metrics/telemetry correlation. +The UUID is either: + - Explicitly provided via .Values.metrics.installation.uuid + - Retrieved from an existing Secret (persisted across upgrades) + - Generated deterministically from release info (for fresh installs) + +The deterministic generation ensures the UUID is consistent across all +template invocations within a single Helm render, while the Secret persists +the value across upgrades. + +Workloads should use secretKeyRef to reference this Secret's "uuid" key +for environment variables like PLANE_INSTALLATION_UUID. +*/}} +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-installation-uuid + labels: + app.kubernetes.io/name: plane-enterprise + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: metrics + annotations: + # Preserve the UUID across helm uninstall/install cycles if desired + # Remove this annotation if you want a new UUID on reinstall + "helm.sh/resource-policy": keep +data: + uuid: {{ include "plane.metrics.installationUUID" . | b64enc | quote }} +{{- end -}} diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index 2471e7c2..28369147 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -403,7 +403,11 @@ metrics: # Installation identification installation: - uuid: "" # Auto-generated if empty + # Unique identifier for this Plane installation. Used for telemetry correlation. + # If empty: A deterministic UUID is generated from the release name/namespace + # and persisted in a Secret. This UUID remains stable across helm upgrades. + # If provided: Your specified UUID is used (recommended for production). + uuid: "" type: "kubernetes" cluster_name: "default" plane_version: "" # Optional From 5a3ce81f0d5dc371539fc60eff6cb80199f95537 Mon Sep 17 00:00:00 2001 From: Thomas Taylor Date: Wed, 10 Dec 2025 17:09:52 -0800 Subject: [PATCH 7/9] Update telemetry endpoints and enhance secret management in Plane Enterprise Helm chart - Modified values.yaml to update the primary telemetry endpoint and add a new v2 telemetry endpoint for improved metrics collection. - Updated app-env.yaml to include the new OTLP v2 endpoint for better OpenTelemetry configuration. - Adjusted silo.yaml to decode the HMAC secret key from base64, ensuring proper handling of sensitive data. These changes enhance the telemetry capabilities and improve the security of secret management in the Plane Enterprise Helm chart. --- .../plane-enterprise/templates/config-secrets/app-env.yaml | 1 + charts/plane-enterprise/templates/config-secrets/silo.yaml | 2 +- charts/plane-enterprise/values.yaml | 5 ++++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/charts/plane-enterprise/templates/config-secrets/app-env.yaml b/charts/plane-enterprise/templates/config-secrets/app-env.yaml index 385d2b25..7e23f379 100644 --- a/charts/plane-enterprise/templates/config-secrets/app-env.yaml +++ b/charts/plane-enterprise/templates/config-secrets/app-env.yaml @@ -82,6 +82,7 @@ data: {{- if .Values.metrics.enabled }} OTLP_ENDPOINT: {{ .Values.metrics.telemetry.http_endpoint | default "" | quote }} + OTLP_V2_ENDPOINT: {{ .Values.metrics.telemetry.http_v2_endpoint | default "" | quote }} OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf" {{- if .Values.metrics.telemetry.push_interval_minutes }} METRICS_PUSH_INTERVAL_MINUTES: {{ .Values.metrics.telemetry.push_interval_minutes | quote }} diff --git a/charts/plane-enterprise/templates/config-secrets/silo.yaml b/charts/plane-enterprise/templates/config-secrets/silo.yaml index 1f3bc132..a379608c 100644 --- a/charts/plane-enterprise/templates/config-secrets/silo.yaml +++ b/charts/plane-enterprise/templates/config-secrets/silo.yaml @@ -10,7 +10,7 @@ stringData: {{- if .Values.env.silo_envs.hmac_secret_key }} SILO_HMAC_SECRET_KEY: {{ .Values.env.silo_envs.hmac_secret_key | quote }} {{- else if (lookup "v1" "Secret" .Release.Namespace (printf "%s-silo-secrets" .Release.Name)) }} - SILO_HMAC_SECRET_KEY: {{ (lookup "v1" "Secret" .Release.Namespace (printf "%s-silo-secrets" .Release.Name)).data.SILO_HMAC_SECRET_KEY | default (randAlphaNum 32) | quote }} + SILO_HMAC_SECRET_KEY: {{ (lookup "v1" "Secret" .Release.Namespace (printf "%s-silo-secrets" .Release.Name)).data.SILO_HMAC_SECRET_KEY | b64dec | default (randAlphaNum 32) | quote }} {{- else }} SILO_HMAC_SECRET_KEY: {{ randAlphaNum 32 | quote }} {{- end }} diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index 28369147..b66e0966 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -414,6 +414,9 @@ metrics: # Telemetry server configuration telemetry: - http_endpoint: "https://v2.metrics.plane.so/v1/traces" # Full URL (do not include :443) + # Primary telemetry endpoint (OTLP HTTP) + http_endpoint: "https://telemetry.plane.so" + # V2 telemetry endpoint for enhanced metrics (OTLP HTTP) + http_v2_endpoint: "https://v2.telemetry.plane.so" headers: {} push_interval_minutes: "" # Optional interval for testing (e.g., "5") From 8c6a995383e622a06424da465765d4b0840f7f4a Mon Sep 17 00:00:00 2001 From: Thomas Taylor Date: Wed, 10 Dec 2025 18:12:54 -0800 Subject: [PATCH 8/9] Refactor installation UUID handling in Plane Enterprise Helm chart - Removed the installation UUID configuration from values.yaml and associated comments for clarity. - Deleted the installation-uuid Secret template to streamline the Helm chart and eliminate unnecessary complexity. - Updated the _helpers.tpl file to remove the installation UUID generation logic, simplifying the template structure. These changes enhance the overall maintainability of the Plane Enterprise Helm chart by reducing redundancy in UUID management. --- .../plane-enterprise/templates/_helpers.tpl | 39 ------------------- .../config-secrets/installation-uuid.yaml | 32 --------------- charts/plane-enterprise/values.yaml | 11 ------ 3 files changed, 82 deletions(-) delete mode 100644 charts/plane-enterprise/templates/config-secrets/installation-uuid.yaml diff --git a/charts/plane-enterprise/templates/_helpers.tpl b/charts/plane-enterprise/templates/_helpers.tpl index e656d346..20af43c9 100644 --- a/charts/plane-enterprise/templates/_helpers.tpl +++ b/charts/plane-enterprise/templates/_helpers.tpl @@ -26,42 +26,3 @@ annotations: {{ toYaml . | nindent 4 }} {{- end }} {{- end }} - -{{/* -plane.metrics.installationUUID returns a stable installation UUID. -This template ensures the same UUID is used across ALL template invocations -within a single Helm render by caching the value. - -Priority: - 1. Explicitly provided .Values.metrics.installation.uuid - 2. Existing UUID from the installation-uuid Secret (survives upgrades) - 3. Newly generated UUID (cached for this render, stored in Secret for persistence) - -IMPORTANT: Workloads should prefer using secretKeyRef to read from the -{{ .Release.Name }}-installation-uuid Secret for environment variables. -This template is for use in ConfigMaps and other non-secret resources. -*/}} -{{- define "plane.metrics.installationUUID" -}} -{{- if .Values.metrics.installation.uuid -}} -{{- .Values.metrics.installation.uuid -}} -{{- else -}} -{{- $secretName := printf "%s-installation-uuid" .Release.Name -}} -{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace $secretName -}} -{{- if and $existingSecret $existingSecret.data (index $existingSecret.data "uuid") -}} -{{- index $existingSecret.data "uuid" | b64dec -}} -{{- else -}} -{{- /* Fresh install: generate deterministic UUID from release info */ -}} -{{- /* This ensures consistency across all template invocations */ -}} -{{- $hash := printf "%s-%s-%s" .Release.Name .Release.Namespace .Chart.Name | sha256sum | trunc 32 -}} -{{- printf "%s-%s-%s-%s-%s" (substr 0 8 $hash) (substr 8 12 $hash) (substr 12 16 $hash) (substr 16 20 $hash) (substr 20 32 $hash) -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -plane.metrics.installationUUIDSecretName returns the name of the Secret -containing the installation UUID. Use this for secretKeyRef in pod specs. -*/}} -{{- define "plane.metrics.installationUUIDSecretName" -}} -{{- printf "%s-installation-uuid" .Release.Name -}} -{{- end -}} diff --git a/charts/plane-enterprise/templates/config-secrets/installation-uuid.yaml b/charts/plane-enterprise/templates/config-secrets/installation-uuid.yaml deleted file mode 100644 index 5af8ddf8..00000000 --- a/charts/plane-enterprise/templates/config-secrets/installation-uuid.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.metrics.enabled -}} -{{/* -This Secret stores the installation UUID for metrics/telemetry correlation. -The UUID is either: - - Explicitly provided via .Values.metrics.installation.uuid - - Retrieved from an existing Secret (persisted across upgrades) - - Generated deterministically from release info (for fresh installs) - -The deterministic generation ensures the UUID is consistent across all -template invocations within a single Helm render, while the Secret persists -the value across upgrades. - -Workloads should use secretKeyRef to reference this Secret's "uuid" key -for environment variables like PLANE_INSTALLATION_UUID. -*/}} -apiVersion: v1 -kind: Secret -type: Opaque -metadata: - namespace: {{ .Release.Namespace }} - name: {{ .Release.Name }}-installation-uuid - labels: - app.kubernetes.io/name: plane-enterprise - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/component: metrics - annotations: - # Preserve the UUID across helm uninstall/install cycles if desired - # Remove this annotation if you want a new UUID on reinstall - "helm.sh/resource-policy": keep -data: - uuid: {{ include "plane.metrics.installationUUID" . | b64enc | quote }} -{{- end -}} diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index b66e0966..a27766e7 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -401,17 +401,6 @@ extraEnv: [] metrics: enabled: true - # Installation identification - installation: - # Unique identifier for this Plane installation. Used for telemetry correlation. - # If empty: A deterministic UUID is generated from the release name/namespace - # and persisted in a Secret. This UUID remains stable across helm upgrades. - # If provided: Your specified UUID is used (recommended for production). - uuid: "" - type: "kubernetes" - cluster_name: "default" - plane_version: "" # Optional - # Telemetry server configuration telemetry: # Primary telemetry endpoint (OTLP HTTP) From f7d0e345531505de3a99cd38e9ad614ea4e6912f Mon Sep 17 00:00:00 2001 From: Thomas Taylor Date: Wed, 10 Dec 2025 19:22:19 -0800 Subject: [PATCH 9/9] Update telemetry endpoint paths in values.yaml and remove metrics-related ClusterRole and ClusterRoleBinding from service-account.yaml - Modified values.yaml to include the full path for telemetry endpoints, ensuring proper configuration for OTLP exporters. - Removed the ClusterRole and ClusterRoleBinding definitions related to metrics scraping from service-account.yaml to streamline the Helm chart. These changes enhance the clarity of telemetry configurations and simplify the service account setup in the Plane Enterprise Helm chart. --- charts/plane-enterprise/README.md | 17 ++++++ .../templates/service-account.yaml | 59 +------------------ charts/plane-enterprise/values.yaml | 6 +- 3 files changed, 22 insertions(+), 60 deletions(-) diff --git a/charts/plane-enterprise/README.md b/charts/plane-enterprise/README.md index 1aecb6eb..c229bfa5 100644 --- a/charts/plane-enterprise/README.md +++ b/charts/plane-enterprise/README.md @@ -489,6 +489,23 @@ Note: When the email service is enabled, the cert-issuer will be automatically c | env.storageClass | <k8s-default-storage-class> | | Creating the persitant volumes for the stateful deployments needs the `storageClass` name. Set the correct value as per your kubernetes cluster configuration. | | env.secret_key | 60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5 | Yes | This must a random string which is used for hashing/encrypting the sensitive data within the application. Once set, changing this might impact the already hashed/encrypted data | +### Metrics and Telemetry Configuration + +| Setting | Default | Required | Description | +| ---------------------------------------- | :---------------------------------------------------: | :------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| metrics.enabled | true | No | Enable or disable metrics collection and telemetry. Set to `false` to completely disable all metrics functionality. | +| metrics.telemetry.http_endpoint | https://telemetry.plane.so/v1/metrics | No | Primary OTLP HTTP endpoint for metrics export. Must include the full path `/v1/metrics` for the OTLP exporter to work correctly. This is used for backward compatibility with v1 telemetry. | +| metrics.telemetry.http_v2_endpoint | https://v2.telemetry.plane.so/v1/metrics | No | V2 OTLP HTTP endpoint for enhanced metrics collection. Must include the full path `/v1/metrics`. The API service uses this endpoint to push instance and workspace-level metrics via the OpenTelemetry Protocol. | +| metrics.telemetry.push_interval_minutes | "" | No | Optional interval (in minutes) for pushing metrics. Leave empty for default behavior (every 6 hours). Set to a value like `1` or `5` for testing/development to push metrics more frequently. Only applicable when metrics.enabled is `true`. | +| metrics.telemetry.headers | {} | No | Optional custom headers to include with telemetry requests. Useful for authentication or routing purposes when using custom telemetry backends. | + +**Notes:** +- Metrics are collected by the API service and pushed to the configured OTLP endpoint using the OpenTelemetry Protocol over HTTP +- The endpoint URLs must include the full path `/v1/metrics` - the OTLP exporter will not automatically append this path +- Metrics include instance-level data (users, workspaces, projects, issues) and workspace-level data +- When `metrics.enabled=false`, no metrics collection or export will occur +- For self-hosted deployments pointing to your own telemetry infrastructure, update the endpoint URLs accordingly + ### Extra Environment Variables | Setting | Default | Required | Description | diff --git a/charts/plane-enterprise/templates/service-account.yaml b/charts/plane-enterprise/templates/service-account.yaml index e75430c1..6eed2f5f 100644 --- a/charts/plane-enterprise/templates/service-account.yaml +++ b/charts/plane-enterprise/templates/service-account.yaml @@ -7,61 +7,4 @@ metadata: {{- if .Values.dockerRegistry.enabled }} imagePullSecrets: - name: {{ .Release.Name }}-docker-registry-credentials -{{- end}} - -{{- if .Values.metrics.enabled }} ---- -# ClusterRole for Kubernetes metrics scraping -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ .Release.Name }}-metrics-reader - labels: - app.kubernetes.io/name: plane-enterprise - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/component: metrics-agent -rules: -- apiGroups: [""] - resources: - - nodes - - nodes/proxy - - nodes/metrics - - services - - endpoints - - pods - verbs: ["get", "list", "watch"] -- apiGroups: ["apps"] - resources: - - deployments - - replicasets - - daemonsets - - statefulsets - verbs: ["get", "list", "watch"] -- apiGroups: ["extensions"] - resources: - - deployments - - replicasets - - daemonsets - verbs: ["get", "list", "watch"] -- nonResourceURLs: ["/metrics"] - verbs: ["get"] - ---- -# ClusterRoleBinding for metrics collection -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ .Release.Name }}-metrics-reader - labels: - app.kubernetes.io/name: plane-enterprise - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/component: metrics-agent -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ .Release.Name }}-metrics-reader -subjects: -- kind: ServiceAccount - name: {{ .Release.Name }}-srv-account - namespace: {{ .Release.Namespace }} -{{- end }} \ No newline at end of file +{{- end}} \ No newline at end of file diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index a27766e7..4879a8c8 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -404,8 +404,10 @@ metrics: # Telemetry server configuration telemetry: # Primary telemetry endpoint (OTLP HTTP) - http_endpoint: "https://telemetry.plane.so" + # Note: Must include full path /v1/metrics for OTLP exporter + http_endpoint: "https://telemetry.plane.so/v1/metrics" # V2 telemetry endpoint for enhanced metrics (OTLP HTTP) - http_v2_endpoint: "https://v2.telemetry.plane.so" + # Note: Must include full path /v1/metrics for OTLP exporter + http_v2_endpoint: "https://v2.telemetry.plane.so/v1/metrics" headers: {} push_interval_minutes: "" # Optional interval for testing (e.g., "5")