default.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import type {BreadcrumbTransactionEvent} from 'sentry/components/events/interfaces/breadcrumbs/types';
  2. import {AnnotatedText} from 'sentry/components/events/meta/annotatedText';
  3. import Highlight from 'sentry/components/highlight';
  4. import Link from 'sentry/components/links/link';
  5. import type {
  6. BreadcrumbTypeDefault,
  7. BreadcrumbTypeNavigation,
  8. } from 'sentry/types/breadcrumbs';
  9. import type {Event} from 'sentry/types/event';
  10. import type {Organization} from 'sentry/types/organization';
  11. import {defined} from 'sentry/utils';
  12. import {generateLinkToEventInTraceView} from 'sentry/utils/discover/urls';
  13. import {useLocation} from 'sentry/utils/useLocation';
  14. import useProjects from 'sentry/utils/useProjects';
  15. import Summary from './summary';
  16. type Props = {
  17. breadcrumb: BreadcrumbTypeDefault | BreadcrumbTypeNavigation;
  18. organization: Organization;
  19. searchTerm: string;
  20. event?: Event;
  21. meta?: Record<any, any>;
  22. transactionEvents?: BreadcrumbTransactionEvent[];
  23. };
  24. export function Default({
  25. meta,
  26. breadcrumb,
  27. event,
  28. organization,
  29. searchTerm,
  30. transactionEvents,
  31. }: Props) {
  32. const {message, data} = breadcrumb;
  33. return (
  34. <Summary kvData={data} meta={meta}>
  35. {meta?.message?.[''] ? (
  36. <AnnotatedText value={message} meta={meta?.message?.['']} />
  37. ) : (
  38. defined(message) && (
  39. <FormatMessage
  40. searchTerm={searchTerm}
  41. event={event}
  42. organization={organization}
  43. breadcrumb={breadcrumb}
  44. message={message}
  45. transactionEvents={transactionEvents}
  46. />
  47. )
  48. )}
  49. </Summary>
  50. );
  51. }
  52. export function isEventId(maybeEventId: string): boolean {
  53. // maybeEventId is an event id if it's a hex string of 32 characters long
  54. return /^[a-fA-F0-9]{32}$/.test(maybeEventId);
  55. }
  56. function FormatMessage({
  57. searchTerm,
  58. event,
  59. message,
  60. breadcrumb,
  61. organization,
  62. transactionEvents,
  63. }: {
  64. breadcrumb: BreadcrumbTypeDefault | BreadcrumbTypeNavigation;
  65. message: string;
  66. organization: Organization;
  67. searchTerm: string;
  68. event?: Event;
  69. transactionEvents?: BreadcrumbTransactionEvent[];
  70. }) {
  71. const location = useLocation();
  72. const content = <Highlight text={searchTerm}>{message}</Highlight>;
  73. const isSentryTransaction =
  74. breadcrumb.category === 'sentry.transaction' && isEventId(message);
  75. const {projects, fetching: fetchingProjects} = useProjects();
  76. const maybeProject = !fetchingProjects
  77. ? projects.find(project => {
  78. return event && project.id === event.projectID;
  79. })
  80. : null;
  81. const transactionData = transactionEvents?.find(
  82. transaction => transaction.id === message
  83. );
  84. if (isSentryTransaction) {
  85. if (!maybeProject) {
  86. return content;
  87. }
  88. const projectSlug = maybeProject.slug;
  89. const description = transactionData ? (
  90. <Link
  91. to={generateLinkToEventInTraceView({
  92. eventId: message,
  93. timestamp: event?.endTimestamp ?? '',
  94. traceSlug: event?.contexts?.trace?.trace_id ?? '',
  95. projectSlug,
  96. organization,
  97. location: {...location, query: {...location.query, referrer: 'breadcrumbs'}},
  98. })}
  99. >
  100. <Highlight text={searchTerm}>{transactionData.title}</Highlight>
  101. </Link>
  102. ) : (
  103. content
  104. );
  105. return description;
  106. }
  107. return content;
  108. }