From b795579ca0a65dcd382f5e401bd0d51caffb7ce6 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Thu, 28 Jul 2022 15:38:55 +0100 Subject: [PATCH] Merge pull request #9006 from overleaf/jpa-sentry-error-context [web] send OError info and OError tags/cause tracebacks to sentry GitOrigin-RevId: 0544768ca16fcafb63ec6116a573e83302cdbdd3 --- .../pdf-preview/util/pdf-caching-transport.js | 18 ++++++++++++++---- .../js/infrastructure/error-boundary.js | 11 +++++++---- .../js/infrastructure/error-reporter.js | 17 +++++++++++++++-- .../web/frontend/js/modules/errorCatcher.js | 7 ++++--- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js b/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js index f3148cd660..5e6ccb8159 100644 --- a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js +++ b/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) }) } diff --git a/services/web/frontend/js/infrastructure/error-boundary.js b/services/web/frontend/js/infrastructure/error-boundary.js index 1384b93abe..51f3ca7c4a 100644 --- a/services/web/frontend/js/infrastructure/error-boundary.js +++ b/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', + }, }) } diff --git a/services/web/frontend/js/infrastructure/error-reporter.js b/services/web/frontend/js/infrastructure/error-reporter.js index 110a195e57..557e9a574d 100644 --- a/services/web/frontend/js/infrastructure/error-reporter.js +++ b/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) { diff --git a/services/web/frontend/js/modules/errorCatcher.js b/services/web/frontend/js/modules/errorCatcher.js index 2f94ecc728..5994dcfc29 100644 --- a/services/web/frontend/js/modules/errorCatcher.js +++ b/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)