Jelajahi Sumber

Merge pull request #9006 from overleaf/jpa-sentry-error-context

[web] send OError info and OError tags/cause tracebacks to sentry

GitOrigin-RevId: 0544768ca16fcafb63ec6116a573e83302cdbdd3
Jakob Ackermann 4 tahun lalu
induk
melakukan
b795579ca0

+ 14 - 4
services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js

@@ -1,3 +1,4 @@
+import OError from '@overleaf/o-error'
 import { fallbackRequest, fetchRange } from './pdf-caching'
 import { captureException } from '../../../infrastructure/error-reporter'
 import { getPdfCachingMetrics } from './metrics'
@@ -40,6 +41,13 @@ export function generatePdfCachingTransportFactory(PDFJS) {
 
     requestDataRange(start, end) {
       const abortSignal = this.abortController.signal
+      const errorInfo = {
+        pdfFile: this.pdfFile,
+        pdfUrl: this.url,
+        start,
+        end,
+        metrics,
+      }
       fetchRange({
         url: this.url,
         start,
@@ -56,16 +64,18 @@ export function generatePdfCachingTransportFactory(PDFJS) {
           if (!enablePdfCaching) {
             throw err // This was a fallback request already. Do not retry.
           }
-          console.error('optimized pdf download error', err)
-          captureException(err)
+          err = OError.tag(err, 'optimized pdf download error', errorInfo)
+          console.error(err)
+          captureException(err, { tags: { fromPdfCaching: true } })
           return fallbackRequest({ url: this.url, start, end, abortSignal })
         })
         .then(blob => {
           this.onDataRange(start, blob)
         })
         .catch(err => {
-          console.error('fatal pdf download error', err)
-          captureException(err)
+          err = OError.tag(err, 'fatal pdf download error', errorInfo)
+          console.error(err)
+          captureException(err, { tags: { fromPdfCaching: true } })
           this.reject(err)
         })
     }

+ 7 - 4
services/web/frontend/js/infrastructure/error-boundary.js

@@ -2,10 +2,13 @@ import { captureException } from './error-reporter'
 import { ErrorBoundary } from 'react-error-boundary'
 
 function errorHandler(error, componentStack) {
-  captureException(error, scope => {
-    scope.setExtra('componentStack', componentStack)
-    scope.setTag('handler', 'react-error-boundary')
-    return scope
+  captureException(error, {
+    extra: {
+      componentStack,
+    },
+    tags: {
+      handler: 'react-error-boundary',
+    },
   })
 }
 

+ 15 - 2
services/web/frontend/js/infrastructure/error-reporter.js

@@ -1,5 +1,6 @@
 // Conditionally enable Sentry based on whether the DSN token is set
 import getMeta from '../utils/meta'
+import OError from '@overleaf/o-error'
 
 const reporterPromise = window.ExposedSettings?.sentryDsn
   ? sentryReporter()
@@ -79,8 +80,20 @@ function nullReporter() {
   })
 }
 
-export function captureException(...args) {
-  reporterPromise.then(reporter => reporter.captureException(...args))
+export function captureException(err, options) {
+  options = options || {}
+  const extra = Object.assign(OError.getFullInfo(err), options.extra || {})
+  const fullStack = OError.getFullStack(err)
+  if (err.stack !== fullStack) {
+    // Attach tracebacks from OError.tag() and OError.cause.
+    extra.fullStack = fullStack
+  }
+  reporterPromise.then(reporter =>
+    reporter.captureException(err, {
+      ...options,
+      extra,
+    })
+  )
 }
 
 export function captureMessage(...args) {

+ 4 - 3
services/web/frontend/js/modules/errorCatcher.js

@@ -29,9 +29,10 @@ app.config([
             return
           }
 
-          captureException(exception, scope => {
-            scope.setTag('handler', 'angular-exception-handler')
-            return scope
+          captureException(exception, {
+            tags: {
+              handler: 'angular-exception-handler',
+            },
           })
 
           return $delegate(exception, cause)