displayReprocessEventAction.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import {
  2. EntryException,
  3. EntryType,
  4. Event,
  5. ExceptionValue,
  6. PlatformType,
  7. StacktraceType,
  8. Thread,
  9. } from 'sentry/types';
  10. const NATIVE_PLATFORMS = ['cocoa', 'native'] as Array<PlatformType>;
  11. // Finds all frames in a given data blob and returns it's platforms
  12. function getPlatforms(exceptionValue: ExceptionValue | StacktraceType | null) {
  13. const frames = exceptionValue?.frames ?? [];
  14. const stacktraceFrames = (exceptionValue as ExceptionValue)?.stacktrace?.frames ?? [];
  15. if (!frames.length && !stacktraceFrames.length) {
  16. return [];
  17. }
  18. return [...frames, ...stacktraceFrames]
  19. .map(frame => frame.platform)
  20. .filter(platform => !!platform);
  21. }
  22. function getStackTracePlatforms(event: Event, exceptionEntry: EntryException) {
  23. // Fetch platforms in stack traces of an exception entry
  24. const exceptionEntryPlatforms = (exceptionEntry.data.values ?? []).flatMap(
  25. getPlatforms
  26. );
  27. // Fetch platforms in an exception entry
  28. const stackTraceEntry = (event.entries.find(
  29. entry => entry.type === EntryType.STACKTRACE
  30. )?.data ?? {}) as StacktraceType;
  31. // Fetch platforms in an exception entry
  32. const stackTraceEntryPlatforms = Object.keys(stackTraceEntry).flatMap(key =>
  33. getPlatforms(stackTraceEntry[key])
  34. );
  35. // Fetch platforms in an thread entry
  36. const threadEntry = (event.entries.find(entry => entry.type === EntryType.THREADS)?.data
  37. .values ?? []) as Array<Thread>;
  38. // Fetch platforms in a thread entry
  39. const threadEntryPlatforms = threadEntry.flatMap(({stacktrace}) =>
  40. getPlatforms(stacktrace)
  41. );
  42. return new Set([
  43. ...exceptionEntryPlatforms,
  44. ...stackTraceEntryPlatforms,
  45. ...threadEntryPlatforms,
  46. ]);
  47. }
  48. // Checks whether an event indicates that it has an apple crash report.
  49. function isNativeEvent(event: Event, exceptionEntry: EntryException) {
  50. const {platform} = event;
  51. if (platform && NATIVE_PLATFORMS.includes(platform)) {
  52. return true;
  53. }
  54. const stackTracePlatforms = getStackTracePlatforms(event, exceptionEntry);
  55. return NATIVE_PLATFORMS.some(nativePlatform => stackTracePlatforms.has(nativePlatform));
  56. }
  57. // Checks whether an event indicates that it has an associated minidump.
  58. function isMinidumpEvent(exceptionEntry: EntryException) {
  59. const {data} = exceptionEntry;
  60. return (data.values ?? []).some(value => value.mechanism?.type === 'minidump');
  61. }
  62. // Checks whether an event indicates that it has an apple crash report.
  63. function isAppleCrashReportEvent(exceptionEntry: EntryException) {
  64. const {data} = exceptionEntry;
  65. return (data.values ?? []).some(value => value.mechanism?.type === 'applecrashreport');
  66. }
  67. export function displayReprocessEventAction(orgFeatures: Array<string>, event?: Event) {
  68. if (!event || !orgFeatures.includes('reprocessing-v2')) {
  69. return false;
  70. }
  71. const {entries} = event;
  72. const exceptionEntry = entries.find(entry => entry.type === EntryType.EXCEPTION) as
  73. | EntryException
  74. | undefined;
  75. if (!exceptionEntry) {
  76. return false;
  77. }
  78. // We want to show the reprocessing button if the issue in question is native or contains native frames.
  79. // The logic is taken from the symbolication pipeline in Python, where it is used to determine whether reprocessing
  80. // payloads should be stored:
  81. // https://github.com/getsentry/sentry/blob/cb7baef414890336881d67b7a8433ee47198c701/src/sentry/lang/native/processing.py#L425-L426
  82. // It is still not ideal as one can always merge native and non-native events together into one issue,
  83. // but it's the best approximation we have.
  84. if (
  85. !isMinidumpEvent(exceptionEntry) &&
  86. !isAppleCrashReportEvent(exceptionEntry) &&
  87. !isNativeEvent(event, exceptionEntry)
  88. ) {
  89. return false;
  90. }
  91. return true;
  92. }