Skip to content

fix: defer UserInteractionInstrumentation enable() to prevent _spansData TypeError #SUPERLOG - #415

Open
superlog-app[bot] wants to merge 1 commit into
mainfrom
superlog/fix-userinteraction-spansdata-init
Open

fix: defer UserInteractionInstrumentation enable() to prevent _spansData TypeError #SUPERLOG#415
superlog-app[bot] wants to merge 1 commit into
mainfrom
superlog/fix-userinteraction-spansdata-init

Conversation

@superlog-app

@superlog-app superlog-app Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Every page load of superlog.sh was triggering TypeError: this._spansData is undefined inside UserInteractionInstrumentation._shouldCountTask. The error fired when the BatchSpanProcessor scheduled its batch-export timer (_maybeStartTimer → setTimeout) while execution was already inside a ZoneContextManager span-context zone created by DocumentLoadInstrumentation._collectPerformance. Zone.js intercepted the setTimeout, ran the patched scheduleTask, found an active span in the zone, and called _shouldCountTask — where this._spansData was undefined.

Root Cause

InstrumentationBase.constructor (from @opentelemetry/instrumentation@0.220.0) always calls this.enable() inside its constructor, before the ES2022 class-field initializers of the derived UserInteractionInstrumentation have run. enable() captures plugin = this and patches Zone.prototype.scheduleTask; but _spansData = new WeakMap() is an instance class field that is only initialized after super() returns. When the zone patch fires while inside the document-load context zone and reaches this._spansData.get(currentSpan), _spansData is undefined and the error is thrown. The throw propagates through Zone.js to window.onerror, where the new window.error listener (also added in this PR) reports it as a browser.exception span, creating the production incident.

Fix: pass { enabled: false } to UserInteractionInstrumentation. InstrumentationBase.constructor then skips enable() during construction. registerInstrumentations() calls enable() after construction completes — at which point _spansData is already the WeakMap — so the zone-patch closure captures a valid _spansData.

This PR also brings instrumentation.ts forward to include:

  • browserTracerProvider variable + forceFlush() on error reporting
  • serviceVersion resource attribute (stamped by CI via VITE_OTEL_SERVICE_VERSION)
  • reportBrowserException() helper + window.error/unhandledrejection listeners for post-bootstrap crash capture

All of these additions were already deployed to production on a pre-merge branch and are being merged to main here together with the _spansData fix.

Resolves incident ashen-hedgehog.


Was this PR helpful? Leave feedback — goes straight to the Superlog team.


Summary by cubic

Delay enabling of UserInteractionInstrumentation to stop _spansData is undefined errors during page load and prevent noisy browser exception reports.

  • Bug Fixes
    • Pass { enabled: false } to UserInteractionInstrumentation so registerInstrumentations() enables it after class fields initialize, ensuring the zone patch sees a valid _spansData.
    • Prevents setTimeout during document load from triggering a TypeError in _shouldCountTask when a span is active.

Written for commit 02276e2. Summary will update on new commits.

Review in cubic

…ata TypeError #SUPERLOG

Delivery-Id: 033b6f0846313157502d4e1668328725ba0669fa49896904a88d2afeb565a60f
Delivery-Base: main

@superlog-app superlog-app Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Observability review

All clear — no observability concerns found.

Very observable!

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