hydrateErrors.tsx 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import * as Sentry from '@sentry/react';
  2. import invariant from 'invariant';
  3. import {defined} from 'sentry/utils';
  4. import isValidDate from 'sentry/utils/date/isValidDate';
  5. import type {
  6. BreadcrumbFrame,
  7. ErrorFrame,
  8. RawReplayError,
  9. } from 'sentry/utils/replays/types';
  10. import toArray from 'sentry/utils/toArray';
  11. import type {ReplayRecord} from 'sentry/views/replays/types';
  12. export default function hydrateErrors(
  13. replayRecord: ReplayRecord,
  14. errors: RawReplayError[]
  15. ): {errorFrames: ErrorFrame[]; feedbackFrames: BreadcrumbFrame[]} {
  16. const startTimestampMs = replayRecord.started_at.getTime();
  17. const errorFrames: ErrorFrame[] = [];
  18. const feedbackFrames: BreadcrumbFrame[] = [];
  19. errors.forEach((e: RawReplayError) => {
  20. try {
  21. // Feedback frame
  22. if (e.title === 'User Feedback') {
  23. const time = new Date(e.timestamp);
  24. invariant(isValidDate(time), 'feedbackFrame.timestamp is invalid');
  25. feedbackFrames.push({
  26. category: 'feedback',
  27. data: {
  28. eventId: e.id,
  29. groupId: e['issue.id'],
  30. groupShortId: e.issue,
  31. label:
  32. (Array.isArray(e['error.type']) ? e['error.type'][0] : e['error.type']) ??
  33. '',
  34. labels: toArray(e['error.type']).filter(Boolean),
  35. projectSlug: e['project.name'],
  36. },
  37. message: e.title,
  38. offsetMs: Math.abs(time.getTime() - startTimestampMs),
  39. timestamp: time,
  40. timestampMs: time.getTime(),
  41. type: 'user', // For compatibility reasons. See BreadcrumbType
  42. });
  43. return;
  44. }
  45. // Error frame
  46. const time = new Date(e.timestamp);
  47. invariant(isValidDate(time), 'errorFrame.timestamp is invalid');
  48. errorFrames.push({
  49. category: 'issue' as const,
  50. data: {
  51. eventId: e.id,
  52. groupId: e['issue.id'],
  53. groupShortId: e.issue,
  54. label:
  55. (Array.isArray(e['error.type']) ? e['error.type'][0] : e['error.type']) ?? '',
  56. labels: toArray(e['error.type']).filter(defined),
  57. projectSlug: e['project.name'],
  58. },
  59. message: e.title,
  60. offsetMs: Math.abs(time.getTime() - startTimestampMs),
  61. timestamp: time,
  62. timestampMs: time.getTime(),
  63. type: 'error', // For compatibility reasons. See BreadcrumbType
  64. });
  65. } catch (error) {
  66. Sentry.captureException(error);
  67. }
  68. });
  69. return {errorFrames, feedbackFrames};
  70. }