Skip to content

feat(telemetry): export reliability by browser and device - #1829

Merged
magic-peach merged 6 commits into
mainfrom
feat/export-reliability-telemetry
Nov 3, 2026
Merged

magic-peach merged 6 commits into
mainfrom
feat/export-reliability-telemetry

Conversation

@magic-peach

@magic-peach magic-peach commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Targets main and includes #1827 and #1828 (they are ancestors of this branch, so a merge commit closes them too).

What this adds

Export reliability by browser and device, from Datadog RUM.

Each export sends export_started, then exactly one of export_succeeded, export_failed or export_cancelled. The events carry bucketed context: format, resolution, input size, clip length, whether there's text, music or an image overlay, engine (multi-/single-threaded), stage (engine start / encoding), failure category and retry state. Browser, OS and device type come from RUM itself. Engine loads report ffmpeg_load_success / ffmpeg_load_failure once per worker.

  • src/lib/exportTelemetry.ts: ExportAttempt (one outcome per attempt; a cancel followed by a late rejection counts once) and startEngineLoad.
  • src/lib/telemetry.ts:
    • Fails closed: localhost, LAN and automated browsers never report, and production requires the host's deploy context.
    • beforeSend scrubs file names, captions, local paths and blob: URLs.
    • Handled failures use a [reframe:handled] prefix so RUM doesn't count them twice.
  • next.config.ts: bakes Netlify's CONTEXT / Vercel's VERCEL_ENV into NEXT_PUBLIC_DEPLOY_CONTEXT. Without this, production would stop reporting.
  • src/lib/ffmpeg.ts, ffmpeg.worker.ts: the worker reports which engine loaded; getEngineMode() is added.
  • src/hooks/useVideoEditor.ts: wires the attempt into export, cancel and retry. Messages users see are unchanged.
  • docs/DATADOG.md: event schema, privacy rules, query syntax (custom actions are @action.target.name, not @action.name), facet setup and import steps.
  • docs/datadog/export-reliability.dashboard.json: an importable dashboard (17 widgets) with success rate overall and by browser, device, OS, format, resolution and engine, each next to its sample size; GIF exports on mobile; failure categories by browser and device; retry recovery.

Privacy

No file names, contents, captions, paths or exact values are sent; a test fails if any property outside the allowed list appears. Session replay stays disabled.

Verified on the deploy preview (2026-11-03)

  • The preview is cross-origin isolated (COOP/COEP present), RUM starts with env: preview, and NEXT_PUBLIC_DEPLOY_CONTEXT is baked in as deploy-preview.
  • A real export in Chrome on macOS sent export_started (format, resolution, buckets), ffmpeg_load_success (engine: multi, first load) and one export_cancelled (stage: encode), all visible through the Datadog RUM API with the expected @context.* paths, browser, OS and device.
  • Not observed yet: export_succeeded / export_failed from a real browser. See the note below on the clips I could generate.

In Datadog now

  • Dashboard 2tw-pge-qkk, created from docs/datadog/export-reliability.dashboard.json.
  • Four notify-only monitors (email) on env:production: failed exports, engine load failures, missing isolation, frontend error spike. IDs are in docs/DATADOG.md.

Existing bug found while testing (not caused by this PR)

Browser-recorded clips (MediaRecorder WebM/MP4, e.g. screen recordings) have no duration in their metadata. getVideoDuration in src/lib/ffmpeg.ts returns Infinity, the args get -t Infinity, and the export hangs at 100% indefinitely. The same file hangs on production (main). The stall detector doesn't catch it. To be fixed separately.

Checks run locally

  • 26 test files, 296 tests pass, including exportTelemetry.hook.test.ts (failure → retry, cancel, engine-load failure) and DatadogInit on local, production and preview hosts.
  • Typecheck, lint, the safety check and the build (with NEXT_PUBLIC_DATADOG_ENV=off) pass.

magic-peach and others added 5 commits October 23, 2026 23:38
- claude-manager.yml (claude-pr-review): skip draft PRs
  (`github.event.pull_request.draft == false`), keep the event and author
  restrictions, rename the step, and replace "squash-merge the PR" with a
  comment that the PR is ready for a maintainer. The prompt now forbids
  merging, approving, enabling auto-merge, pushing and marking drafts
  ready. Permissions unchanged (contents: read).
- CLAUDE.md: PR Automation no longer merges; automatic conflict resolution
  (git merge + push to the PR branch) becomes guidance in a comment;
  General Rules no longer list "merge PRs".
- scripts/ci/check-pr-automation.mjs: fails on merge commands/APIs in any
  workflow, contents: write / write-all in a Claude job, a PR-writing
  Claude job without a draft guard, and affirmative merge/push
  instructions in prompts or CLAUDE.md. Run in lint.yml; unit-tested with
  passing and failing fixtures (it flags all six items on main today).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The previous commit rewrote the file with LF; the net change against main is
now only the two added lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #1810, #1822, #1823 and #1825 so this PR applies to current main.
No conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t-config-next

#1823 bumped next to 16.4.1 in package.json only, and react-dom had stayed
at 19.2.8 while react is 19.3.0, so bun.lock no longer matched package.json:
- `bun install --frozen-lockfile` failed;
- the lockfile still pinned next 16.3.4 (critical advisories), while plain
  installs got 16.4.1;
- a plain install paired react 19.3.0 with react-dom 19.2.8, so 5 test files
  failed to load with "Incompatible React versions".

react-dom 19.2.8 → 19.3.0 and eslint-config-next 16.3.4 → 16.4.1 (matching
next); bun.lock regenerated (42 entries, Next.js packages and the sharp patch
Next requires; no majors).

Verified: frozen install, 20/20 test files and 241 tests (was 5 files
failing), typecheck, lint, production build. bun audit: next now has 0
advisories; the remaining critical is Storybook's dev server (dev-only),
handled in the security pipeline work.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Report one outcome per export attempt (export_started, then exactly one of
export_succeeded / export_failed / export_cancelled) with bucketed context:
format, resolution, input size, clip length, overlays, engine, stage, failure
category and retry state. Browser, OS and device type come from RUM itself.

- exportTelemetry.ts: ExportAttempt and per-worker engine-load events
- telemetry.ts: fail-closed env resolution (local hosts and automated
  browsers never report; production needs the deploy context), scrubbing
  of file names, captions and paths in beforeSend, handled-error prefix
- next.config.ts: bake the host's deploy context into
  NEXT_PUBLIC_DEPLOY_CONTEXT so production keeps reporting
- docs/DATADOG.md and an importable dashboard definition (untested import;
  no Datadog API access). Queries use @action.target.name.

Session replay stays disabled. User-facing error messages are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

👋 Thanks for your PR, @magic-peach!

Welcome to Reframe — a browser-based video editor built for everyone 🎬

What happens next

  1. 🤖 Automated checks — build & TypeScript typecheck will run automatically
  2. ✅ Vercel preview — a preview deployment will be created (requires maintainer authorization for fork PRs)
  3. 👀 Code review — a maintainer will review your changes
  4. 🚀 Merge — once approved, your PR will be merged!

Quick checklist

  • PR title follows Conventional Commits (e.g. feat: add dark mode)
  • Linked the issue this PR closes (e.g. Closes #123)
  • Tested the changes locally (bun run dev)
  • Build passes (bun run build)

Useful links

Happy coding! 🎉

@github-actions github-actions Bot added level:advanced Advanced level - 55 pts type:docs Documentation type:testing Testing labels Nov 3, 2026
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ PR Format Issues — @magic-peach

Please fix the following before your PR can be reviewed:

  • ⚠️ No linked issue found. Add Closes #<issue-number> to your PR description.

Push new commits after fixing — this comment will update automatically.

📖 CONTRIBUTING.md

@magic-peach
magic-peach changed the base branch from fix/lockfile-sync to main November 3, 2026 06:15
@magic-peach magic-peach closed this Nov 3, 2026
@magic-peach magic-peach reopened this Nov 3, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@netlify

netlify Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for reframe-os ready!

Name Link
🔨 Latest commit c3f79a9
🔍 Latest deploy log https://app.netlify.com/projects/reframe-os/deploys/6ae97e9d4739f0be3d4dfd3b
😎 Deploy Preview https://deploy-preview-1829--reframe-os.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@magic-peach
magic-peach marked this pull request as ready for review November 3, 2026 06:55
@magic-peach
magic-peach merged commit 4555bde into main Nov 3, 2026
20 of 24 checks passed
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Claude encountered an error —— View job


I'll analyze this and get back to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

level:advanced Advanced level - 55 pts type:docs Documentation type:testing Testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant