profilingBreadcrumbs.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import {useMemo} from 'react';
  2. import {Location} from 'history';
  3. import omit from 'lodash/omit';
  4. import _Breadcrumbs, {Crumb} from 'sentry/components/breadcrumbs';
  5. import {t} from 'sentry/locale';
  6. import {Organization, Project} from 'sentry/types';
  7. import {
  8. generateProfileFlamechartRouteWithQuery,
  9. generateProfileSummaryRouteWithQuery,
  10. generateProfilingRouteWithQuery,
  11. } from 'sentry/utils/profiling/routes';
  12. export interface ProfilingBreadcrumbsProps {
  13. organization: Organization;
  14. trails: Trail[];
  15. }
  16. function ProfilingBreadcrumbs({organization, trails}: ProfilingBreadcrumbsProps) {
  17. const crumbs = useMemo(
  18. () => trails.map(trail => trailToCrumb(trail, {organization})),
  19. [organization, trails]
  20. );
  21. return <_Breadcrumbs crumbs={crumbs} />;
  22. }
  23. function trailToCrumb(
  24. trail: Trail,
  25. {
  26. organization,
  27. }: {
  28. organization: Organization;
  29. }
  30. ): Crumb {
  31. switch (trail.type) {
  32. case 'landing': {
  33. return {
  34. to: generateProfilingRouteWithQuery({
  35. // cursor and query are not used in the landing page
  36. // and break the API call as the qs gets forwarded to the API
  37. query: omit(trail.payload.query, ['cursor', 'query']),
  38. orgSlug: organization.slug,
  39. }),
  40. label: t('Profiling'),
  41. preservePageFilters: true,
  42. };
  43. }
  44. case 'profile summary': {
  45. return {
  46. to: generateProfileSummaryRouteWithQuery({
  47. // cursor and query are not used in the summary page
  48. // and break the API call as the qs gets forwarded to the API
  49. query: omit(trail.payload.query, ['cursor', 'query']),
  50. orgSlug: organization.slug,
  51. projectSlug: trail.payload.projectSlug,
  52. transaction: trail.payload.transaction,
  53. }),
  54. label: t('Profile Summary'),
  55. preservePageFilters: true,
  56. };
  57. }
  58. case 'flamechart': {
  59. return {
  60. to: generateProfileFlamechartRouteWithQuery({
  61. query: trail.payload.query,
  62. orgSlug: organization.slug,
  63. projectSlug: trail.payload.projectSlug,
  64. profileId: trail.payload.profileId,
  65. }),
  66. label: trail.payload.transaction,
  67. preservePageFilters: true,
  68. };
  69. }
  70. default:
  71. throw new Error(`Unknown breadcrumb type: ${JSON.stringify(trail)}`);
  72. }
  73. }
  74. type ProfilingTrail = {
  75. payload: {
  76. query: Location['query'];
  77. };
  78. type: 'landing';
  79. };
  80. type ProfileSummaryTrail = {
  81. payload: {
  82. projectSlug: Project['slug'];
  83. query: Location['query'];
  84. transaction: string;
  85. };
  86. type: 'profile summary';
  87. };
  88. type FlamegraphTrail = {
  89. payload: {
  90. profileId: string;
  91. projectSlug: string;
  92. query: Location['query'];
  93. transaction: string;
  94. };
  95. type: 'flamechart';
  96. };
  97. type Trail = ProfilingTrail | ProfileSummaryTrail | FlamegraphTrail;
  98. export {ProfilingBreadcrumbs};