error-reporter.js 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Conditionally enable Sentry based on whether the DSN token is set
  2. import getMeta from '../utils/meta'
  3. const reporterPromise = window.ExposedSettings?.sentryDsn
  4. ? sentryReporter()
  5. : nullReporter()
  6. function sentryReporter() {
  7. return (
  8. import(/* webpackMode: "eager" */ '@sentry/browser')
  9. .then(Sentry => {
  10. let eventCount = 0
  11. Sentry.init({
  12. dsn: window.ExposedSettings.sentryDsn,
  13. environment: window.ExposedSettings.sentryEnvironment,
  14. release: window.ExposedSettings.sentryRelease,
  15. autoSessionTracking: false,
  16. // Ignore errors unless they come from our origins
  17. // Adapted from: https://docs.sentry.io/platforms/javascript/#decluttering-sentry
  18. whitelistUrls: [
  19. new RegExp(window.ExposedSettings.sentryAllowedOriginRegex),
  20. ],
  21. ignoreErrors: [
  22. // Ignore very noisy error
  23. 'SecurityError: Permission denied to access property "pathname" on cross-origin object',
  24. // Ignore unhandled error that is "expected" - see https://github.com/overleaf/issues/issues/3321
  25. /^Missing PDF/,
  26. /^pdfng error Error: MissingPDFException/,
  27. // Ignore "expected" error from aborted fetch - see https://github.com/overleaf/issues/issues/3321
  28. /^AbortError/,
  29. // Ignore spurious error from Ace internals - see https://github.com/overleaf/issues/issues/3321
  30. 'ResizeObserver loop limit exceeded',
  31. 'ResizeObserver loop completed with undelivered notifications.',
  32. // Microsoft Outlook SafeLink crawler
  33. // https://forum.sentry.io/t/unhandledrejection-non-error-promise-rejection-captured-with-value/14062
  34. /Non-Error promise rejection captured with value: Object Not Found Matching Id/,
  35. ],
  36. beforeSend(event) {
  37. // Limit number of events sent to Sentry to 100 events "per page load",
  38. // (i.e. the cap will be reset if the page is reloaded). This prevent
  39. // hitting their server-side event cap.
  40. eventCount++
  41. if (eventCount > 100) {
  42. return null // Block the event from sending
  43. } else {
  44. return event
  45. }
  46. },
  47. })
  48. Sentry.setUser({ id: window.user_id })
  49. const splitTestAssignments = getMeta('ol-splitTestVariants')
  50. if (splitTestAssignments) {
  51. for (const [name, value] of Object.entries(splitTestAssignments)) {
  52. // Ensure Sentry tag name is within the 32-character limit
  53. Sentry.setTag(`ol.${name}`.slice(0, 32), value.toString())
  54. }
  55. }
  56. return Sentry
  57. })
  58. // If Sentry fails to load, use the null reporter instead
  59. .catch(error => {
  60. console.error(error)
  61. return nullReporter()
  62. })
  63. )
  64. }
  65. function nullReporter() {
  66. return Promise.resolve({
  67. captureException: console.error,
  68. captureMessage: console.error,
  69. })
  70. }
  71. export function captureException(...args) {
  72. reporterPromise.then(reporter => reporter.captureException(...args))
  73. }
  74. export function captureMessage(...args) {
  75. reporterPromise.then(reporter => reporter.captureMessage(...args))
  76. }