-
Notifications
You must be signed in to change notification settings - Fork 29
feat(plane-enterprise): native OpenTelemetry APM support (v2.5.1) #241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
98f5eb3
630c57c
9962e17
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -242,3 +242,61 @@ Caller must nindent to the correct depth. | |||||||||||||||||||||||
| value: "/ca-bundle/custom-ca-bundle.crt" | ||||||||||||||||||||||||
| {{- end }} | ||||||||||||||||||||||||
| {{- end -}} | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| {{/* | ||||||||||||||||||||||||
| OpenTelemetry inline env vars for a single workload. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| The Django backend (api, worker, beat-worker, automation-consumer, outbox-poller, | ||||||||||||||||||||||||
| migrator) already sources the shared OTEL_* config from the app-vars ConfigMap | ||||||||||||||||||||||||
| (see config-secrets/app-env.yaml). This helper renders those same keys INLINE so | ||||||||||||||||||||||||
| that services which do NOT consume app-vars — the Node services (silo, live), the | ||||||||||||||||||||||||
| SSR frontend (space) and Plane Intelligence (pi-api, pi-worker, pi-beat) — get | ||||||||||||||||||||||||
| full OTel coverage, and so every workload can report its own OTEL_SERVICE_NAME | ||||||||||||||||||||||||
| (inline env wins over envFrom). Kept in sync with the OTEL block in app-env.yaml. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Call with a dict carrying the root context and the per-service name: | ||||||||||||||||||||||||
| {{- include "plane.otelServiceEnv" (dict "context" $ "service" "silo") }} | ||||||||||||||||||||||||
| Pass "full" false to emit ONLY the OTEL_SERVICE_NAME override — used by Django | ||||||||||||||||||||||||
| workloads that already get the rest of the OTEL_* keys from app-vars. | ||||||||||||||||||||||||
| Caller must indent to the correct depth (matches the s3CA*EnvVars pattern). | ||||||||||||||||||||||||
| */}} | ||||||||||||||||||||||||
| {{- define "plane.otelServiceEnv" -}} | ||||||||||||||||||||||||
| {{- $ctx := .context -}} | ||||||||||||||||||||||||
| {{- $otel := $ctx.Values.observability.otel -}} | ||||||||||||||||||||||||
| {{- if $otel.enabled -}} | ||||||||||||||||||||||||
| - name: OTEL_SERVICE_NAME | ||||||||||||||||||||||||
| value: {{ .service | quote }} | ||||||||||||||||||||||||
| {{- if not (eq .full false) }} | ||||||||||||||||||||||||
| - name: OTEL_ENABLED | ||||||||||||||||||||||||
| value: "1" | ||||||||||||||||||||||||
| {{- if $otel.endpoint }} | ||||||||||||||||||||||||
| - name: OTEL_EXPORTER_OTLP_ENDPOINT | ||||||||||||||||||||||||
| value: {{ $otel.endpoint | quote }} | ||||||||||||||||||||||||
| {{- else if $otel.collector.enabled }} | ||||||||||||||||||||||||
| - name: OTEL_EXPORTER_OTLP_ENDPOINT | ||||||||||||||||||||||||
| value: "http://{{ $ctx.Release.Name }}-otel-collector.{{ $ctx.Release.Namespace }}.svc.{{ $ctx.Values.env.default_cluster_domain | default "cluster.local" }}:{{ eq ($otel.protocol | default "grpc") "grpc" | ternary "4317" "4318" }}" | ||||||||||||||||||||||||
| {{- else }} | ||||||||||||||||||||||||
| - name: OTEL_EXPORTER_OTLP_ENDPOINT | ||||||||||||||||||||||||
| value: "" | ||||||||||||||||||||||||
| {{- end }} | ||||||||||||||||||||||||
| - name: OTEL_EXPORTER_OTLP_PROTOCOL | ||||||||||||||||||||||||
| value: {{ $otel.protocol | default "grpc" | quote }} | ||||||||||||||||||||||||
| - name: OTEL_TRACES_SAMPLER | ||||||||||||||||||||||||
| value: {{ $otel.tracesSampler | default "parentbased_traceidratio" | quote }} | ||||||||||||||||||||||||
| - name: OTEL_TRACES_SAMPLER_ARG | ||||||||||||||||||||||||
| value: {{ $otel.tracesSamplerArg | default "0.1" | quote }} | ||||||||||||||||||||||||
| {{- if $otel.resourceAttributes }} | ||||||||||||||||||||||||
| - name: OTEL_RESOURCE_ATTRIBUTES | ||||||||||||||||||||||||
| value: {{ $otel.resourceAttributes | quote }} | ||||||||||||||||||||||||
| {{- end }} | ||||||||||||||||||||||||
| {{- if $otel.debugConsole }} | ||||||||||||||||||||||||
| - name: OTEL_DEBUG_CONSOLE | ||||||||||||||||||||||||
| value: "1" | ||||||||||||||||||||||||
| {{- end }} | ||||||||||||||||||||||||
| {{- if $otel.headers }} | ||||||||||||||||||||||||
| - name: OTEL_EXPORTER_OTLP_HEADERS | ||||||||||||||||||||||||
| value: {{ $otel.headers | quote }} | ||||||||||||||||||||||||
| {{- end }} | ||||||||||||||||||||||||
|
Comment on lines
+296
to
+299
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win OTLP auth headers embedded in plaintext in Deployment manifests for non-Django workloads. For callers using Consider sourcing this value from a Secret (create/reuse an otel-headers Secret and reference it via 💡 Sketch of an alternative using a Secret reference {{- if $otel.headers }}
- name: OTEL_EXPORTER_OTLP_HEADERS
- value: {{ $otel.headers | quote }}
+ valueFrom:
+ secretKeyRef:
+ name: {{ $ctx.Release.Name }}-otel-secrets
+ key: OTEL_EXPORTER_OTLP_HEADERS
{{- end }}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| {{- end }} | ||||||||||||||||||||||||
| {{- end }} | ||||||||||||||||||||||||
| {{- end -}} | ||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| {{- /* | ||
| Bundled OpenTelemetry Collector. Rendered only when OTEL is enabled AND the | ||
| bundled collector is requested. Self-hosters pointing at an external collector | ||
| (Datadog Agent, Grafana Cloud, an existing cluster collector) leave | ||
| observability.otel.collector.enabled=false and these resources are omitted. | ||
|
|
||
| When enabled with an empty observability.otel.endpoint, the backend auto-targets | ||
| this collector's in-cluster Service (see config-secrets/app-env.yaml). | ||
| */}} | ||
| {{- if and .Values.observability.otel.enabled .Values.observability.otel.collector.enabled }} | ||
| apiVersion: v1 | ||
| kind: ConfigMap | ||
| metadata: | ||
| namespace: {{ .Release.Namespace }} | ||
| name: {{ .Release.Name }}-otel-collector-config | ||
| labels: | ||
| app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-otel-collector | ||
| data: | ||
| config.yaml: | | ||
| {{- if .Values.observability.otel.collector.config }} | ||
| {{ .Values.observability.otel.collector.config | indent 4 }} | ||
| {{- else }} | ||
| # Default pipeline: receive OTLP, log via `debug`. Override the whole config | ||
| # with observability.otel.collector.config to export to a real backend. | ||
| receivers: | ||
| otlp: | ||
| protocols: | ||
| grpc: | ||
| endpoint: 0.0.0.0:4317 | ||
| http: | ||
| endpoint: 0.0.0.0:4318 | ||
| processors: | ||
| batch: | ||
| timeout: 10s | ||
| send_batch_size: 1024 | ||
| exporters: | ||
| debug: | ||
| verbosity: detailed | ||
| service: | ||
| pipelines: | ||
| traces: | ||
| receivers: [otlp] | ||
| processors: [batch] | ||
| exporters: [debug] | ||
| metrics: | ||
| receivers: [otlp] | ||
| processors: [batch] | ||
| exporters: [debug] | ||
| {{- end }} | ||
|
|
||
| --- | ||
|
|
||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| namespace: {{ .Release.Namespace }} | ||
| name: {{ .Release.Name }}-otel-collector | ||
| labels: | ||
| app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-otel-collector | ||
| spec: | ||
| type: ClusterIP | ||
| ports: | ||
| - name: otlp-grpc | ||
| port: 4317 | ||
| protocol: TCP | ||
| targetPort: 4317 | ||
| - name: otlp-http | ||
| port: 4318 | ||
| protocol: TCP | ||
| targetPort: 4318 | ||
| selector: | ||
| app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-otel-collector | ||
|
|
||
| --- | ||
|
|
||
| apiVersion: apps/v1 | ||
| kind: Deployment | ||
| metadata: | ||
| namespace: {{ .Release.Namespace }} | ||
| name: {{ .Release.Name }}-otel-collector | ||
| {{- include "plane.labelsAndAnnotations" (dict "context" $ "values" .Values.observability.otel.collector) }} | ||
| spec: | ||
| replicas: {{ .Values.observability.otel.collector.replicas | default 1 }} | ||
| selector: | ||
| matchLabels: | ||
| app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-otel-collector | ||
| template: | ||
| metadata: | ||
| namespace: {{ .Release.Namespace }} | ||
| labels: | ||
| app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-otel-collector | ||
| annotations: | ||
| timestamp: {{ now | quote }} | ||
| spec: | ||
| {{- include "plane.podScheduling" .Values.observability.otel.collector }} | ||
|
Comment on lines
+87
to
+95
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- target file (relevant ranges) ---'
nl -ba charts/plane-enterprise/templates/observability/otel-collector.yaml | sed -n '1,220p'
echo
echo '--- checksum patterns in repo ---'
rg -n 'checksum/|now \| quote|sha256sum' charts/plane-enterprise -SRepository: makeplane/helm-charts Length of output: 237 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- target file (relevant ranges) ---'
sed -n '1,220p' charts/plane-enterprise/templates/observability/otel-collector.yaml | cat -n
echo
echo '--- checksum patterns in repo ---'
rg -n 'checksum/|now \| quote|sha256sum' charts/plane-enterprise -SRepository: makeplane/helm-charts Length of output: 7360 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- checksum / configmap annotation patterns in repo ---'
rg -n 'checksum/.*config|configmap.*sha256sum|sha256sum.*config|include .*sha256sum|checksum/config' charts -S
echo
echo '--- config-related pod annotations in repo ---'
rg -n 'annotations:|timestamp: \{\{ now \| quote \}\}' charts/plane-enterprise/templates -SRepository: makeplane/helm-charts Length of output: 216 Avoid the unconditional
🤖 Prompt for AI Agents |
||
| containers: | ||
| - name: {{ .Release.Name }}-otel-collector | ||
| imagePullPolicy: {{ .Values.observability.otel.collector.pullPolicy | default "IfNotPresent" }} | ||
| image: {{ .Values.observability.otel.collector.image | default "otel/opentelemetry-collector-contrib:0.115.1" }} | ||
| args: ["--config=/etc/otel/config.yaml"] | ||
| ports: | ||
| - name: otlp-grpc | ||
| containerPort: 4317 | ||
| - name: otlp-http | ||
| containerPort: 4318 | ||
| resources: | ||
| requests: | ||
| memory: {{ .Values.observability.otel.collector.memoryRequest | default "128Mi" | quote }} | ||
| cpu: {{ .Values.observability.otel.collector.cpuRequest | default "100m" | quote }} | ||
| limits: | ||
| memory: {{ .Values.observability.otel.collector.memoryLimit | default "512Mi" | quote }} | ||
| cpu: {{ .Values.observability.otel.collector.cpuLimit | default "500m" | quote }} | ||
| volumeMounts: | ||
| - name: config | ||
| mountPath: /etc/otel | ||
| volumes: | ||
| - name: config | ||
| configMap: | ||
| name: {{ .Release.Name }}-otel-collector-config | ||
| {{- end }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,9 +88,12 @@ spec: | |
| - secretRef: | ||
| name: {{ if not (empty .Values.external_secrets.opensearch_existingSecret) }}{{ .Values.external_secrets.opensearch_existingSecret }}{{ else }}{{ .Release.Name }}-opensearch-secrets{{ end }} | ||
| optional: false | ||
| {{- if or .Values.extraEnv (include "plane.s3CAEnabled" .) }} | ||
| {{- if or .Values.extraEnv (include "plane.s3CAEnabled" .) .Values.observability.otel.enabled }} | ||
| env: | ||
| {{- with (include "plane.s3CAEnvVars" .) }} | ||
| {{ . | indent 10 }} | ||
| {{- end }} | ||
| {{- with (include "plane.otelServiceEnv" (dict "context" $ "service" "pi-api")) }} | ||
| {{ . | indent 10 }} | ||
| {{- end }} | ||
|
Comment on lines
+91
to
98
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift OTLP auth headers rendered as plaintext env value, unlike the Secret-backed path used for backend workloads.
This is called here without Consider sourcing 🤖 Prompt for AI Agents |
||
| {{- if .Values.extraEnv }} | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.