Skip to content

feat(logging): structured wide events and console migration#120

Merged
walterlow merged 2 commits intomainfrom
develop
Mar 15, 2026
Merged

feat(logging): structured wide events and console migration#120
walterlow merged 2 commits intomainfrom
develop

Conversation

@walterlow
Copy link
Copy Markdown
Owner

@walterlow walterlow commented Mar 15, 2026

Summary

  • Enhanced src/shared/logging/logger.ts with wide event support: startEvent(), event(), and createOperationId() for accumulating context across multi-step operations and emitting one structured event at completion
  • Consolidated scattered log calls in export (use-client-render.ts) and media import (media-import-actions.ts) flows into single wide events with business context (project ID, codec, resolution, item counts, duration)
  • Migrated ~55 raw console.warn/console.error calls across 30 files to use createLogger, leaving only logger internals and the debug panel using console directly

Test plan

  • Verify dev server starts without errors (npm run dev)
  • Trigger an export and confirm a single structured [Export] render event appears in console with full context
  • Import media files and confirm a single [MediaImport] import event appears with counts
  • Verify auto-save emits [AutoSave] save event with duration
  • Confirm production build succeeds (npm run build) — no TDZ issues from logger changes
  • Verify debug panel still outputs directly to console as expected

Summary by CodeRabbit

  • Refactor

    • Adjusted the “soft” animation curve for more consistent keyframe easing.
  • Chores

    • Centralized and improved internal logging and telemetry across many components to enhance diagnostics and error reporting (no user-facing behavior changes).

DEFAULT_BEZIER_POINTS from @/types/keyframe was used at module scope
in BEZIER_PRESETS, causing a temporal dead zone error when production
chunk ordering evaluates keyframe-graph-panel before keyframe.ts.
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
freecut Ready Ready Preview, Comment Mar 15, 2026 6:49am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 15, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Widespread introduction of a structured logging/events system: a new wide-event logging API was added, many modules replaced direct console calls with the centralized logger (and event usage), media import/resolution logic was refactored for deduplication and evented operations, plus one small bezier preset tweak.

Changes

Cohort / File(s) Summary
Logging core API
src/shared/logging/logger.ts
Added EventData/WideEvent API, startEvent/event methods, and createOperationId; implements structured, long-lived telemetry events.
Mass logger integration
src/components/error-boundary.tsx, src/domain/timeline/transitions/registry.ts, src/features/composition-runtime/components/item.tsx, src/features/composition-runtime/components/video-content.tsx, src/features/editor/components/media-sidebar.tsx, src/features/editor/components/unsaved-changes-dialog.tsx, src/features/editor/hooks/use-auto-save.ts, src/features/export/hooks/use-client-render.ts, src/features/export/utils/client-render-engine.ts, src/features/media-library/workers/media-processor.worker.ts, src/features/media-library/workers/opfs-worker.ts, src/features/player/clock/Clock.ts, src/features/player/player-emitter.ts, src/features/player/video/VideoSourcePool.ts, src/features/preview/components/video-preview.tsx, src/features/project-bundle/services/bundle-export-service.ts, src/features/project-bundle/services/bundle-import-service.ts, src/features/projects/hooks/use-project-thumbnail.ts, src/features/timeline/components/clip-filmstrip/index.tsx, src/features/timeline/components/clip-waveform/index.tsx, src/features/timeline/components/timeline.tsx, src/features/timeline/hooks/use-timeline-drag.ts, src/features/timeline/hooks/use-timeline-zoom.ts, src/features/timeline/utils/collision-utils.ts, src/lib/gpu-compositor/compositor-pipeline.ts, src/lib/gpu-effects/effects-pipeline.ts, src/lib/gpu-transitions/transition-pipeline.ts, src/shared/typography/font-loader.ts
Replaced numerous console.* uses with centralized logger calls (logger.warn/error/info) and instantiated module-scoped loggers. One file (player-emitter.ts) also added new exported event payload types and extended PlayerStateEventMap.
Media import & processing
src/features/media-library/stores/media-import-actions.ts, src/features/media-library/utils/media-resolver.ts
Refactored import result handling: added ImportedMetadata type, processImportResults and showImportNotifications helpers, centralized event-based logging via createOperationId/startEvent, batching of notifications; added pendingRequests deduplication and enhanced FileAccessError handling marking broken media.
Client render telemetry
src/features/export/hooks/use-client-render.ts
Replaced ad-hoc logging with event-based telemetry: createOperationId and startEvent used to record render config, media/composition metadata, outcomes, and fallback paths; no control-flow changes.
Small config tweak
src/features/timeline/components/keyframe-graph-panel.tsx
Replaced reference to DEFAULT_BEZIER_POINTS for the 'soft' preset with explicit bezier coordinates {x1:0.42,y1:0,x2:0.58,y2:1}.

Sequence Diagram(s)

(Skipped — changes are primarily logging, refactors, and internal batching without a new multi-component sequential runtime flow that requires visualization.)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through logs with gentle care,
Replaced console footprints everywhere,
Events that hum with a tidy tune,
Imports batched beneath the moon,
A rabbit cheers: clearer traces, everywhere! 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'feat(logging): structured wide events and console migration' describes logging refactoring and event system expansion, but the PR summary indicates the primary objective is fixing a temporal dead zone (TDZ) crash in production builds, with logging changes as secondary modifications. Retitle to reflect the primary fix: 'fix(bezier): avoid TDZ crash by inlining DEFAULT_BEZIER_POINTS' or similar, noting that logging refactoring is a secondary change.
Docstring Coverage ⚠️ Warning Docstring coverage is 56.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 15, 2026

Greptile Summary

This single-line fix inlines the DEFAULT_BEZIER_POINTS values directly into the module-scope BEZIER_PRESETS constant to prevent a Temporal Dead Zone (TDZ) crash (Cannot access '_t' before initialization) that occurs in production builds when Vite's chunk ordering evaluates keyframe-graph-panel.tsx before keyframe.ts.

  • The inlined values { x1: 0.42, y1: 0, x2: 0.58, y2: 1 } exactly match the canonical DEFAULT_BEZIER_POINTS in src/types/keyframe.ts
  • The DEFAULT_BEZIER_POINTS import is retained because it is still used at runtime (in buildEasingConfig, useState initializers, and useMemo callbacks — none of which trigger TDZ since they execute lazily)
  • Only the module-scope const initializer was affected by TDZ, making this a targeted and correct fix

Confidence Score: 5/5

  • This PR is safe to merge — it's a minimal, correct fix for a production-only crash with no behavioral changes.
  • The change is a single-line value inlining that exactly matches the source constant. The fix is well-targeted: only the module-scope initializer that triggers TDZ is modified, while all other usages of the import (which execute lazily at runtime) are left untouched. No logic, behavior, or API surface changes.
  • No files require special attention.

Important Files Changed

Filename Overview
src/features/timeline/components/keyframe-graph-panel.tsx Inlines DEFAULT_BEZIER_POINTS values in module-scope BEZIER_PRESETS constant to fix TDZ crash in production builds. Values match the source of truth exactly; import is retained for other runtime usages.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Vite production build"] --> B{"Chunk ordering"}
    B -->|"keyframe-graph-panel.tsx evaluated first"| C["BEZIER_PRESETS module-scope init"]
    C --> D{"References DEFAULT_BEZIER_POINTS?"}
    D -->|"Before fix: yes (import)"| E["TDZ Error: Cannot access '_t'"]
    D -->|"After fix: no (inlined)"| F["Initializes successfully"]
    F --> G["keyframe.ts evaluated later"]
    G --> H["DEFAULT_BEZIER_POINTS available for runtime usages"]
Loading

Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/features/timeline/components/keyframe-graph-panel.tsx
Line: 105

Comment:
**Inlined values may drift from source of truth**

The values `{ x1: 0.42, y1: 0, x2: 0.58, y2: 1 }` are correct today (matching `DEFAULT_BEZIER_POINTS` in `keyframe.ts:163-168`), but since the "Soft" preset is semantically the default bezier curve, a future change to `DEFAULT_BEZIER_POINTS` won't automatically propagate here. Consider adding a comment referencing the source constant so a future maintainer knows to keep them in sync, e.g.:

```suggestion
  { value: 'soft', label: 'Soft', points: { x1: 0.42, y1: 0, x2: 0.58, y2: 1 } }, // must match DEFAULT_BEZIER_POINTS
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 5dc06d4

];
const BEZIER_PRESETS = [
{ value: 'soft', label: 'Soft', points: DEFAULT_BEZIER_POINTS },
{ value: 'soft', label: 'Soft', points: { x1: 0.42, y1: 0, x2: 0.58, y2: 1 } },
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.

Inlined values may drift from source of truth

The values { x1: 0.42, y1: 0, x2: 0.58, y2: 1 } are correct today (matching DEFAULT_BEZIER_POINTS in keyframe.ts:163-168), but since the "Soft" preset is semantically the default bezier curve, a future change to DEFAULT_BEZIER_POINTS won't automatically propagate here. Consider adding a comment referencing the source constant so a future maintainer knows to keep them in sync, e.g.:

Suggested change
{ value: 'soft', label: 'Soft', points: { x1: 0.42, y1: 0, x2: 0.58, y2: 1 } },
{ value: 'soft', label: 'Soft', points: { x1: 0.42, y1: 0, x2: 0.58, y2: 1 } }, // must match DEFAULT_BEZIER_POINTS
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/features/timeline/components/keyframe-graph-panel.tsx
Line: 105

Comment:
**Inlined values may drift from source of truth**

The values `{ x1: 0.42, y1: 0, x2: 0.58, y2: 1 }` are correct today (matching `DEFAULT_BEZIER_POINTS` in `keyframe.ts:163-168`), but since the "Soft" preset is semantically the default bezier curve, a future change to `DEFAULT_BEZIER_POINTS` won't automatically propagate here. Consider adding a comment referencing the source constant so a future maintainer knows to keep them in sync, e.g.:

```suggestion
  { value: 'soft', label: 'Soft', points: { x1: 0.42, y1: 0, x2: 0.58, y2: 1 } }, // must match DEFAULT_BEZIER_POINTS
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code Fix in Codex

Copy link
Copy Markdown
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/features/timeline/components/keyframe-graph-panel.tsx (1)

104-105: Consider documenting why this literal is intentionally inlined.

A brief comment here would help prevent future “cleanup” refactors from reintroducing the module-evaluation TDZ path.

Optional patch
 const BEZIER_PRESETS = [
+  // Intentionally inlined to avoid module-scope TDZ from imported constants in production chunk ordering.
   { value: 'soft', label: 'Soft', points: { x1: 0.42, y1: 0, x2: 0.58, y2: 1 } },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/timeline/components/keyframe-graph-panel.tsx` around lines 104 -
105, The BEZIER_PRESETS literal is intentionally inlined to avoid a
module-evaluation TDZ path; add a concise comment above the BEZIER_PRESETS
declaration explaining that it must remain an inline literal (not extracted to
another module or computed at import time) to prevent dead temporal zone
initialization issues and to reference the specific usage in KeyframeGraphPanel
or functions that rely on its immediate availability; keep the comment short,
mention "TDZ/module-evaluation" and the rationale so future maintainers don't
refactor it away.
🤖 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/features/timeline/components/keyframe-graph-panel.tsx`:
- Around line 104-105: The BEZIER_PRESETS literal is intentionally inlined to
avoid a module-evaluation TDZ path; add a concise comment above the
BEZIER_PRESETS declaration explaining that it must remain an inline literal (not
extracted to another module or computed at import time) to prevent dead temporal
zone initialization issues and to reference the specific usage in
KeyframeGraphPanel or functions that rely on its immediate availability; keep
the comment short, mention "TDZ/module-evaluation" and the rationale so future
maintainers don't refactor it away.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4dfac978-3dc1-4ba1-b978-262883d16c60

📥 Commits

Reviewing files that changed from the base of the PR and between 6041146 and 5dc06d4.

📒 Files selected for processing (1)
  • src/features/timeline/components/keyframe-graph-panel.tsx

…o structured logger

Enhance logger with startEvent/event methods for accumulating context
across multi-step operations (export, import, auto-save) and emitting
one structured event at completion. Add createOperationId() for
correlating log entries. Migrate all raw console.warn/error calls
(~55 across 30 files) to use createLogger, leaving only logger
internals and the debug panel using console directly.
@walterlow walterlow changed the title Fix TDZ crash in production build feat(logging): structured wide events and console migration Mar 15, 2026
@walterlow walterlow merged commit aa3c375 into main Mar 15, 2026
3 of 4 checks passed
Comment on lines +431 to +433
event.set('outcome', 'cancelled');
event.set('duration_ms', Date.now());
log.event('render', { opId, outcome: 'cancelled' });
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Incorrect handling of cancelled export event. Line 432 sets duration_ms to Date.now() (absolute timestamp) instead of elapsed time. Line 433 calls log.event() with a minimal new object, discarding all accumulated context (codec, resolution, items, tracks, etc.) collected throughout the export.

Fix: Remove lines 431-433 and emit the accumulated event:

event.set('outcome', 'cancelled');
event.success({ outcome: 'cancelled' });

Or add a cancel() method to WideEvent interface that properly calculates duration and emits all accumulated data.

Suggested change
event.set('outcome', 'cancelled');
event.set('duration_ms', Date.now());
log.event('render', { opId, outcome: 'cancelled' });
event.set('outcome', 'cancelled');
event.success({ outcome: 'cancelled' });

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Comment on lines +220 to +221
event.set('outcome', 'cancelled');
logger.event('import', { opId, outcome: 'cancelled' });
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Incorrect handling of cancelled import event. Line 221 calls logger.event() with a minimal new object containing only opId and outcome, discarding all accumulated context (source, projectId, fileCount) collected during the import setup.

Fix: Emit the accumulated event data:

event.set('outcome', 'cancelled');
event.success({ outcome: 'cancelled' });

Or add a cancel() method to WideEvent interface for consistent cancellation handling.

Suggested change
event.set('outcome', 'cancelled');
logger.event('import', { opId, outcome: 'cancelled' });
event.set('outcome', 'cancelled');
event.success({ outcome: 'cancelled' });

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

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