Browse Source

feat: Use new JS SDK (#11046)

* feat: Update loader + loader usage

Remove raven-js dep

* feat: Use @sentry/browser, inject sdk options into bundle

* ref: Add small Raven shim with console.error

* fix: JS linter errors
Daniel Griesser 6 years ago
parent
commit
5f0f87daf0

+ 1 - 1
package.json

@@ -6,6 +6,7 @@
     "url": "git://github.com/getsentry/sentry.git"
   },
   "dependencies": {
+    "@sentry/browser": "^4.4.2",
     "babel-core": "6.21.0",
     "babel-gettext-extractor": "^3.0.0",
     "babel-loader": "^7.1.2",
@@ -61,7 +62,6 @@
     "po-catalog-loader": "2.0.0",
     "prop-types": "^15.6.0",
     "query-string": "2.4.2",
-    "raven-js": "^3.26.3",
     "react": "16.5.1",
     "react-addons-css-transition-group": "15.6.2",
     "react-autosize-textarea": "^4.0.0",

+ 34 - 2
src/sentry/static/sentry/app/index.js

@@ -8,7 +8,7 @@ import * as EmotionTheming from 'emotion-theming';
 import * as GridEmotion from 'grid-emotion';
 import JsCookie from 'js-cookie';
 import PropTypes from 'prop-types';
-import Raven from 'raven-js';
+import * as Sentry from '@sentry/browser';
 import React from 'react';
 import ReactBootstrapModal from 'react-bootstrap/lib/Modal';
 import ReactDOM from 'react-dom';
@@ -26,6 +26,37 @@ import * as api from 'app/api';
 import * as il8n from 'app/locale';
 import plugins from 'app/plugins';
 
+// SDK INIT  --------------------------------------------------------
+// window.__SENTRY__OPTIONS will be emmited by sdk-config.html before loading this script
+Sentry.init(window.__SENTRY__OPTIONS);
+
+Sentry.configureScope(scope => {
+  if (window.__SENTRY__USER) {
+    scope.setUser(window.__SENTRY__USER);
+  }
+  if (window.__SENTRY__VERSION) {
+    scope.setTag('sentry_version', window.__SENTRY__VERSION);
+  }
+});
+
+function __raven_deprecated() {
+  const message = '[DEPRECATED]: Please no longer use Raven, use Sentry instead';
+  console.error(message);
+  Sentry.captureMessage(message);
+}
+
+const Raven = {
+  captureMessage: () => __raven_deprecated(),
+  captureException: () => __raven_deprecated(),
+  captureBreadcrumb: () => __raven_deprecated(),
+  showReportDialog: () => __raven_deprecated(),
+  setTagsContext: () => __raven_deprecated(),
+  setExtraContext: () => __raven_deprecated(),
+  setUserContext: () => __raven_deprecated(),
+};
+window.Raven = Raven;
+// -----------------------------------------------------------------
+
 // Used for operational metrics to determine that the application js
 // bundle was loaded by browser.
 metric.mark('sentry-app-init');
@@ -59,8 +90,9 @@ if (module.hot) {
 export default {
   jQuery,
   moment,
-  Raven,
+  Sentry,
   React,
+  Raven,
   ReactDOM: {
     findDOMNode: ReactDOM.findDOMNode,
     render: ReactDOM.render,

+ 13 - 21
src/sentry/static/sentry/app/utils/sdk.js

@@ -1,19 +1,13 @@
+import * as Sentry from '@sentry/browser';
+
 let _addBreadcrumb = () => {};
 let _captureException = () => {};
 let _captureMessage = () => {};
 let _showReportDialog = () => {};
 let _lastEventId = () => {};
 
-document.addEventListener('ravenLoaded', function() {
-  _addBreadcrumb = window.Raven.captureBreadcrumb.bind(window.Raven);
-  _captureException = window.Raven.captureException.bind(window.Raven);
-  _captureMessage = window.Raven.captureMessage.bind(window.Raven);
-  _showReportDialog = window.Raven.showReportDialog.bind(window.Raven);
-  _lastEventId = window.Raven.lastEventId.bind(window.Raven);
-});
-
 function setContextInScope(context) {
-  window.Sentry.configureScope(scope => {
+  Sentry.configureScope(scope => {
     if (context.user) {
       scope.setUser(context.user);
     }
@@ -34,35 +28,33 @@ function setContextInScope(context) {
   });
 }
 
-document.addEventListener('sentryLoaded', function() {
-  _addBreadcrumb = window.Sentry.addBreadcrumb;
+Sentry.onLoad(function() {
+  _addBreadcrumb = Sentry.addBreadcrumb;
   _captureMessage = (...args) => {
-    window.Sentry.getDefaultHub().pushScope();
+    Sentry.getDefaultHub().pushScope();
     if (args[1]) {
       setContextInScope(args[1]);
     }
     if (args[0]) {
-      window.Sentry.captureMessage(args[0]);
+      Sentry.captureMessage(args[0]);
     }
-    window.Sentry.getDefaultHub().popScope();
+    Sentry.getDefaultHub().popScope();
   };
   _captureException = (...args) => {
-    window.Sentry.getDefaultHub().pushScope();
+    Sentry.getDefaultHub().pushScope();
     if (args[1]) {
       setContextInScope(args[1]);
     }
     if (args[0]) {
-      window.Sentry.captureException(args[0]);
+      Sentry.captureException(args[0]);
     }
-    window.Sentry.getDefaultHub().popScope();
+    Sentry.getDefaultHub().popScope();
   };
   _showReportDialog = () => {
-    // TODO: eventually implement this
-    window.Sentry.captureMessage('Would have shown report dialog');
+    Sentry.showReportDialog();
   };
   _lastEventId = () => {
-    // TODO: eventually implement this
-    window.Sentry.captureMessage('Would have called lastEventId()');
+    Sentry.lastEventId();
   };
 });
 

+ 6 - 2
src/sentry/static/sentry/app/utils/tracing.jsx

@@ -6,8 +6,12 @@ let transactionId = null;
 export function startTransaction() {
   spanId = uniqueId();
   transactionId = uniqueId();
-  window.Raven &&
-    window.Raven.setTagsContext({span_id: spanId, transaction_id: transactionId});
+  if (window.Sentry) {
+    window.Sentry.configureScope(function(scope) {
+      scope.setTag('span_id', spanId);
+      scope.setTag('transaction_id', transactionId);
+    });
+  }
   return {spanId, transactionId};
 }
 

+ 0 - 10
src/sentry/templates/sentry/includes/ravenjs.html

@@ -1,10 +0,0 @@
-{% load sentry_api %}
-{% load sentry_dsn %}
-
-<script>
-Raven.config('{% public_dsn %}', {
-  release: '{{ sentry_version.build }}',
-  whitelistUrls: {% convert_to_json ALLOWED_HOSTS %}
-}).install();
-Raven.setUserContext({% get_user_context request %});
-</script>

+ 10 - 0
src/sentry/templates/sentry/includes/sdk-config.html

@@ -0,0 +1,10 @@
+{% load sentry_api %}
+{% load sentry_dsn %}
+<script>
+  window.__SENTRY__OPTIONS = {
+    dsn: '{% public_dsn %}',
+    release: '{{ sentry_version.build }}',
+    whitelistUrls: {% convert_to_json ALLOWED_HOSTS %}
+  };
+  window.__SENTRY__USER = {% get_user_context request %} || undefined;
+</script>

+ 35 - 21
src/sentry/templates/sentry/js-sdk-loader.js.tmpl

@@ -1,17 +1,27 @@
 {% load sentry_helpers %}// Sentry Loader
-(function(_window, _document, _script, _onerror, _onunhandledrejection, _namespace, _publicKey, _sdkBundleUrl, _config) {
+(function(
+  _window,
+  _document,
+  _script,
+  _onerror,
+  _onunhandledrejection,
+  _namespace,
+  _publicKey,
+  _sdkBundleUrl,
+  _config
+) {
   var lazy = true;
   var forceLoad = false;
 
   for (var i = 0; i < document.scripts.length; i++) {
     if (document.scripts[i].src.indexOf(_publicKey) > -1) {
-      lazy = !(document.scripts[i].dataset.lazy === 'no');
+      lazy = !(document.scripts[i].getAttribute('data-lazy') === 'no');
       break;
     }
   }
 
   var injected = false;
-  var onLoadCallback;
+  var onLoadCallbacks = [];
 
   // Create a namespace and attach function that will store captured exception
   // Because functions are also objects, we can attach the queue itself straight to it and save some bytes
@@ -20,7 +30,8 @@
     // content.p = promise rejection
     // content.f = function call the Sentry
     if (
-      (content.e || content.p ||
+      (content.e ||
+        content.p ||
         (content.f && content.f.indexOf('capture') > -1) ||
         (content.f && content.f.indexOf('showReportDialog') > -1)) &&
       lazy
@@ -28,13 +39,13 @@
       // We only want to lazy inject/load the sdk bundle if
       // an error or promise rejection occured
       // OR someone called `capture...` on the SDK
-      injectSdk(onLoadCallback);
+      injectSdk(onLoadCallbacks);
     }
     queue.data.push(content);
   };
   queue.data = [];
 
-  function injectSdk(callback) {
+  function injectSdk(callbacks) {
     if (injected) {
       return;
     }
@@ -73,7 +84,7 @@
           oldInit(target);
         };
 
-        sdkLoaded(callback, SDK);
+        sdkLoaded(callbacks, SDK);
       } catch (o_O) {
         console.error(o_O);
       }
@@ -82,11 +93,14 @@
     _currentScriptTag.parentNode.insertBefore(_newScriptTag, _currentScriptTag);
   }
 
-  function sdkLoaded(callback, SDK) {
+  function sdkLoaded(callbacks, SDK) {
     try {
-      if (callback) {
-        callback();
+      for (var i = 0; i < callbacks.length; i++) {
+        if (typeof callbacks[i] === 'function') {
+          callbacks[i]();
+        }
       }
+
       var data = queue.data;
 
       // We want to replay all calls to Sentry first to make sure init is called before
@@ -130,21 +144,21 @@
   // We don't want to _window.Sentry = _window.Sentry || { ... } since we want to make sure
   // that the first Sentry "instance" is our with onLoad
   _window[_namespace] = {
-    onLoad: function(callback) {
+    onLoad: function (callback) {
+      onLoadCallbacks.push(callback);
       if (lazy && !forceLoad) {
-        onLoadCallback = callback;
-      } else {
-        injectSdk(callback);
+        return;
       }
+      injectSdk(onLoadCallbacks);
     },
     forceLoad: function() {
       forceLoad = true;
       if (lazy) {
         setTimeout(function() {
-          injectSdk(onLoadCallback);
+          injectSdk(onLoadCallbacks);
         });
       }
-    },
+    }
   };
 
   [
@@ -155,10 +169,10 @@
     'captureEvent',
     'configureScope',
     'withScope',
-    'showReportDialog',
+    'showReportDialog'
   ].forEach(function(f) {
     _window[_namespace][f] = function() {
-      queue({f: f, a: arguments});
+      queue({ f: f, a: arguments });
     };
   });
 
@@ -168,7 +182,7 @@
   _window[_onerror] = function(message, source, lineno, colno, exception) {
     // Use keys as "data type" to save some characters"
     queue({
-      e: [].slice.call(arguments),
+      e: [].slice.call(arguments)
     });
 
     if (_oldOnerror) _oldOnerror.apply(_window, arguments);
@@ -178,14 +192,14 @@
   var _oldOnunhandledrejection = _window[_onunhandledrejection];
   _window[_onunhandledrejection] = function(exception) {
     queue({
-      p: exception.reason,
+      p: exception.reason
     });
     if (_oldOnunhandledrejection) _oldOnunhandledrejection.apply(_window, arguments);
   };
 
   if (!lazy) {
     setTimeout(function() {
-      injectSdk(onLoadCallback);
+      injectSdk(onLoadCallbacks);
     });
   }
 })(window, document, "script", "onerror", "onunhandledrejection", "Sentry", "{{ publicKey|safe }}", "{{ jsSdkUrl|safe }}", {{ config|to_json|safe }});

+ 4 - 3
src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl

@@ -1,3 +1,4 @@
-{% load sentry_helpers %}(function(c,t,u,m,n,p,y,z,v){function h(a){if(!w){w=!0;var e=t.getElementsByTagName(u)[0],b=t.createElement(u);b.src=z;b.crossorigin="anonymous";b.addEventListener("load",function(){try{c[m]=q;c[n]=r;var b=c[p],e=b.init;b.init=function(a){for(var b in a)Object.prototype.hasOwnProperty.call(a,b)&&(v[b]=a[b]);e(v)};A(a,b)}catch(d){console.error(d)}});e.parentNode.insertBefore(b,e)}}function A(a,e){try{a&&a();for(var b=k.data,f=!1,h=!1,d=0;d<b.length;d++)if(b[d].f){h=!0;var g=b[d];!1===f&&"init"!==g.f&&
-e.init();f=!0;e[g.f].apply(e,g.a)}!1===h&&e.init();var l=c[m];for(d=0;d<b.length;d++)b[d].e?l.apply(c,b[d].e):b[d].p&&e.captureException(b[d].p)}catch(B){console.error(B)}}for(var f=!0,x=!1,g=0;g<document.scripts.length;g++)if(-1<document.scripts[g].src.indexOf(y)){f="no"!==document.scripts[g].dataset.lazy;break}var w=!1,l,k=function(a){(a.e||a.p||a.f&&-1<a.f.indexOf("capture")||a.f&&-1<a.f.indexOf("showReportDialog"))&&f&&h(l);k.data.push(a)};k.data=[];c[p]={onLoad:function(a){f&&!x?l=a:h(a)},forceLoad:function(){x=
-!0;f&&setTimeout(function(){h(l)})}};"init addBreadcrumb captureMessage captureException captureEvent configureScope withScope showReportDialog".split(" ").forEach(function(a){c[p][a]=function(){k({f:a,a:arguments})}});var q=c[m];c[m]=function(a,e,b,f,g){k({e:[].slice.call(arguments)});q&&q.apply(c,arguments)};var r=c[n];c[n]=function(a){k({p:a.reason});r&&r.apply(c,arguments)};f||setTimeout(function(){h(l)})})(window,document,"script","onerror","onunhandledrejection","Sentry","{{ publicKey|safe }}","{{ jsSdkUrl|safe }}",{{ config|to_json|safe }});
+{% load sentry_helpers %}(function(c,t,u,m,n,p,y,z,v){function e(b){if(!w){w=!0;var d=t.getElementsByTagName(u)[0],a=t.createElement(u);a.src=z;a.crossorigin="anonymous";a.addEventListener("load",function(){try{c[m]=q;c[n]=r;var a=c[p],d=a.init;a.init=function(a){for(var b in a)Object.prototype.hasOwnProperty.call(a,b)&&(v[b]=a[b]);d(v)};B(b,a)}catch(A){console.error(A)}});d.parentNode.insertBefore(a,d)}}function B(b,d){try{for(var a=0;a<b.length;a++)if("function"===typeof b[a])b[a]();var f=k.data,g=!1,h=!1;for(a=0;a<f.length;a++)if(f[a].f){h=
+!0;var e=f[a];!1===g&&"init"!==e.f&&d.init();g=!0;d[e.f].apply(d,e.a)}!1===h&&d.init();var l=c[m];for(a=0;a<f.length;a++)f[a].e?l.apply(c,f[a].e):f[a].p&&d.captureException(f[a].p)}catch(C){console.error(C)}}for(var g=!0,x=!1,l=0;l<document.scripts.length;l++)if(-1<document.scripts[l].src.indexOf(y)){g="no"!==document.scripts[l].getAttribute("data-lazy");break}var w=!1,h=[],k=function(b){(b.e||b.p||b.f&&-1<b.f.indexOf("capture")||b.f&&-1<b.f.indexOf("showReportDialog"))&&g&&e(h);k.data.push(b)};k.data=
+[];c[p]={onLoad:function(b){h.push(b);g&&!x||e(h)},forceLoad:function(){x=!0;g&&setTimeout(function(){e(h)})}};"init addBreadcrumb captureMessage captureException captureEvent configureScope withScope showReportDialog".split(" ").forEach(function(b){c[p][b]=function(){k({f:b,a:arguments})}});var q=c[m];c[m]=function(b,d,a,f,e){k({e:[].slice.call(arguments)});q&&q.apply(c,arguments)};var r=c[n];c[n]=function(b){k({p:b.reason});r&&r.apply(c,arguments)};g||setTimeout(function(){e(h)})})(window,document,
+"script","onerror","onunhandledrejection","Sentry","{{ publicKey|safe }}","{{ jsSdkUrl|safe }}",{{ config|to_json|safe }});

+ 1 - 2
src/sentry/templates/sentry/layout.html

@@ -39,6 +39,7 @@
   </script>
 
   {% block scripts %}
+  {% include "sentry/includes/sdk-config.html" %}
   <script src="{% asset_url "sentry" "dist/vendor.js" %}"{% crossorigin %}></script>
   {% locale_js_include %}
   <script src="{% asset_url "sentry" "dist/app.js" %}"{% crossorigin %}></script>
@@ -57,8 +58,6 @@
     SentryApp.ConfigStore.loadInitialData({% get_react_config %}, {{ request.LANGUAGE_CODE|to_json|safe }});
   </script>
   <script src="{% asset_url 'sentry' 'js/ads.js' %}"></script>
-
-  {% include "sentry/includes/ravenjs.html" %}
   {% endblock %}
 
   {% block meta %}

+ 1 - 1
webpack.config.js

@@ -59,7 +59,7 @@ var appEntry = {
     'marked',
     'moment',
     'moment-timezone',
-    'raven-js',
+    '@sentry/browser',
     'react',
     'react-dom',
     'react-dom/server',

Some files were not shown because too many files changed in this diff