-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Telemetry: Queue error reporting & filter browser-extention #32499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…l is unavailable. Update `shouldSkipError` to include additional error messages for better filtering.
WalkthroughImplements telemetry error queuing and global error routing: adds queued error storage, flushes queued errors when a channel becomes available, reverses skip logic to early-return on skippable errors, and wires window-level error and unhandledrejection events to the telemetry sender. Updates the skip list to ignore a specific React devtools production-mode message. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant App
participant GlobalHandlers as Global Error Handlers
participant Telemetry as sendTelemetryError
participant Channel as Telemetry Channel
rect rgb(245,248,255)
note over App,GlobalHandlers: New: Global routing
User->>App: Causes runtime error / rejection
App-->>GlobalHandlers: window "error" / "unhandledrejection"
GlobalHandlers->>Telemetry: sendTelemetryError(error)
end
alt shouldSkipError(error) == true
Telemetry-->>Telemetry: Return early (no emit)
else Channel unavailable
Telemetry->>Telemetry: preparedError = prepareForTelemetry(error)
Telemetry->>Telemetry: queuedErrors.push(preparedError)
Telemetry-->>GlobalHandlers: Return
else Channel available
Telemetry->>Channel: Flush queuedErrors (TELEMETRY_ERROR x N)
Telemetry->>Channel: Emit TELEMETRY_ERROR(preparedError)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (6)
code/core/src/manager/utils/prepareForTelemetry.ts (2)
28-33
: Make skip matching robust (substring + case-insensitive).React/DevTools messages often vary slightly. Use a case-insensitive substring match so variants are also filtered.
Apply this diff:
-export const shouldSkipError = (error: Error) => errorMessages.includes(error?.message); +export const shouldSkipError = (error: Error) => { + const msg = error?.message?.toLowerCase?.(); + return !!msg && errorMessages.some((m) => msg.includes(m.toLowerCase())); +};
32-32
: Optional: accept unknown and normalize to a message.This makes the filter resilient to strings/objects passed from unhandledrejection.
Example (outside the changed hunk):
export const shouldSkipError = (err: unknown) => { const msg = err instanceof Error ? err.message : typeof err === 'string' ? err : typeof (err as any)?.message === 'string' ? (err as any).message : ''; const lower = msg.toLowerCase(); return lower && errorMessages.some((m) => lower.includes(m.toLowerCase())); };code/core/src/manager/globals-runtime.ts (4)
13-14
: Bound the queue to prevent unbounded memory growth.If the channel is unavailable for a while, the queue can grow without limit.
Apply this diff:
-const queuedErrors: Error[] = []; +const queuedErrors: Error[] = []; +const MAX_QUEUED_ERRORS = 200; // drop oldest beyond this
15-22
: Normalize input to Error before filtering and preparing.Unhandled rejections can be strings/objects. Normalize first so skip logic and preparation are reliable.
Apply this diff:
-globalThis.sendTelemetryError = (error) => { - if (shouldSkipError(error)) { +globalThis.sendTelemetryError = (raw) => { + const error = + raw instanceof Error + ? raw + : new Error(String((raw as any)?.message ?? raw)); + if (shouldSkipError(error)) { return; } - const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__; - const preparedError = prepareForTelemetry(error); + const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__; + const preparedError = prepareForTelemetry(error);
23-26
: Drop oldest when queue is full.Prevents runaway memory while preserving the most recent context.
Apply this diff:
- if (!channel) { - queuedErrors.push(preparedError); + if (!channel) { + if (queuedErrors.length >= MAX_QUEUED_ERRORS) queuedErrors.shift(); + queuedErrors.push(preparedError); return; }
28-33
: Flush without O(n) shift and guard against emit failures.Use splice to drain in one shot and try/catch so one bad emit doesn’t stop the rest.
Apply this diff:
- // Flush any queued errors first - while (queuedErrors.length > 0) { - const queuedError = queuedErrors.shift(); - channel.emit(TELEMETRY_ERROR, queuedError); - } + // Flush any queued errors first + const toFlush = queuedErrors.splice(0, queuedErrors.length); + for (const queuedError of toFlush) { + try { + channel.emit(TELEMETRY_ERROR, queuedError); + } catch { + // swallow to avoid cascading failures + } + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
code/core/src/manager/globals-runtime.ts
(1 hunks)code/core/src/manager/utils/prepareForTelemetry.ts
(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
code/core/src/manager/globals-runtime.ts (1)
code/core/src/manager/utils/prepareForTelemetry.ts (2)
shouldSkipError
(32-32)prepareForTelemetry
(34-64)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: normal
- GitHub Check: Danger JS
- GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (3)
code/core/src/manager/utils/prepareForTelemetry.ts (1)
28-30
: Good call filtering React DevTools noise.This avoids a common false-positive from the extension.
code/core/src/manager/globals-runtime.ts (2)
34-35
: LGTM: emit current error after flush.Order is correct; no reordering risk.
38-45
: Global routing looks good; relies on normalization above.Once normalization lands, both listeners will produce consistent telemetry.
Please manually verify:
- With no addons channel, trigger 3+ errors and confirm queue size caps at MAX_QUEUED_ERRORS.
- After channel becomes available, confirm queued errors flush followed by the current one, and no duplicates are left in the queue.
View your CI Pipeline Execution ↗ for commit d399876
☁️ Nx Cloud last updated this comment at |
…nager-runtime Telemetry: Queue error reporting & filter browser-extention (cherry picked from commit 6b967f1)
What I did
Implemented a fix suggested by @yannbf for reporting errors even if they happen before storybook loads.
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
No manual testing required
Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal
,ci:merged
orci:daily
GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.ts
Make sure this PR contains one of the labels below:
Available labels
bug
: Internal changes that fixes incorrect behavior.maintenance
: User-facing maintenance tasks.dependencies
: Upgrading (sometimes downgrading) dependencies.build
: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup
: Minor cleanup style change. Will not show up in release changelog.documentation
: Documentation only changes. Will not show up in release changelog.feature request
: Introducing a new feature.BREAKING CHANGE
: Changes that break compatibility in some way with current major version.other
: Changes that don't fit in the above categories.🦋 Canary release
This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the
@storybookjs/core
team here.core team members can create a canary release here or locally with
gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=<PR_NUMBER>
Summary by CodeRabbit