Skip to content

feat(plane-enterprise): add OpenTelemetry traces/logs/metrics support#248

Open
pratapalakshmi wants to merge 3 commits into
masterfrom
feat/plane-enterprise-otel
Open

feat(plane-enterprise): add OpenTelemetry traces/logs/metrics support#248
pratapalakshmi wants to merge 3 commits into
masterfrom
feat/plane-enterprise-otel

Conversation

@pratapalakshmi

@pratapalakshmi pratapalakshmi commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator

What

Adds native, opt-in OpenTelemetry support to the plane-enterprise chart, mirroring the otel-observability kustomize component already used in commercial-deployments. Off by default — no behavior change unless observability.otel.enabled=true.

Changes

  • values.yaml — new observability.otel block:
    • enabled, endpoint, protocol (grpc), headers, environment, resourceAttributes, debugConsole, sampler, samplerArg
    • frontend.{enabled,endpoint,headers} for browser tracing (web/admin/space), served to browsers by the API.
  • templates/config-secrets/otel.yaml — shared <release>-otel-vars ConfigMap, rendered only when enabled.
  • templates/_helpers.tplplane.otel.enabled / plane.otel.envFrom / plane.otel.serviceEnv.
  • 11 backend workloads wired (api, worker, beat-worker, automation-consumer, outbox-poller, silo, live, space, pi-api, pi-beat, pi-worker): the shared ConfigMap via envFrom + an inline per-workload OTEL_SERVICE_NAME so each reports its own service.name. web/admin are intentionally not wired (browser-only tracing, configured from the API's instance config).

Why these defaults

Three lessons from validating tracing on a live cluster:

  1. sampler: always_onparentbased_* defers to an incoming traceparent's sampled flag and ignores the ratio, so browser-initiated POST/user-action traces get dropped even at 1.0 (you see only root GET traffic). always_on captures everything for test/debug. Use parentbased_traceidratio for prod.
  2. environmentdeployment.environment.name — the current semconv key, so the API's environment tag matches the node/pi/browser services for cross-service filtering (the legacy deployment.environment does not).
  3. frontend.headers non-empty — forces the browser OTLP exporter onto XHR; sendBeacon fails CORS against a wildcard Access-Control-Allow-Origin.

Testing

helm template in both states:

  • Enabled: all 11 workloads get the otel-vars configMapRef + correct distinct OTEL_SERVICE_NAME; ConfigMap renders deployment.environment.name=… and OTEL_TRACES_SAMPLER: always_on.
  • Disabled (default): zero OTel env injected, no null/empty env/envFrom blocks; all rendered manifests parse as valid Kubernetes YAML.

Note: no Chart.yaml version bump included (assuming versioning is handled via the separate release flow — happy to add one if preferred).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added OpenTelemetry observability integration to enable comprehensive application performance monitoring and distributed tracing across all services
    • Introduced new observability configuration options for OTLP export settings, trace sampling strategies, and service environment tagging
    • Extended monitoring support to all application workloads with configurable environment-specific attributes and resource identification
    • Added optional frontend tracing capabilities to monitor browser and client-side application behavior

Adds native, opt-in OTel wiring to the chart (mirrors the kustomize
otel-observability component used in commercial-deployments). Off by default.

- observability.otel.* values block: enabled, endpoint, protocol, headers,
  environment, resourceAttributes, debugConsole, sampler, samplerArg, and a
  frontend.{enabled,endpoint,headers} block for browser tracing.
- Shared <release>-otel-vars ConfigMap (templates/config-secrets/otel.yaml),
  rendered only when observability.otel.enabled.
- Wires the 11 backend workloads (api, worker, beat-worker,
  automation-consumer, outbox-poller, silo, live, space, pi-api, pi-beat,
  pi-worker) via envFrom + an inline per-workload OTEL_SERVICE_NAME so each
  reports its own service.name. web/admin are intentionally not wired — their
  only OTel is browser tracing, served to them by the API via the frontend.* keys.
- Helpers: plane.otel.enabled / plane.otel.envFrom / plane.otel.serviceEnv.

Defaults encode two hard-won lessons:
- sampler defaults to always_on: parentbased_* defers to an upstream
  traceparent's sampled flag (dropping browser-initiated POST traces even at
  ratio 1.0); always_on captures everything for test/debug. Switch to
  parentbased_traceidratio for prod.
- environment maps to deployment.environment.name (current semconv key) so the
  tag matches the other services for cross-service filtering.
- frontend.headers defaults to a non-empty value to force the browser OTLP
  exporter onto XHR (sendBeacon fails CORS against a wildcard ACAO).

Verified with `helm template` in both enabled and disabled states: all
workloads wire correctly when enabled, and no OTel env / null env blocks render
when disabled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@pratapalakshmi, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 46 minutes and 34 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8f924db4-b6b7-4f81-b8b4-994d7372d2a3

📥 Commits

Reviewing files that changed from the base of the PR and between d1e3e2a and 54551e2.

📒 Files selected for processing (2)
  • charts/plane-enterprise/Chart.yaml
  • charts/plane-enterprise/questions.yml

Walkthrough

Adds OpenTelemetry support to the plane-enterprise Helm chart. Three new helper templates are introduced in _helpers.tpl, a conditional OTEL ConfigMap template is added, a new observability.otel values block defines all OTLP and sampling settings, and twelve workload Deployment templates are updated to inject the shared OTEL environment configuration.

Changes

OpenTelemetry Integration

Layer / File(s) Summary
Values schema and OTEL helper templates
charts/plane-enterprise/values.yaml, charts/plane-enterprise/templates/_helpers.tpl
Adds an observability.otel values block (disabled by default) covering OTLP endpoint/protocol/headers, resource attributes, debug toggle, trace sampler, and frontend sub-config. Introduces three helpers: plane.otel.enabled (feature gate), plane.otel.envFrom (ConfigMap reference), and plane.otel.serviceEnv (per-service OTEL_SERVICE_NAME var).
OTEL ConfigMap template
charts/plane-enterprise/templates/config-secrets/otel.yaml
Conditionally renders a ConfigMap named {release}-otel-vars with OTEL_ENABLED, OTLP exporter settings, environment/resource attributes, debug console toggle, trace sampler configuration, and optional frontend OTEL exporter values, all driven by .Values.observability.otel.*.
Workload Deployment environment injection
charts/plane-enterprise/templates/workloads/*.deployment.yaml
Updates all twelve workload Deployments (api, automation-consumer, beat-worker, live, outbox-poller, pi-api, pi-beat, pi-worker, silo, space, worker) to include plane.otel.envFrom in envFrom and inject plane.otel.serviceEnv within expanded env: conditional blocks when OTEL is enabled.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • akshat5302
  • mguptahub

Poem

🐇 A rabbit hops through traces bright,
ConfigMaps glow with OTEL light.
Each service named, each span in place,
Twelve deployments set the pace.
With observability on, we soar—
No span goes untracked anymore! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding OpenTelemetry support to the plane-enterprise Helm chart, which accurately reflects the primary purpose of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/plane-enterprise-otel

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@charts/plane-enterprise/templates/config-secrets/otel.yaml`:
- Around line 15-17: The OTEL_EXPORTER_OTLP_HEADERS field containing
authentication credentials is currently stored in a ConfigMap, which is not
encrypted and poses a security risk. Remove the OTEL_EXPORTER_OTLP_HEADERS
variable from the otel.yaml ConfigMap template and instead create a separate
Secret resource to store sensitive OTEL header values. Update the pod
specification to mount these values from the Secret using secretRef instead of
configMapRef, ensuring the ingestion credentials are properly protected.
- Around line 33-37: The FRONTEND_OTEL_ENABLED configuration variable is
currently being set to "1" based only on the frontend.enabled flag, but
according to the values contract it should only be enabled when both
frontend.enabled is true AND frontend.endpoint is set. Update the conditional
check at line 33 to verify both conditions are met by combining the check for
observability.otel.frontend.enabled with a check that
observability.otel.frontend.endpoint is also defined and not empty before
setting FRONTEND_OTEL_ENABLED to "1".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8ae0949c-79b7-4363-a629-2000d2232b49

📥 Commits

Reviewing files that changed from the base of the PR and between 728c9d9 and d1e3e2a.

📒 Files selected for processing (14)
  • charts/plane-enterprise/templates/_helpers.tpl
  • charts/plane-enterprise/templates/config-secrets/otel.yaml
  • charts/plane-enterprise/templates/workloads/api.deployment.yaml
  • charts/plane-enterprise/templates/workloads/automation-consumer.deployment.yaml
  • charts/plane-enterprise/templates/workloads/beat-worker.deployment.yaml
  • charts/plane-enterprise/templates/workloads/live.deployment.yaml
  • charts/plane-enterprise/templates/workloads/outbox-poller.deployment.yaml
  • charts/plane-enterprise/templates/workloads/pi-api.deployment.yaml
  • charts/plane-enterprise/templates/workloads/pi-beat.deployment.yaml
  • charts/plane-enterprise/templates/workloads/pi-worker.deployment.yaml
  • charts/plane-enterprise/templates/workloads/silo.deployment.yaml
  • charts/plane-enterprise/templates/workloads/space.deployment.yaml
  • charts/plane-enterprise/templates/workloads/worker.deployment.yaml
  • charts/plane-enterprise/values.yaml

Comment on lines +15 to +17
{{- with .Values.observability.otel.headers }}
OTEL_EXPORTER_OTLP_HEADERS: {{ . | quote }}
{{- end }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Move OTLP auth headers out of ConfigMap

OTEL_EXPORTER_OTLP_HEADERS can carry ingestion credentials, but this template stores it in a ConfigMap. That weakens secret handling and broadens accidental exposure. Use a Secret for sensitive OTEL header values and mount via secretRef instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@charts/plane-enterprise/templates/config-secrets/otel.yaml` around lines 15 -
17, The OTEL_EXPORTER_OTLP_HEADERS field containing authentication credentials
is currently stored in a ConfigMap, which is not encrypted and poses a security
risk. Remove the OTEL_EXPORTER_OTLP_HEADERS variable from the otel.yaml
ConfigMap template and instead create a separate Secret resource to store
sensitive OTEL header values. Update the pod specification to mount these values
from the Secret using secretRef instead of configMapRef, ensuring the ingestion
credentials are properly protected.

Comment on lines +33 to +37
{{- if .Values.observability.otel.frontend.enabled }}
FRONTEND_OTEL_ENABLED: "1"
{{- with .Values.observability.otel.frontend.endpoint }}
FRONTEND_OTLP_ENDPOINT: {{ . | quote }}
{{- end }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Frontend OTEL enablement is missing endpoint gating

Line 33 enables frontend OTEL based only on frontend.enabled, but the values contract says it should turn on only when both enabled and endpoint are set. This can emit FRONTEND_OTEL_ENABLED without a usable endpoint and produce broken browser exporter config.

Suggested template fix
-  {{- if .Values.observability.otel.frontend.enabled }}
+  {{- if and .Values.observability.otel.frontend.enabled .Values.observability.otel.frontend.endpoint }}
   FRONTEND_OTEL_ENABLED: "1"
   {{- with .Values.observability.otel.frontend.endpoint }}
   FRONTEND_OTLP_ENDPOINT: {{ . | quote }}
   {{- end }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{{- if .Values.observability.otel.frontend.enabled }}
FRONTEND_OTEL_ENABLED: "1"
{{- with .Values.observability.otel.frontend.endpoint }}
FRONTEND_OTLP_ENDPOINT: {{ . | quote }}
{{- end }}
{{- if and .Values.observability.otel.frontend.enabled .Values.observability.otel.frontend.endpoint }}
FRONTEND_OTEL_ENABLED: "1"
{{- with .Values.observability.otel.frontend.endpoint }}
FRONTEND_OTLP_ENDPOINT: {{ . | quote }}
{{- end }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@charts/plane-enterprise/templates/config-secrets/otel.yaml` around lines 33 -
37, The FRONTEND_OTEL_ENABLED configuration variable is currently being set to
"1" based only on the frontend.enabled flag, but according to the values
contract it should only be enabled when both frontend.enabled is true AND
frontend.endpoint is set. Update the conditional check at line 33 to verify both
conditions are met by combining the check for
observability.otel.frontend.enabled with a check that
observability.otel.frontend.endpoint is also defined and not empty before
setting FRONTEND_OTEL_ENABLED to "1".

pratapalakshmi and others added 2 commits June 20, 2026 16:06
…s.yml

Surfaces the new observability.otel.* values as a Rancher catalog "OpenTelemetry"
question group: an enable toggle with subquestions for endpoint, protocol, headers,
environment, resource attributes, sampler (+ ratio), debug console, and the browser
tracing block. Defaults mirror values.yaml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y support

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant