contextlines.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import { defineIntegration, convertIntegrationFnToClass } from '@sentry/core';
  2. import { stripUrlQueryAndFragment, addContextToFrame, GLOBAL_OBJ } from '@sentry/utils';
  3. const WINDOW = GLOBAL_OBJ ;
  4. const DEFAULT_LINES_OF_CONTEXT = 7;
  5. const INTEGRATION_NAME = 'ContextLines';
  6. const _contextLinesIntegration = ((options = {}) => {
  7. const contextLines = options.frameContextLines != null ? options.frameContextLines : DEFAULT_LINES_OF_CONTEXT;
  8. return {
  9. name: INTEGRATION_NAME,
  10. // TODO v8: Remove this
  11. setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function
  12. processEvent(event) {
  13. return addSourceContext(event, contextLines);
  14. },
  15. };
  16. }) ;
  17. const contextLinesIntegration = defineIntegration(_contextLinesIntegration);
  18. /**
  19. * Collects source context lines around the lines of stackframes pointing to JS embedded in
  20. * the current page's HTML.
  21. *
  22. * This integration DOES NOT work for stack frames pointing to JS files that are loaded by the browser.
  23. * For frames pointing to files, context lines are added during ingestion and symbolication
  24. * by attempting to download the JS files to the Sentry backend.
  25. *
  26. * Use this integration if you have inline JS code in HTML pages that can't be accessed
  27. * by our backend (e.g. due to a login-protected page).
  28. *
  29. * @deprecated Use `contextLinesIntegration()` instead.
  30. */
  31. // eslint-disable-next-line deprecation/deprecation
  32. const ContextLines = convertIntegrationFnToClass(INTEGRATION_NAME, contextLinesIntegration)
  33. ;
  34. /**
  35. * Processes an event and adds context lines.
  36. */
  37. function addSourceContext(event, contextLines) {
  38. const doc = WINDOW.document;
  39. const htmlFilename = WINDOW.location && stripUrlQueryAndFragment(WINDOW.location.href);
  40. if (!doc || !htmlFilename) {
  41. return event;
  42. }
  43. const exceptions = event.exception && event.exception.values;
  44. if (!exceptions || !exceptions.length) {
  45. return event;
  46. }
  47. const html = doc.documentElement.innerHTML;
  48. if (!html) {
  49. return event;
  50. }
  51. const htmlLines = ['<!DOCTYPE html>', '<html>', ...html.split('\n'), '</html>'];
  52. exceptions.forEach(exception => {
  53. const stacktrace = exception.stacktrace;
  54. if (stacktrace && stacktrace.frames) {
  55. stacktrace.frames = stacktrace.frames.map(frame =>
  56. applySourceContextToFrame(frame, htmlLines, htmlFilename, contextLines),
  57. );
  58. }
  59. });
  60. return event;
  61. }
  62. /**
  63. * Only exported for testing
  64. */
  65. function applySourceContextToFrame(
  66. frame,
  67. htmlLines,
  68. htmlFilename,
  69. linesOfContext,
  70. ) {
  71. if (frame.filename !== htmlFilename || !frame.lineno || !htmlLines.length) {
  72. return frame;
  73. }
  74. addContextToFrame(htmlLines, frame, linesOfContext);
  75. return frame;
  76. }
  77. export { ContextLines, applySourceContextToFrame, contextLinesIntegration };
  78. //# sourceMappingURL=contextlines.js.map