From b20b711cb27f85b650a11e8aa0b5f9913ddad1bb Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 6 Apr 2023 09:39:22 +0200 Subject: [PATCH] feat(loader): Ensure default integrations are added & work for performance/replay --- .../templates/sentry/js-sdk-loader.js.tmpl | 44 ++++++++++---- .../sentry/js-sdk-loader.min.js.tmpl | 2 +- src/sentry/templates/sentry/js-sdk-loader.ts | 57 ++++++++++++++----- 3 files changed, 75 insertions(+), 28 deletions(-) diff --git a/src/sentry/templates/sentry/js-sdk-loader.js.tmpl b/src/sentry/templates/sentry/js-sdk-loader.js.tmpl index dd5fe397c0d6e9..ccb673522d91cc 100644 --- a/src/sentry/templates/sentry/js-sdk-loader.js.tmpl +++ b/src/sentry/templates/sentry/js-sdk-loader.js.tmpl @@ -50,13 +50,29 @@ // Once our SDK is loaded _newScriptTag.addEventListener('load', function () { try { - // Restore onerror/onunhandledrejection handlers - _window[_onerror] = _oldOnerror; - _window[_onunhandledrejection] = _oldOnunhandledrejection; + // Restore onerror/onunhandledrejection handlers - only if not mutated in the meanwhile + if (_window[_onerror] && _window[_onerror].__SENTRY_LOADER__) { + _window[_onerror] = _oldOnerror; + } + if (_window[_onunhandledrejection] && + _window[_onunhandledrejection].__SENTRY_LOADER__) { + _window[_onunhandledrejection] = _oldOnunhandledrejection; + } // Add loader as SDK source _window.SENTRY_SDK_SOURCE = 'loader'; var SDK = _window[_namespace]; var oldInit_1 = SDK.init; + // Add necessary integrations based on config + var integrations = []; + if (_config.tracesSampleRate) { + integrations.push(new SDK.BrowserTracing()); + } + if (_config.replaysSessionSampleRate || _config.replaysOnErrorSampleRate) { + integrations.push(new SDK.Replay()); + } + if (integrations.length) { + _config.integrations = integrations; + } // Configure it using provided DSN and config object SDK.init = function (options) { var target = _config; @@ -75,23 +91,25 @@ }); _currentScriptTag.parentNode.insertBefore(_newScriptTag, _currentScriptTag); } + function sdkIsLoaded() { + var __sentry = _window.__SENTRY__; + // If there is a global __SENTRY__ that means that in any of the callbacks init() was already invoked + return !!(!(typeof __sentry === 'undefined') && + __sentry.hub && + __sentry.hub.getClient()); + } function sdkLoaded(callbacks, SDK) { try { - var data = queue.data; // We have to make sure to call all callbacks first for (var i = 0; i < callbacks.length; i++) { if (typeof callbacks[i] === 'function') { callbacks[i](); } } - var initAlreadyCalled = false; - var __sentry = _window.__SENTRY__; - // If there is a global __SENTRY__ that means that in any of the callbacks init() was already invoked - if (!(typeof __sentry === 'undefined') && - __sentry.hub && - __sentry.hub.getClient()) { - initAlreadyCalled = true; - } + var data = queue.data; + var initAlreadyCalled = sdkIsLoaded(); + // Call init first, if provided + data.sort(function (a) { return (a.f === 'init' ? -1 : 0); }); // We want to replay all calls to Sentry and also make sure that `init` is called if it wasn't already // We replay all calls to `Sentry.*` now var calledSentry = false; @@ -172,6 +190,7 @@ _oldOnerror.apply(_window, arguments); } }; + _window[_onerror].__SENTRY_LOADER__ = true; // Do the same store/queue/call operations for `onunhandledrejection` event var _oldOnunhandledrejection = _window[_onunhandledrejection]; _window[_onunhandledrejection] = function (e) { @@ -186,6 +205,7 @@ _oldOnunhandledrejection.apply(_window, arguments); } }; + _window[_onunhandledrejection].__SENTRY_LOADER__ = true; if (!lazy) { setTimeout(function () { injectSdk(onLoadCallbacks); diff --git a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl index bc33aec005180b..cdc71cf880f4bb 100644 --- a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl +++ b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl @@ -1 +1 @@ -{% load sentry_helpers %}!function(n,t,e,o,i,r,a,c,f,p){for(var u=p,forceLoad=!1,s=0;s-1){u&&"no"===document.scripts[s].getAttribute("data-lazy")&&(u=!1);break}var _=!1,d=[],l=function(n){("e"in n||"p"in n||n.f&&n.f.indexOf("capture")>-1||n.f&&n.f.indexOf("showReportDialog")>-1)&&u&&h(d),l.data.push(n)};function h(a){if(!_){_=!0;var p=t.scripts[0],u=t.createElement(e);u.src=c,u.crossOrigin="anonymous",u.addEventListener("load",(function(){try{n[o]=v,n[i]=y,n.SENTRY_SDK_SOURCE="loader";var t=n[r],e=t.init;t.init=function(n){var t=f;for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(t[o]=n[o]);e(t)},function(t,e){try{for(var r=l.data,a=0;a-1){s&&"no"===document.scripts[f].getAttribute("data-lazy")&&(s=!1);break}var u=!1,l=[],d=function(n){("e"in n||"p"in n||n.f&&n.f.indexOf("capture")>-1||n.f&&n.f.indexOf("showReportDialog")>-1)&&s&&E(l),d.data.push(n)};function E(i){if(!u){u=!0;var p=e.scripts[0],s=e.createElement(t);s.src=c,s.crossOrigin="anonymous",s.addEventListener("load",(function(){try{n[r]&&n[r].__SENTRY_LOADER__&&(n[r]=R),n[o]&&n[o].__SENTRY_LOADER__&&(n[o]=h),n.SENTRY_SDK_SOURCE="loader";var e=n[a],t=e.init,c=[];_.tracesSampleRate&&c.push(new e.BrowserTracing),(_.replaysSessionSampleRate||_.replaysOnErrorSampleRate)&&c.push(new e.Replay),c.length&&(_.integrations=c),e.init=function(n){var e=_;for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r]);t(e)},function(e,t){try{for(var a=0;a (a.f === 'init' ? -1 : 0)); // We want to replay all calls to Sentry and also make sure that `init` is called if it wasn't already // We replay all calls to `Sentry.*` now @@ -213,6 +238,7 @@ declare const __LOADER__IS_LAZY__: any; _oldOnerror.apply(_window, arguments); } }; + _window[_onerror].__SENTRY_LOADER__ = true; // Do the same store/queue/call operations for `onunhandledrejection` event const _oldOnunhandledrejection = _window[_onunhandledrejection]; @@ -229,6 +255,7 @@ declare const __LOADER__IS_LAZY__: any; _oldOnunhandledrejection.apply(_window, arguments); } }; + _window[_onunhandledrejection].__SENTRY_LOADER__ = true; if (!lazy) { setTimeout(function () {