Skip to content

feat: Add PostHog telemetry provider#9409

Merged
christian-byrne merged 1 commit intomainfrom
feat/posthog-telemetry-provider
Mar 6, 2026
Merged

feat: Add PostHog telemetry provider#9409
christian-byrne merged 1 commit intomainfrom
feat/posthog-telemetry-provider

Conversation

@robinjhuang
Copy link
Member

@robinjhuang robinjhuang commented Mar 5, 2026

Add PostHog as a telemetry provider for cloud builds so custom events can be correlated with session recordings. Follows the same pattern as MixpanelTelemetryProvider with dynamic import, event queuing, and disabled events from remote config. Tree-shaken away in OSS builds.

The posthog-js package uses Apache-2.0 (verified from its LICENSE file) but declares it as "SEE LICENSE IN LICENSE" in package.json, which
the license checker can't parse.

┆Issue is synchronized with this Notion page by Unito

@robinjhuang robinjhuang requested a review from a team as a code owner March 5, 2026 01:54
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Mar 5, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new cloud PostHog telemetry provider, registers it in telemetry initialization, exposes PostHog config in types and remote config, adds the posthog-js dependency, includes CI checks for PostHog, and adds unit tests for the provider.

Changes

Cohort / File(s) Summary
Type Definitions & Remote Config
global.d.ts, src/platform/remoteConfig/types.ts
Added optional posthog_project_token?: string and posthog_api_host?: string to Window.__CONFIG__ and RemoteConfig.
Dependencies / Workspace
package.json, pnpm-workspace.yaml
Added posthog-js dependency and pinned workspace catalog entry.
Telemetry Registry
src/platform/telemetry/initTelemetry.ts
Imported and registered new PostHogTelemetryProvider alongside existing cloud providers.
PostHog Provider & Tests
src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts, src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.test.ts
New PostHogTelemetryProvider implemented with lazy posthog-js import, init/queueing logic, disabled-events via remote config, user identification, event mapping methods; comprehensive unit tests added.
CI Workflows
.github/workflows/ci-oss-assets-validation.yaml, .github/workflows/ci-dist-telemetry-scan.yaml
Excluded posthog-js from OSS license check; added CI scan step to detect PostHog telemetry references in built assets.

Sequence Diagram(s)

sequenceDiagram
    participant Registry as TelemetryRegistry
    participant Remote as RemoteConfig
    participant User as UserService
    participant PH as PostHog SDK

    Registry->>Remote: read posthog_project_token / posthog_api_host
    alt token missing
        Registry->>Registry: mark PostHog provider disabled
    else token present
        Registry->>PH: dynamic import & init(token, api_host)
        PH-->>Registry: initialized
        Registry->>User: subscribe onUserResolved
        User-->>Registry: user resolved (id, props)
        Registry->>PH: identify(user.id, user.props)
    end
    Registry->>Registry: track(event) (queues if PH not ready)
    alt PH ready
        Registry->>PH: capture event
    else PH not ready
        Registry->>Registry: enqueue event
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped in with a token and host,
Queued tiny hops until PostHog awoke,
Remote whispers told which tracks to keep,
Events leapt out and landed on posts —
A rabbit’s soft clap for telemetry toast!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the purpose (enable custom event/session recording correlation), implementation approach (follows MixpanelTelemetryProvider pattern), and licensing details, but does not follow the required template structure with Summary, Changes, and Review Focus sections. Restructure the description to follow the template: add a one-sentence Summary section, organize Changes section (What/Breaking/Dependencies), and include Review Focus with key design decisions or edge cases requiring attention.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Add PostHog telemetry provider' accurately and concisely describes the main change—adding a new telemetry provider—matching the changeset's primary objective.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/posthog-telemetry-provider

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

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 03/05/2026, 06:27:13 AM UTC

Links

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

🎭 Playwright: ✅ 549 passed, 0 failed · 5 flaky

📊 Browser Reports
  • chromium: View Report (✅ 536 / ❌ 0 / ⚠️ 5 / ⏭️ 10)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 10 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

📦 Bundle: 4.49 MB gzip ⚪ 0 B

Details

Summary

  • Raw size: 21.1 MB baseline 21.1 MB — ⚪ 0 B
  • Gzip: 4.49 MB baseline 4.49 MB — ⚪ 0 B
  • Brotli: 3.47 MB baseline 3.47 MB — ⚪ 0 B
  • Bundles: 228 current • 228 baseline

Category Glance
Vendor & Third-Party ⚪ 0 B (8.86 MB) · Other ⚪ 0 B (7.92 MB) · Data & Services ⚪ 0 B (2.73 MB) · Graph Workspace ⚪ 0 B (920 kB) · Panels & Settings ⚪ 0 B (436 kB) · Views & Navigation ⚪ 0 B (72.4 kB) · + 5 more

App Entry Points — 17.8 kB (baseline 17.8 kB) • ⚪ 0 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-CFDnq3Ai.js 17.8 kB 17.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Graph Workspace — 920 kB (baseline 920 kB) • ⚪ 0 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-X1J3idHi.js 920 kB 920 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Views & Navigation — 72.4 kB (baseline 72.4 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudAuthTimeoutView-DSWBOqkd.js 4.95 kB 4.95 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudForgotPasswordView-BPi8mSnz.js 5.6 kB 5.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudLayoutView-CpFhvPnk.js 6.47 kB 6.47 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudLoginView-CYRjvRCL.js 11.5 kB 11.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudSignupView-CQknHfMY.js 9.41 kB 9.41 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudSorryContactSupportView-DwQRNUxH.js 1.02 kB 1.02 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudSubscriptionRedirectView-uZW1jgHu.js 4.8 kB 4.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudSurveyView-BaH-d27Z.js 15.5 kB 15.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/layout-CTBdQNLF.js 296 B 296 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserCheckView-CfbWp14K.js 8.41 kB 8.41 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserSelectView-Bx_7q6pJ.js 4.5 kB 4.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Panels & Settings — 436 kB (baseline 436 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/AboutPanel-Qnag-BtT.js 9.79 kB 9.79 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/cloudRemoteConfig-DMO5L-7j.js 1.48 kB 1.48 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/config-Dim-BcsI.js 996 B 996 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ExtensionPanel-C4EUHBkK.js 9.42 kB 9.42 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/KeybindingPanel-BubSOG3F.js 12.3 kB 12.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/LegacyCreditsPanel-DQD6ClZ9.js 20.7 kB 20.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/refreshRemoteConfig-D3bNXjTb.js 1.14 kB 1.14 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SecretsPanel-BVIberNo.js 21.5 kB 21.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ServerConfigPanel-BsaPEf59.js 6.49 kB 6.49 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Az4QGSr7.js 38.5 kB 38.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Bc1kL5ht.js 27.8 kB 27.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BxoUe5GJ.js 28.7 kB 28.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-ClhpchbB.js 34.2 kB 34.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-D9qrBXiF.js 30.5 kB 30.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DXfL5vCm.js 23.9 kB 23.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-jzj0F3XL.js 28.8 kB 28.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-KcouHUkA.js 27.9 kB 27.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-MfieTybP.js 32.4 kB 32.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-V6oR26kh.js 24.5 kB 24.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-YUrYiWmR.js 29.9 kB 29.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscriptionPanel-CeTp6WJp.js 18.7 kB 18.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserPanel-7O47d2Rr.js 6.21 kB 6.21 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
User & Accounts — 16.1 kB (baseline 16.1 kB) • ⚪ 0 B

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/auth-B5FjR8ys.js 357 B 357 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/auth-DJeBXJoo.js 3.4 kB 3.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/firebaseAuthStore-sFXizCSW.js 831 B 831 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/PasswordFields-C2IR8Uml.js 4.51 kB 4.51 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SignUpForm-CDktNwnU.js 3.01 kB 3.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UpdatePasswordContent-elJOa-OD.js 2.41 kB 2.41 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WorkspaceProfilePic-KL8Hs2yn.js 1.57 kB 1.57 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Editors & Dialogs — 779 B (baseline 779 B) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useSubscriptionDialog-DmhCylbn.js 779 B 779 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
UI Components — 47 kB (baseline 47 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/Button-D-9gIyaN.js 3.08 kB 3.08 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudBadge-Cx_Hg1jw.js 1.11 kB 1.11 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/cloudFeedbackTopbarButton-B28qhmYU.js 1.64 kB 1.64 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ComfyQueueButton-B143Jqoq.js 8.02 kB 8.02 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ComfyQueueButton-F7Jwgdcb.js 836 B 836 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/FormSearchInput-y8BSEeZq.js 3.73 kB 3.73 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ScrubableNumberInput-BS8_8a5j.js 5.95 kB 5.95 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscribeButton-DpZ-8gIg.js 2.34 kB 2.34 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/TopbarBadge-D1EvgBfE.js 7.39 kB 7.39 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserAvatar-BQCZ8iNl.js 1.17 kB 1.17 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useTerminalTabs-tYp-6iWM.js 9.89 kB 9.89 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetButton-DGB_HZfA.js 1.84 kB 1.84 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Data & Services — 2.73 MB (baseline 2.73 MB) • ⚪ 0 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/api-DLX40S6L.js 689 kB 689 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/audioService-C_qI9vRj.js 1.73 kB 1.73 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/bootstrapStore-CDhT8OIA.js 2.08 kB 2.08 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/dialogService-6nkYWwLj.js 1.91 MB 1.91 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/dialogService-CQ6iFVq6.js 768 B 768 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/extensionStore-uhxC5bS1.js 13 kB 13 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/keybindingService-CQAVPTDF.js 6.52 kB 6.52 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/load3dService-Cp0-ymmM.js 91 kB 91 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/releaseStore-CXKYA2zv.js 803 B 803 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/releaseStore-D5cnn80I.js 7.96 kB 7.96 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/serverConfigStore-BJqmVNuT.js 2.32 kB 2.32 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settingStore-QRManT5j.js 787 B 787 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/userStore-Bg8DQfoH.js 1.85 kB 1.85 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/workflowDraftStore-lULpE52_.js 779 B 779 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
Utilities & Hooks — 56.6 kB (baseline 56.6 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/_plugin-vue_export-helper-ralzwvFM.js 315 B 315 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/audioUtils-eImDk5Hr.js 858 B 858 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/colorUtil-BJSyqxym.js 7 kB 7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/envUtil-CC-l-L9z.js 466 B 466 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/markdownRendererUtil-Cddas8Zl.js 1.56 kB 1.56 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SkeletonUtils-CsnHjXS0.js 133 B 133 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/subscriptionCheckoutUtil-Ckm9KsB7.js 2.53 kB 2.53 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useCopyToClipboard-BIA0IAgt.js 944 B 944 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useCurrentUser-4M6Rw4_v.js 765 B 765 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useErrorHandling-C7PEp_zS.js 1.5 kB 1.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useExternalLink-jZrPYEpq.js 1.66 kB 1.66 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useFeatureFlags-Bhh2Befa.js 4.14 kB 4.14 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useLoad3d-CGx8vNU6.js 902 B 902 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useLoad3d-CTOUe8IC.js 14.6 kB 14.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useLoad3dViewer-B3sASCxH.js 14.1 kB 14.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useLoad3dViewer-B878UsRM.js 881 B 881 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useWorkspaceSwitch-B4_92AdE.js 1.25 kB 1.25 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useWorkspaceUI-HX_iimnk.js 3 kB 3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Vendor & Third-Party — 8.86 MB (baseline 8.86 MB) • ⚪ 0 B

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-axios-Cp6hch1I.js 70.7 kB 70.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-chart-l-KY-tZQ.js 399 kB 399 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-firebase-BvMr43CG.js 836 kB 836 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-i18n-DccD0mxo.js 133 kB 133 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-markdown-D5S6AC80.js 103 kB 103 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-other-BSv7ubBF.js 1.52 MB 1.52 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-D2gQvLCc.js 1.73 MB 1.73 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-reka-ui-C-tDe-KL.js 399 kB 399 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-sentry-SQwstEKc.js 182 kB 182 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-ueviNA60.js 1.8 MB 1.8 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-BnYkbQDM.js 634 kB 634 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-core-CmHHRvL9.js 311 kB 311 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vueuse-cYXYo6hi.js 121 kB 121 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-XVeHlCL4.js 374 kB 374 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-yjs-CP_4YO8u.js 143 kB 143 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-zod-DcCUUPIi.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Other — 7.92 MB (baseline 7.92 MB) • ⚪ 0 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/AnimationControls-Bal5YgT5.js 4.61 kB 4.61 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ApiNodesSignInContent-Djz4Lsh2.js 2.69 kB 2.69 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/AudioPreviewPlayer-VFRZxAQf.js 11 kB 11 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/auto-Bt3L7FBS.js 1.7 kB 1.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/BaseViewTemplate-BU8wYnsH.js 1.78 kB 1.78 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CancelSubscriptionDialogContent-4AGRHMAk.js 4.83 kB 4.83 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/changeTracker-BHSZEWFl.js 9.44 kB 9.44 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/changeTracker-C0WSkmLK.js 800 B 800 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/cloudBadges-Dwrw5bud.js 1.41 kB 1.41 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudRunButtonWrapper-DZp4YPfI.js 1.72 kB 1.72 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/cloudSessionCookie-Db5NLcFV.js 3.14 kB 3.14 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/cloudSubscription-CpiCScXX.js 1.37 kB 1.37 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/comfy-logo-single-CoSPG7JX.js 198 B 198 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ComfyOrgHeader-CXepDPJT.js 910 B 910 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-32T5PqF_.js 19 kB 19 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Ak-xav7X.js 17.7 kB 17.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-B7yDR3IF.js 16.2 kB 16.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BfgrmbF3.js 16.3 kB 16.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BKiowuzF.js 17.1 kB 17.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-C2ScMdCP.js 16.1 kB 16.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CIaXr_da.js 16.3 kB 16.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CQ_1hcIQ.js 15.2 kB 15.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-D9CRAR5X.js 17.7 kB 17.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DgrxZ384.js 16.9 kB 16.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Dm6gdG1p.js 15.4 kB 15.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/constants-CobilG8q.js 579 B 579 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/core-DxmlBS1N.js 73.7 kB 73.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CreateWorkspaceDialogContent-Co1hLZtf.js 5.57 kB 5.57 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CurrentUserPopoverWorkspace-ClKAUJxJ.js 20.5 kB 20.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/DeleteWorkspaceDialogContent-Dw9ilEhx.js 4.27 kB 4.27 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/EditWorkspaceDialogContent-xzxUN6lO.js 5.37 kB 5.37 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/FreeTierDialogContent-8VtAx4NF.js 5.43 kB 5.43 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/GlobalToast-CGMsfima.js 2.91 kB 2.91 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/graphHasMissingNodes-DFJPLQbd.js 761 B 761 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/groupNode-C3q_wZZM.js 71.8 kB 71.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/i18n-DjENuXF_.js 199 B 199 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/i18n-J1VFb2ee.js 535 kB 535 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/InviteMemberDialogContent-DxyVmjs7.js 7.43 kB 7.43 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/InviteMemberUpsellDialogContent-CEMo6N1g.js 3.87 kB 3.87 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/LeaveWorkspaceDialogContent-Dk18cN1q.js 4.1 kB 4.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Load3D-Cj7GQH5C.js 1.11 kB 1.11 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/load3d-Db8s6unb.js 14.8 kB 14.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Load3D-DXwMEDVY.js 16.2 kB 16.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Load3DConfiguration-CBLH42-w.js 6.27 kB 6.27 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Load3DControls-KR9TEwm2.js 30.9 kB 30.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Load3dViewerContent-kM9GS-YM.js 23 kB 23 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Load3dViewerContent-SVwGtWJz.js 1.04 kB 1.04 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-a_fD2A1w.js 151 kB 151 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Bi1XfdpF.js 188 kB 188 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BJQ0M9Yj.js 210 kB 210 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BvVDOLZZ.js 150 kB 150 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BZLcIBqp.js 173 kB 173 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CjbGas6Z.js 132 kB 132 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CZaOv97H.js 133 kB 133 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-D6nxp_Jl.js 153 kB 153 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-dKpvLPCH.js 181 kB 181 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-dXT40Jsi.js 158 kB 158 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-WPbnhfZ5.js 155 kB 155 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Media3DTop-CZ4wk4U1.js 1.82 kB 1.82 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-pqbTSt64.js 1.43 kB 1.43 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-CfDqPsGU.js 1.75 kB 1.75 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaOtherTop-B84VMc_d.js 1.02 kB 1.02 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaTextTop-DIqLHunN.js 1.01 kB 1.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-WILUyTDj.js 2.77 kB 2.77 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nightlyBadges-DOEl77fn.js 1.04 kB 1.04 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-46r0KRED.js 451 kB 451 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BrUpuJ60.js 396 kB 396 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-C5Naq7UG.js 364 kB 364 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CenyYNO8.js 450 kB 450 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CN3CzRXx.js 404 kB 404 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Cz73oY7a.js 368 kB 368 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-D22mZTDT.js 400 kB 400 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Dh2PHfFx.js 391 kB 391 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DJ0GsBGj.js 399 kB 399 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DJKCo7UK.js 416 kB 416 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-FjSUW2rw.js 491 kB 491 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeTemplates-C_p6EP2B.js 9.34 kB 9.34 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/OBJLoader2WorkerModule-DTMpvldF.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/onboardingCloudRoutes-DflzI1ya.js 5.47 kB 5.47 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Popover-iM3e9lB4.js 3.65 kB 3.65 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Preview3d-C3_HRDtY.js 4.89 kB 4.89 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/previousFullPath-B7kLbu-T.js 1.39 kB 1.39 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/RemoveMemberDialogContent-BGlikIUO.js 4.08 kB 4.08 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/RevokeInviteDialogContent-D2ZHDW5x.js 4 kB 4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/rolldown-runtime-DLICfi3-.js 1.97 kB 1.97 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/saveMesh-nslieznb.js 3.42 kB 3.42 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SelectValue-CedvgC2B.js 8.94 kB 8.94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SignInContent-BLSICAVe.js 18.9 kB 18.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/signInSchema-D-cpFzst.js 1.53 kB 1.53 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Slider-D4A5BM3I.js 3.52 kB 3.52 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/src-KRN59wM5.js 251 B 251 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscribeToRun-DJxL5akE.js 2.06 kB 2.06 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscriptionBenefits-BxBbqnOZ.js 2.01 kB 2.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscriptionPanelContentWorkspace-BpTgKhVI.js 22 kB 22 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscriptionPanelContentWorkspace-yBxZaJDq.js 963 B 963 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscriptionRequiredDialogContent-Bb-aNFJt.js 25.7 kB 25.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscriptionRequiredDialogContentWorkspace-lrhY7Tu9.js 46.4 kB 46.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/telemetry-zZf2dHJ2.js 226 B 226 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/tierBenefits-Bsn-agZL.js 3.66 kB 3.66 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/types-DT3N7am7.js 204 B 204 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ValueControlPopover-k-SZ9s6R.js 4.96 kB 4.96 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/VideoPlayOverlay-d1kDZ1Hw.js 1.35 kB 1.35 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widget-DIRwAHBY.js 3.01 kB 3.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-Dx4DYlRd.js 3.19 kB 3.19 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-ThP4bP1R.js 283 B 283 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-YZCBKjIT.js 2.21 kB 2.21 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetColorPicker-C4yd_6Zg.js 2.9 kB 2.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetCurve-C3tuuOR3.js 9.36 kB 9.36 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetGalleria-tNR6Ubxu.js 3.61 kB 3.61 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-HFijaR80.js 7 kB 7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCrop-DT5Gj--f.js 22.2 kB 22.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetInputNumber-CN3lxTt3.js 18.8 kB 18.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetInputText-W9vcgWMp.js 1.86 kB 1.86 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetLayoutField-S6xnM-i1.js 1.98 kB 1.98 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetLegacy-lvXeoQEY.js 787 B 787 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetMarkdown-BqPoJLFX.js 2.93 kB 2.93 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetPainter-9zcpi7WL.js 32.9 kB 32.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-C6ZYch5M.js 1.1 kB 1.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetRecordAudio-11lQE-Dc.js 17.4 kB 17.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetSelect-DdLDVcqm.js 58.3 kB 58.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetTextarea-aCGogL4R.js 5.07 kB 5.07 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetToggleSwitch-9dIESGMI.js 6.8 kB 6.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetTypes-DYLaC2lj.js 393 B 393 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetWithControl-4pAtw5Wa.js 4.14 kB 4.14 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WorkspacePanelContent-B1sftQ8N.js 29.3 kB 29.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

@robinjhuang robinjhuang added backport Backporting a PR onto a release candidate cloud/1.40 Backport PRs for cloud 1.40 labels Mar 5, 2026
@github-actions
Copy link

github-actions bot commented Mar 5, 2026

⚡ Performance Report

ℹ️ Collecting baseline variance data (0/5 runs). Significance will appear after 2 main branch runs.

Metric Baseline PR Δ
canvas-idle: style recalcs 125 125 +0%
canvas-idle: layouts 0 0 +0%
canvas-idle: task duration 410ms 426ms +4%
canvas-mouse-sweep: style recalcs 176 178 +1%
canvas-mouse-sweep: layouts 13 12 -5%
canvas-mouse-sweep: task duration 885ms 965ms +9%
dom-widget-clipping: style recalcs 43 44 +2%
dom-widget-clipping: layouts 0 0
dom-widget-clipping: task duration 369ms 366ms -1%
subgraph-dom-widget-clipping: style recalcs 74 73 -0%
subgraph-dom-widget-clipping: layouts 0 0
subgraph-dom-widget-clipping: task duration 424ms 427ms +1%
subgraph-idle: style recalcs 121 122 +1%
subgraph-idle: layouts 0 0
subgraph-idle: task duration 378ms 402ms +7%
subgraph-mouse-sweep: style recalcs 155 155 -0%
subgraph-mouse-sweep: layouts 16 16 +0%
subgraph-mouse-sweep: task duration 730ms 729ms -0%
Raw data
{
  "timestamp": "2026-03-05T06:30:29.526Z",
  "gitSha": "3f9771160f6a2ddd991ef7a43ba905ce15b7ea08",
  "branch": "feat/posthog-telemetry-provider",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2036.5400000000022,
      "styleRecalcs": 125,
      "styleRecalcDurationMs": 22.601,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 448.59700000000004,
      "heapDeltaBytes": -1980544
    },
    {
      "name": "canvas-idle",
      "durationMs": 2049.24699999998,
      "styleRecalcs": 126,
      "styleRecalcDurationMs": 24.176,
      "layouts": 1,
      "layoutDurationMs": 0.26499999999999996,
      "taskDurationMs": 407.47,
      "heapDeltaBytes": -2223200
    },
    {
      "name": "canvas-idle",
      "durationMs": 2026.7590000000268,
      "styleRecalcs": 123,
      "styleRecalcDurationMs": 24.641,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 422.642,
      "heapDeltaBytes": -2690176
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 2041.5720000000022,
      "styleRecalcs": 184,
      "styleRecalcDurationMs": 53.248000000000005,
      "layouts": 12,
      "layoutDurationMs": 3.3950000000000005,
      "taskDurationMs": 1004.405,
      "heapDeltaBytes": -1743180
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 2050.6559999999754,
      "styleRecalcs": 181,
      "styleRecalcDurationMs": 53.75600000000001,
      "layouts": 12,
      "layoutDurationMs": 3.1040000000000005,
      "taskDurationMs": 1041.1709999999998,
      "heapDeltaBytes": -3249792
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1859.6620000000144,
      "styleRecalcs": 169,
      "styleRecalcDurationMs": 51.467999999999996,
      "layouts": 12,
      "layoutDurationMs": 3.4040000000000004,
      "taskDurationMs": 847.958,
      "heapDeltaBytes": -2380452
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 585.5530000000044,
      "styleRecalcs": 43,
      "styleRecalcDurationMs": 12.623000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 358.627,
      "heapDeltaBytes": 7563348
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 562.0710000000031,
      "styleRecalcs": 42,
      "styleRecalcDurationMs": 12.649000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 347.802,
      "heapDeltaBytes": 7484896
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 613.9149999999631,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 17.403,
      "layouts": 1,
      "layoutDurationMs": 0.2850000000000001,
      "taskDurationMs": 391.776,
      "heapDeltaBytes": 8787960
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 597.6509999999848,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 19.446,
      "layouts": 1,
      "layoutDurationMs": 0.26699999999999996,
      "taskDurationMs": 430.628,
      "heapDeltaBytes": -8626128
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 580.2999999999656,
      "styleRecalcs": 72,
      "styleRecalcDurationMs": 15.466000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 417.79299999999995,
      "heapDeltaBytes": -7724456
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 597.5799999999936,
      "styleRecalcs": 73,
      "styleRecalcDurationMs": 16.779000000000003,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 433.90400000000005,
      "heapDeltaBytes": -7408840
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2012.943000000007,
      "styleRecalcs": 123,
      "styleRecalcDurationMs": 24.332,
      "layouts": 1,
      "layoutDurationMs": 0.17199999999999996,
      "taskDurationMs": 413.447,
      "heapDeltaBytes": -1082888
    },
    {
      "name": "subgraph-idle",
      "durationMs": 1992.1370000000138,
      "styleRecalcs": 120,
      "styleRecalcDurationMs": 20.819999999999997,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 381.76500000000004,
      "heapDeltaBytes": -1846816
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2010.0040000000376,
      "styleRecalcs": 122,
      "styleRecalcDurationMs": 24.495000000000005,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 411.59599999999995,
      "heapDeltaBytes": -1919120
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1677.1770000000004,
      "styleRecalcs": 154,
      "styleRecalcDurationMs": 44.598,
      "layouts": 16,
      "layoutDurationMs": 3.826,
      "taskDurationMs": 712.765,
      "heapDeltaBytes": -5741424
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1683.1830000000423,
      "styleRecalcs": 154,
      "styleRecalcDurationMs": 44.937000000000005,
      "layouts": 16,
      "layoutDurationMs": 4.1579999999999995,
      "taskDurationMs": 721.743,
      "heapDeltaBytes": -3988856
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1732.0359999999937,
      "styleRecalcs": 156,
      "styleRecalcDurationMs": 47.800000000000004,
      "layouts": 16,
      "layoutDurationMs": 4.039,
      "taskDurationMs": 751.4119999999999,
      "heapDeltaBytes": -3855896
    }
  ]
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/platform/telemetry/initTelemetry.ts (1)

23-35: ⚠️ Potential issue | 🟠 Major

Avoid all-or-nothing provider initialization.

Line 29 uses Promise.all(...); if the new PostHog import at Line 34 fails,
init rejects and Mixpanel/GTM/Impact are never registered. Isolate PostHog load
so existing providers still initialize.

💡 Proposed fix
     const [
       { TelemetryRegistry },
       { MixpanelTelemetryProvider },
       { GtmTelemetryProvider },
-      { ImpactTelemetryProvider },
-      { PostHogTelemetryProvider }
+      { ImpactTelemetryProvider }
     ] = await Promise.all([
       import('./TelemetryRegistry'),
       import('./providers/cloud/MixpanelTelemetryProvider'),
       import('./providers/cloud/GtmTelemetryProvider'),
-      import('./providers/cloud/ImpactTelemetryProvider'),
-      import('./providers/cloud/PostHogTelemetryProvider')
+      import('./providers/cloud/ImpactTelemetryProvider')
     ])
@@
     registry.registerProvider(new MixpanelTelemetryProvider())
     registry.registerProvider(new GtmTelemetryProvider())
     registry.registerProvider(new ImpactTelemetryProvider())
-    registry.registerProvider(new PostHogTelemetryProvider())
+    try {
+      const { PostHogTelemetryProvider } = await import(
+        './providers/cloud/PostHogTelemetryProvider'
+      )
+      registry.registerProvider(new PostHogTelemetryProvider())
+    } catch (error) {
+      console.error('[Telemetry] Failed to load PostHog provider', error)
+    }

As per coding guidelines, "Implement proper error propagation."

Also applies to: 41-41

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/telemetry/initTelemetry.ts` around lines 23 - 35, The current
Promise.all import of TelemetryRegistry and providers (TelemetryRegistry,
MixpanelTelemetryProvider, GtmTelemetryProvider, ImpactTelemetryProvider,
PostHogTelemetryProvider) makes the whole init fail if one import (e.g.,
PostHogTelemetryProvider) throws; change to import TelemetryRegistry first then
load provider modules individually using Promise.allSettled or try/catch per
import so successful providers (MixpanelTelemetryProvider, GtmTelemetryProvider,
ImpactTelemetryProvider) still get registered even if PostHog fails, and ensure
errors from failed imports are logged via the existing telemetry init logging
path without rethrowing to block initialization (follow "proper error
propagation" guideline).
🧹 Nitpick comments (1)
src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts (1)

73-75: Bound the pending event queue to prevent unbounded growth.

Lines 155 and 173 always enqueue when not initialized, and Line 73 has no cap.
A prolonged init/load issue can grow memory indefinitely.

♻️ Proposed refactor
+const MAX_EVENT_QUEUE_SIZE = 500
+
 export class PostHogTelemetryProvider implements TelemetryProvider {
   private isEnabled = true
   private posthog: PostHog | null = null
   private eventQueue: QueuedEvent[] = []
@@
     if (this.isInitialized && this.posthog) {
       try {
         this.posthog.capture(eventName, properties || {})
       } catch (error) {
         console.error('Failed to track PostHog event:', error)
       }
     } else {
+      if (this.eventQueue.length >= MAX_EVENT_QUEUE_SIZE) {
+        this.eventQueue.shift()
+      }
       this.eventQueue.push(event)
     }
   }
@@
     if (this.isInitialized && this.posthog) {
       try {
         this.posthog.capture(eventName, properties || {})
       } catch (error) {
         console.error('Failed to track PostHog event:', error)
       }
     } else {
+      if (this.eventQueue.length >= MAX_EVENT_QUEUE_SIZE) {
+        this.eventQueue.shift()
+      }
       this.eventQueue.push({
         eventName,
         properties: properties as TelemetryEventProperties
       })
     }
   }

Also applies to: 154-156, 173-176

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts` around
lines 73 - 75, The pending event queue eventQueue can grow unbounded while
isInitialized is false; add a fixed cap (e.g. const MAX_PENDING_EVENTS = 1000)
and centralize enqueue logic into a helper (e.g. enqueuePendingEvent(event:
QueuedEvent)) to be used instead of direct pushes (replace places that push when
!isInitialized). The helper should enforce the cap by dropping oldest entries or
rejecting new ones (and log via the provider logger when a drop occurs), and
ensure eventQueue remains a bounded array of QueuedEvent; update any code paths
that directly push to eventQueue (the locations that currently enqueue when
!isInitialized) to call this helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts`:
- Around line 269-275: The submitted-survey branch calls
this.posthog.people.set(...) without checking the telemetry disabled-events
config; modify the guard at the top of the block (the code handling stage ===
'submitted' with normalizedResponses && this.posthog) to first verify the
USER_SURVEY_SUBMITTED event is enabled (e.g. check this.config.disabledEvents
does not include 'USER_SURVEY_SUBMITTED' or call the provider
helper/isEventEnabled method) and only call
this.posthog.people.set(normalizedResponses) when the event is allowed; if
disabled, skip the people.set call entirely to respect opt-out.

---

Outside diff comments:
In `@src/platform/telemetry/initTelemetry.ts`:
- Around line 23-35: The current Promise.all import of TelemetryRegistry and
providers (TelemetryRegistry, MixpanelTelemetryProvider, GtmTelemetryProvider,
ImpactTelemetryProvider, PostHogTelemetryProvider) makes the whole init fail if
one import (e.g., PostHogTelemetryProvider) throws; change to import
TelemetryRegistry first then load provider modules individually using
Promise.allSettled or try/catch per import so successful providers
(MixpanelTelemetryProvider, GtmTelemetryProvider, ImpactTelemetryProvider) still
get registered even if PostHog fails, and ensure errors from failed imports are
logged via the existing telemetry init logging path without rethrowing to block
initialization (follow "proper error propagation" guideline).

---

Nitpick comments:
In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts`:
- Around line 73-75: The pending event queue eventQueue can grow unbounded while
isInitialized is false; add a fixed cap (e.g. const MAX_PENDING_EVENTS = 1000)
and centralize enqueue logic into a helper (e.g. enqueuePendingEvent(event:
QueuedEvent)) to be used instead of direct pushes (replace places that push when
!isInitialized). The helper should enforce the cap by dropping oldest entries or
rejecting new ones (and log via the provider logger when a drop occurs), and
ensure eventQueue remains a bounded array of QueuedEvent; update any code paths
that directly push to eventQueue (the locations that currently enqueue when
!isInitialized) to call this helper.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4a1d7a47-bbac-4b7c-b636-0da8440d0ad6

📥 Commits

Reviewing files that changed from the base of the PR and between 5327fef and 2536397.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • global.d.ts
  • package.json
  • pnpm-workspace.yaml
  • scripts/vite-define-shim.ts
  • src/platform/telemetry/initTelemetry.ts
  • src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts
  • vite.config.mts
  • vitest.setup.ts

@robinjhuang robinjhuang force-pushed the feat/posthog-telemetry-provider branch from 2536397 to 5644b56 Compare March 5, 2026 02:07
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts (1)

269-275: ⚠️ Potential issue | 🟠 Major

Respect disabled-event config before people.set on survey submit.

Line 269 can still send survey-derived user properties even when
USER_SURVEY_SUBMITTED is disabled. This bypasses the provider’s opt-out
control.

💡 Proposed fix
-    if (stage === 'submitted' && normalizedResponses && this.posthog) {
+    if (
+      stage === 'submitted' &&
+      normalizedResponses &&
+      this.posthog &&
+      this.isEnabled &&
+      !this.disabledEvents.has(TelemetryEvents.USER_SURVEY_SUBMITTED)
+    ) {
       try {
         this.posthog.people.set(normalizedResponses)
       } catch (error) {
         console.error('Failed to set PostHog user properties:', error)
       }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts` around
lines 269 - 275, The posthog.people.set call in PostHogTelemetryProvider (inside
the survey submit block) bypasses the provider's opt-out for
USER_SURVEY_SUBMITTED; update the conditional to also check the provider's
disabled-event config (the same check used for captures) before calling
this.posthog.people.set so that people.set runs only when the
USER_SURVEY_SUBMITTED event is enabled (e.g., use the existing disabled-events
check or an isEventEnabled('USER_SURVEY_SUBMITTED') helper in the
PostHogTelemetryProvider class to gate the call); keep the existing
normalizedResponses and this.posthog null checks and preserve the try/catch
around people.set.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts`:
- Around line 376-377: trackPageView currently drops caller-provided metadata
and therefore violates the TelemetryProvider interface; update the
PostHogTelemetryProvider.trackPageView signature to accept the optional
properties?: PageViewMetadata parameter, pass those properties through to
this.captureRaw when emitting TelemetryEvents.PAGE_VIEW, and ensure the method
signature and any related type imports match the TelemetryProvider contract so
page view metadata (e.g., path) is preserved the same way as in
GtmTelemetryProvider and ImpactTelemetryProvider.

---

Duplicate comments:
In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts`:
- Around line 269-275: The posthog.people.set call in PostHogTelemetryProvider
(inside the survey submit block) bypasses the provider's opt-out for
USER_SURVEY_SUBMITTED; update the conditional to also check the provider's
disabled-event config (the same check used for captures) before calling
this.posthog.people.set so that people.set runs only when the
USER_SURVEY_SUBMITTED event is enabled (e.g., use the existing disabled-events
check or an isEventEnabled('USER_SURVEY_SUBMITTED') helper in the
PostHogTelemetryProvider class to gate the call); keep the existing
normalizedResponses and this.posthog null checks and preserve the try/catch
around people.set.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 54318a55-5fd5-4e86-ba83-261a572a64a7

📥 Commits

Reviewing files that changed from the base of the PR and between 2536397 and 5644b56.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • global.d.ts
  • package.json
  • pnpm-workspace.yaml
  • src/platform/remoteConfig/types.ts
  • src/platform/telemetry/initTelemetry.ts
  • src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • src/platform/telemetry/initTelemetry.ts

@robinjhuang robinjhuang force-pushed the feat/posthog-telemetry-provider branch from 5644b56 to 8ebc719 Compare March 5, 2026 03:46
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Mar 5, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts (2)

376-377: ⚠️ Potential issue | 🟠 Major

Preserve page-view metadata in trackPageView.
At Line 376, the method drops optional metadata passed by callers and diverges
from the broader telemetry contract behavior.

💡 Proposed fix
 import type {
   AuthMetadata,
   EnterLinearMetadata,
   ExecutionErrorMetadata,
   ExecutionSuccessMetadata,
   HelpCenterClosedMetadata,
   HelpCenterOpenedMetadata,
   HelpResourceClickedMetadata,
   NodeSearchMetadata,
   NodeSearchResultMetadata,
+  PageViewMetadata,
   PageVisibilityMetadata,
   SettingChangedMetadata,
   SubscriptionMetadata,
   SurveyResponses,
@@
-  trackPageView(pageName: string): void {
-    this.captureRaw(TelemetryEvents.PAGE_VIEW, { page_name: pageName })
+  trackPageView(pageName: string, properties?: PageViewMetadata): void {
+    this.captureRaw(TelemetryEvents.PAGE_VIEW, {
+      page_name: pageName,
+      ...(properties ?? {})
+    })
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts` around
lines 376 - 377, The trackPageView method currently only accepts pageName and
calls this.captureRaw(TelemetryEvents.PAGE_VIEW, { page_name: pageName }),
dropping optional metadata; update trackPageView to accept an optional metadata
parameter (e.g., metadata?: Record<string, any>) and merge it with the page_name
field before calling this.captureRaw so that additional caller-provided
page-view properties are preserved; ensure the signature change and the merge
happen in PostHogTelemetryProvider.trackPageView and that the merged object is
passed to this.captureRaw with TelemetryEvents.PAGE_VIEW.

269-275: ⚠️ Potential issue | 🟠 Major

Respect disabled-event opt-out before calling people.set.
At Line 269, survey profile updates are still sent even when
USER_SURVEY_SUBMITTED is disabled, which bypasses telemetry opt-out.

💡 Proposed fix
-    if (stage === 'submitted' && normalizedResponses && this.posthog) {
+    if (
+      stage === 'submitted' &&
+      normalizedResponses &&
+      this.posthog &&
+      this.isEnabled &&
+      !this.disabledEvents.has(TelemetryEvents.USER_SURVEY_SUBMITTED)
+    ) {
       try {
         this.posthog.people.set(normalizedResponses)
       } catch (error) {
         console.error('Failed to set PostHog user properties:', error)
       }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts` around
lines 269 - 275, The survey user-profile update block currently calls
this.posthog.people.set(...) regardless of the USER_SURVEY_SUBMITTED opt-out;
change it to first check the telemetry opt-out setting and only call people.set
when the event is enabled (e.g. verify a flag or method like
isEventEnabled('USER_SURVEY_SUBMITTED') on your telemetry/config object), and
skip the set (and any related work) when the event is disabled; ensure you still
guard on this.posthog, stage === 'submitted', and normalizedResponses before
invoking people.set and keep the existing try/catch error logging around the
call.
🧹 Nitpick comments (1)
src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.test.ts (1)

219-230: Add a regression case for page-view metadata passthrough.
Current test only asserts page_name; it won’t catch dropped optional metadata
(e.g. path) in provider implementations.

💡 Suggested test addition
   describe('page view', () => {
     it('captures page view with page_name property', async () => {
       const provider = createProvider()
       await vi.dynamicImportSettled()

       provider.trackPageView('workflow_editor')

       expect(hoisted.mockCapture).toHaveBeenCalledWith(
         TelemetryEvents.PAGE_VIEW,
         { page_name: 'workflow_editor' }
       )
     })
+
+    it('captures page view with additional metadata', async () => {
+      const provider = createProvider()
+      await vi.dynamicImportSettled()
+
+      provider.trackPageView('workflow_editor', { path: 'https://app.test/wf' })
+
+      expect(hoisted.mockCapture).toHaveBeenCalledWith(
+        TelemetryEvents.PAGE_VIEW,
+        { page_name: 'workflow_editor', path: 'https://app.test/wf' }
+      )
+    })
   })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.test.ts`
around lines 219 - 230, The test in PostHogTelemetryProvider.test.ts only
asserts page_name and misses optional metadata; update the 'page view' spec that
calls provider.trackPageView to include optional metadata (e.g., pass { path:
'/some/path' } or combine with page_name) and add an expectation that
hoisted.mockCapture was called with TelemetryEvents.PAGE_VIEW and the full
metadata object (ensuring that provider.trackPageView and the provider
implementation pass through optional fields like path). Target the test that
invokes provider.trackPageView and the assertion using
hoisted.mockCapture/TelmetryEvents.PAGE_VIEW to verify metadata passthrough.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts`:
- Around line 376-377: The trackPageView method currently only accepts pageName
and calls this.captureRaw(TelemetryEvents.PAGE_VIEW, { page_name: pageName }),
dropping optional metadata; update trackPageView to accept an optional metadata
parameter (e.g., metadata?: Record<string, any>) and merge it with the page_name
field before calling this.captureRaw so that additional caller-provided
page-view properties are preserved; ensure the signature change and the merge
happen in PostHogTelemetryProvider.trackPageView and that the merged object is
passed to this.captureRaw with TelemetryEvents.PAGE_VIEW.
- Around line 269-275: The survey user-profile update block currently calls
this.posthog.people.set(...) regardless of the USER_SURVEY_SUBMITTED opt-out;
change it to first check the telemetry opt-out setting and only call people.set
when the event is enabled (e.g. verify a flag or method like
isEventEnabled('USER_SURVEY_SUBMITTED') on your telemetry/config object), and
skip the set (and any related work) when the event is disabled; ensure you still
guard on this.posthog, stage === 'submitted', and normalizedResponses before
invoking people.set and keep the existing try/catch error logging around the
call.

---

Nitpick comments:
In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.test.ts`:
- Around line 219-230: The test in PostHogTelemetryProvider.test.ts only asserts
page_name and misses optional metadata; update the 'page view' spec that calls
provider.trackPageView to include optional metadata (e.g., pass { path:
'/some/path' } or combine with page_name) and add an expectation that
hoisted.mockCapture was called with TelemetryEvents.PAGE_VIEW and the full
metadata object (ensuring that provider.trackPageView and the provider
implementation pass through optional fields like path). Target the test that
invokes provider.trackPageView and the assertion using
hoisted.mockCapture/TelmetryEvents.PAGE_VIEW to verify metadata passthrough.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 92f96981-f4b3-4add-9b6c-7b05ec9d6100

📥 Commits

Reviewing files that changed from the base of the PR and between 5644b56 and 8ebc719.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • global.d.ts
  • package.json
  • pnpm-workspace.yaml
  • src/platform/remoteConfig/types.ts
  • src/platform/telemetry/initTelemetry.ts
  • src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.test.ts
  • src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • pnpm-workspace.yaml
  • src/platform/remoteConfig/types.ts
  • global.d.ts

@robinjhuang robinjhuang force-pushed the feat/posthog-telemetry-provider branch from 8ebc719 to a6b1b3e Compare March 5, 2026 03:51
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts (1)

77-87: Minor: Redundant configureDisabledEvents call on initialization.

configureDisabledEvents is called explicitly on lines 78-80, then the watch with { immediate: true } calls it again immediately on line 84. Consider removing the explicit call since the immediate watch handles it.

Proposed fix
   constructor() {
-    this.configureDisabledEvents(
-      (window.__CONFIG__ as Partial<RemoteConfig> | undefined) ?? null
-    )
     watch(
       remoteConfig,
       (config) => {
         this.configureDisabledEvents(config)
       },
       { immediate: true }
     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts` around
lines 77 - 87, In the constructor of PostHogTelemetryProvider remove the
redundant explicit call to configureDisabledEvents((window.__CONFIG__ as
Partial<RemoteConfig> | undefined) ?? null) and rely on the existing
watch(remoteConfig, (config) => { this.configureDisabledEvents(config) }, {
immediate: true }) to invoke configureDisabledEvents on init; leave the watch
and its immediate option unchanged so initial and subsequent config updates
still call configureDisabledEvents.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts`:
- Around line 77-87: In the constructor of PostHogTelemetryProvider remove the
redundant explicit call to configureDisabledEvents((window.__CONFIG__ as
Partial<RemoteConfig> | undefined) ?? null) and rely on the existing
watch(remoteConfig, (config) => { this.configureDisabledEvents(config) }, {
immediate: true }) to invoke configureDisabledEvents on init; leave the watch
and its immediate option unchanged so initial and subsequent config updates
still call configureDisabledEvents.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a97c9d6f-4b33-41b6-a45e-7a1b6120f6d4

📥 Commits

Reviewing files that changed from the base of the PR and between 8ebc719 and a6b1b3e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • .github/workflows/ci-oss-assets-validation.yaml
  • global.d.ts
  • package.json
  • pnpm-workspace.yaml
  • src/platform/remoteConfig/types.ts
  • src/platform/telemetry/initTelemetry.ts
  • src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.test.ts
  • src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • global.d.ts
  • package.json
  • src/platform/telemetry/initTelemetry.ts
  • pnpm-workspace.yaml
  • src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.test.ts
  • src/platform/remoteConfig/types.ts

@robinjhuang
Copy link
Member Author

@benceruleanlu is this a flaky test? Or a bug I introduced

image

@benceruleanlu
Copy link
Member

@benceruleanlu is this a flaky test? Or a bug I introduced

image

Flaky. Snapshot tests in FE have been the biggest piece of tech debt for months.

Copy link
Contributor

@christian-byrne christian-byrne left a comment

Choose a reason for hiding this comment

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

Looks good, can you add a query term to ensure it never gets included in the OSS distribution? Just 1-2 lines in this file https://github.com/Comfy-Org/ComfyUI_frontend/blob/main/.github/workflows/ci-dist-telemetry-scan.yaml.

@benceruleanlu benceruleanlu removed their assignment Mar 5, 2026
@robinjhuang robinjhuang force-pushed the feat/posthog-telemetry-provider branch from a6b1b3e to 30bfa65 Compare March 5, 2026 04:48
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts (2)

269-275: ⚠️ Potential issue | 🟠 Major

Guard survey profile updates behind the disabled-event check.

At Line 269, people.set(...) still runs for submitted surveys even when USER_SURVEY_SUBMITTED is disabled, which bypasses telemetry opt-out for that event.

💡 Proposed fix
-    if (stage === 'submitted' && normalizedResponses && this.posthog) {
+    if (
+      stage === 'submitted' &&
+      normalizedResponses &&
+      this.posthog &&
+      this.isEnabled &&
+      !this.disabledEvents.has(TelemetryEvents.USER_SURVEY_SUBMITTED)
+    ) {
       try {
         this.posthog.people.set(normalizedResponses)
       } catch (error) {
         console.error('Failed to set PostHog user properties:', error)
       }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts` around
lines 269 - 275, When handling survey submission in PostHogTelemetryProvider,
ensure you only call this.posthog.people.set(normalizedResponses) for stage ===
'submitted' if the USER_SURVEY_SUBMITTED event is enabled; add the same
disabled-event check used elsewhere (the feature/telemetry event enabling guard)
before invoking this.posthog.people.set to honor telemetry opt-out for submitted
surveys and leave normalizedResponses and this.posthog null-checks intact.

376-377: ⚠️ Potential issue | 🟠 Major

Preserve caller-provided page-view metadata.

At Line 376, trackPageView drops optional metadata passed by callers and only forwards page_name, so fields like path are lost.

💡 Proposed fix
 import type {
   AuthMetadata,
   EnterLinearMetadata,
   ExecutionErrorMetadata,
   ExecutionSuccessMetadata,
   HelpCenterClosedMetadata,
   HelpCenterOpenedMetadata,
   HelpResourceClickedMetadata,
   NodeSearchMetadata,
   NodeSearchResultMetadata,
+  PageViewMetadata,
   PageVisibilityMetadata,
   SettingChangedMetadata,
   SubscriptionMetadata,
   SurveyResponses,
   TabCountMetadata,
@@
-  trackPageView(pageName: string): void {
-    this.captureRaw(TelemetryEvents.PAGE_VIEW, { page_name: pageName })
+  trackPageView(pageName: string, properties?: PageViewMetadata): void {
+    this.captureRaw(TelemetryEvents.PAGE_VIEW, {
+      page_name: pageName,
+      ...(properties ?? {})
+    })
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts` around
lines 376 - 377, trackPageView currently overwrites any caller-provided metadata
by only sending { page_name: pageName } to captureRaw; update the trackPageView
method to accept an optional metadata object parameter and merge the caller
metadata with { page_name: pageName } before calling
this.captureRaw(TelemetryEvents.PAGE_VIEW,...), so fields like path are
preserved; locate the trackPageView function in PostHogTelemetryProvider and
ensure the merged payload is passed to captureRaw rather than replacing caller
metadata.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts`:
- Around line 269-275: When handling survey submission in
PostHogTelemetryProvider, ensure you only call
this.posthog.people.set(normalizedResponses) for stage === 'submitted' if the
USER_SURVEY_SUBMITTED event is enabled; add the same disabled-event check used
elsewhere (the feature/telemetry event enabling guard) before invoking
this.posthog.people.set to honor telemetry opt-out for submitted surveys and
leave normalizedResponses and this.posthog null-checks intact.
- Around line 376-377: trackPageView currently overwrites any caller-provided
metadata by only sending { page_name: pageName } to captureRaw; update the
trackPageView method to accept an optional metadata object parameter and merge
the caller metadata with { page_name: pageName } before calling
this.captureRaw(TelemetryEvents.PAGE_VIEW,...), so fields like path are
preserved; locate the trackPageView function in PostHogTelemetryProvider and
ensure the merged payload is passed to captureRaw rather than replacing caller
metadata.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 54f5a361-e8ef-40f6-9296-c3081edfcf67

📥 Commits

Reviewing files that changed from the base of the PR and between a6b1b3e and 30bfa65.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • .github/workflows/ci-dist-telemetry-scan.yaml
  • .github/workflows/ci-oss-assets-validation.yaml
  • global.d.ts
  • package.json
  • pnpm-workspace.yaml
  • src/platform/remoteConfig/types.ts
  • src/platform/telemetry/initTelemetry.ts
  • src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.test.ts
  • src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/platform/remoteConfig/types.ts
  • pnpm-workspace.yaml
  • package.json
  • global.d.ts
  • .github/workflows/ci-oss-assets-validation.yaml

@robinjhuang robinjhuang force-pushed the feat/posthog-telemetry-provider branch from 30bfa65 to 6b2d886 Compare March 5, 2026 06:02
- Add posthog-js dependency
- Create PostHogTelemetryProvider following MixpanelTelemetryProvider pattern
- Register provider in initTelemetry.ts
- Read posthog_project_token and posthog_api_host from window.__CONFIG__ (runtime config from /features endpoint)
- Extract getExecutionContext to shared utility used by both Mixpanel and PostHog
- Add PostHog to dist telemetry scan and license clarifications
- Tree-shaken away in OSS builds (verified)
@robinjhuang robinjhuang force-pushed the feat/posthog-telemetry-provider branch from 6b2d886 to 7aff5f3 Compare March 5, 2026 06:25
Copy link
Contributor

@christian-byrne christian-byrne left a comment

Choose a reason for hiding this comment

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

LGTM!

@christian-byrne christian-byrne merged commit 6c2680f into main Mar 6, 2026
34 checks passed
@christian-byrne christian-byrne deleted the feat/posthog-telemetry-provider branch March 6, 2026 00:19
@robinjhuang robinjhuang added the needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch label Mar 6, 2026
@github-actions
Copy link

github-actions bot commented Mar 6, 2026

⚠️ Backport to cloud/1.40 failed

Reason: Merge conflicts detected during cherry-pick of 6c2680f

📄 Conflicting files
.github/workflows/ci-oss-assets-validation.yaml
pnpm-lock.yaml
🤖 Prompt for AI Agents
Backport PR #9409 (https://github.com/Comfy-Org/ComfyUI_frontend/pull/9409) to cloud/1.40.
Cherry-pick merge commit 6c2680f0ba31bf24bca51f63dc87b437869f4ad7 onto new branch
backport-9409-to-cloud-1.40 from origin/cloud/1.40.
Resolve conflicts in: .github/workflows/ci-oss-assets-validation.yaml pnpm-lock.yaml .
For test snapshots (browser_tests/**/*-snapshots/), accept PR version if
changed in original PR, else keep target. For package.json versions, keep
target branch. For pnpm-lock.yaml, regenerate with pnpm install.
Ask user for non-obvious conflicts.
Create PR titled "[backport cloud/1.40] <original title>" with label "backport".
See .github/workflows/pr-backport.yaml for workflow details.

cc @robinjhuang

robinjhuang added a commit that referenced this pull request Mar 6, 2026
christian-byrne pushed a commit that referenced this pull request Mar 6, 2026
Backport of #9409 to `cloud/1.40`.

Automatically created by manual backport workflow.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9457-backport-cloud-1-40-feat-Add-PostHog-telemetry-provider-31b6d73d365081ac9eb4d596daafddf3)
by [Unito](https://www.unito.io)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport Backporting a PR onto a release candidate cloud/1.40 Backport PRs for cloud 1.40 needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants