events.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import {
  2. BaseGroup,
  3. EventMetadata,
  4. EventOrGroupType,
  5. GroupTombstone,
  6. TreeLabelPart,
  7. } from 'app/types';
  8. import {Event} from 'app/types/event';
  9. import {isNativePlatform} from 'app/utils/platform';
  10. function isTombstone(maybe: BaseGroup | Event | GroupTombstone): maybe is GroupTombstone {
  11. return !maybe.hasOwnProperty('type');
  12. }
  13. /**
  14. * Extract the display message from an event.
  15. */
  16. export function getMessage(
  17. event: Event | BaseGroup | GroupTombstone
  18. ): string | undefined {
  19. if (isTombstone(event)) {
  20. return event.culprit || '';
  21. }
  22. const {metadata, type, culprit} = event;
  23. switch (type) {
  24. case EventOrGroupType.ERROR:
  25. return metadata.value;
  26. case EventOrGroupType.CSP:
  27. return metadata.message;
  28. case EventOrGroupType.EXPECTCT:
  29. case EventOrGroupType.EXPECTSTAPLE:
  30. case EventOrGroupType.HPKP:
  31. return '';
  32. default:
  33. return culprit || '';
  34. }
  35. }
  36. /**
  37. * Get the location from an event.
  38. */
  39. export function getLocation(event: Event | BaseGroup | GroupTombstone) {
  40. if (isTombstone(event)) {
  41. return undefined;
  42. }
  43. if (event.type === EventOrGroupType.ERROR && isNativePlatform(event.platform)) {
  44. return event.metadata.filename || undefined;
  45. }
  46. return undefined;
  47. }
  48. export function getTreeLabelPartDetails(part: TreeLabelPart) {
  49. // Note: This function also exists in Python in eventtypes/base.py, to make
  50. // porting efforts simpler it's recommended to keep both variants
  51. // structurally similar.
  52. if (typeof part === 'string') {
  53. return {
  54. label: part,
  55. highlight: false,
  56. };
  57. }
  58. let label = part?.function || part?.package || part?.filebase || part?.type;
  59. const classbase = part?.classbase;
  60. if (classbase) {
  61. if (label) {
  62. label = `${classbase}.${label}`;
  63. } else {
  64. label = classbase;
  65. }
  66. }
  67. return {
  68. label: label || '<unknown>',
  69. highlight: !!part.is_sentinel,
  70. };
  71. }
  72. function computeTitleWithTreeLabel(metadata: EventMetadata, features: string[] = []) {
  73. const {type, current_tree_label, finest_tree_label} = metadata;
  74. const treeLabel = features.includes('grouping-title-ui')
  75. ? current_tree_label || finest_tree_label
  76. : undefined;
  77. const formattedTreeLabel = treeLabel
  78. ? treeLabel.map(labelPart => getTreeLabelPartDetails(labelPart).label).join(' | ')
  79. : undefined;
  80. if (!type) {
  81. return {
  82. title: formattedTreeLabel || metadata.function || '<unknown>',
  83. treeLabel,
  84. };
  85. }
  86. if (!formattedTreeLabel) {
  87. return {title: type, treeLabel: undefined};
  88. }
  89. return {
  90. title: `${type} | ${formattedTreeLabel}`,
  91. treeLabel: [{type}, ...(treeLabel ?? [])],
  92. };
  93. }
  94. export function getTitle(event: Event | BaseGroup, features: string[] = []) {
  95. const {metadata, type, culprit} = event;
  96. const customTitle =
  97. features.includes('custom-event-title') && metadata?.title
  98. ? metadata.title
  99. : undefined;
  100. switch (type) {
  101. case EventOrGroupType.ERROR: {
  102. if (customTitle) {
  103. return {
  104. title: customTitle,
  105. subtitle: culprit,
  106. treeLabel: undefined,
  107. };
  108. }
  109. return {
  110. subtitle: culprit,
  111. ...computeTitleWithTreeLabel(metadata, features),
  112. };
  113. }
  114. case EventOrGroupType.CSP:
  115. return {
  116. title: customTitle ?? metadata.directive ?? '',
  117. subtitle: metadata.uri ?? '',
  118. treeLabel: undefined,
  119. };
  120. case EventOrGroupType.EXPECTCT:
  121. case EventOrGroupType.EXPECTSTAPLE:
  122. case EventOrGroupType.HPKP:
  123. // Due to a regression some reports did not have message persisted
  124. // (https://github.com/getsentry/sentry/pull/19794) so we need to fall
  125. // back to the computed title for these.
  126. return {
  127. title: customTitle ?? (metadata.message || event.title),
  128. subtitle: metadata.origin ?? '',
  129. treeLabel: undefined,
  130. };
  131. case EventOrGroupType.DEFAULT:
  132. return {
  133. title: customTitle ?? metadata.title ?? '',
  134. subtitle: '',
  135. treeLabel: undefined,
  136. };
  137. default:
  138. return {
  139. title: customTitle ?? event.title,
  140. subtitle: '',
  141. treeLabel: undefined,
  142. };
  143. }
  144. }
  145. /**
  146. * Returns a short eventId with only 8 characters
  147. */
  148. export function getShortEventId(eventId: string) {
  149. return eventId.substring(0, 8);
  150. }