useTraceMeta.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import {useMemo} from 'react';
  2. import type {Location} from 'history';
  3. import * as qs from 'query-string';
  4. import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
  5. import {DEFAULT_STATS_PERIOD} from 'sentry/constants';
  6. import type {PageFilters} from 'sentry/types/core';
  7. import type {TraceMeta} from 'sentry/utils/performance/quickTrace/types';
  8. import {useApiQuery, type UseApiQueryResult} from 'sentry/utils/queryClient';
  9. import {decodeScalar} from 'sentry/utils/queryString';
  10. import useOrganization from 'sentry/utils/useOrganization';
  11. import usePageFilters from 'sentry/utils/usePageFilters';
  12. import {useParams} from 'sentry/utils/useParams';
  13. function getMetaQueryParams(
  14. query: Location['query'],
  15. filters: Partial<PageFilters> = {}
  16. ):
  17. | {
  18. // demo has the format ${projectSlug}:${eventId}
  19. // used to query a demo transaction event from the backend.
  20. demo: string | undefined;
  21. statsPeriod: string;
  22. }
  23. | {
  24. demo: string | undefined;
  25. timestamp: string;
  26. } {
  27. const normalizedParams = normalizeDateTimeParams(query, {
  28. allowAbsolutePageDatetime: true,
  29. });
  30. const statsPeriod = decodeScalar(normalizedParams.statsPeriod);
  31. const timestamp = decodeScalar(normalizedParams.timestamp);
  32. if (timestamp) {
  33. return {timestamp, demo: decodeScalar(normalizedParams.demo)};
  34. }
  35. return {
  36. statsPeriod: (statsPeriod || filters?.datetime?.period) ?? DEFAULT_STATS_PERIOD,
  37. demo: decodeScalar(normalizedParams.demo),
  38. };
  39. }
  40. export function useTraceMeta(
  41. traceSlug?: string
  42. ): UseApiQueryResult<TraceMeta | null, any> {
  43. const filters = usePageFilters();
  44. const organization = useOrganization();
  45. const params = useParams<{traceSlug?: string}>();
  46. const queryParams = useMemo(() => {
  47. const query = qs.parse(location.search);
  48. return getMetaQueryParams(query, filters.selection);
  49. // eslint-disable-next-line react-hooks/exhaustive-deps
  50. }, []);
  51. const mode = queryParams.demo ? 'demo' : undefined;
  52. const trace = traceSlug ?? params.traceSlug;
  53. const traceMetaQueryResults = useApiQuery<TraceMeta>(
  54. [
  55. `/organizations/${organization.slug}/events-trace-meta/${trace ?? ''}/`,
  56. {query: queryParams},
  57. ],
  58. {
  59. staleTime: Infinity,
  60. enabled: !!trace && !!organization.slug && mode !== 'demo',
  61. }
  62. );
  63. // When projects don't have performance set up, we allow them to view a sample transaction.
  64. // The backend creates the sample transaction, however the trace is created async, so when the
  65. // page loads, we cannot guarantee that querying the trace will succeed as it may not have been stored yet.
  66. // When this happens, we assemble a fake trace response to only include the transaction that had already been
  67. // created and stored already so that the users can visualize in the context of a trace.
  68. // The trace meta query has to reflect this by returning a single transaction and project.
  69. if (mode === 'demo') {
  70. return {
  71. data: {
  72. errors: 0,
  73. performance_issues: 0,
  74. projects: 1,
  75. transactions: 1,
  76. },
  77. failureCount: 0,
  78. errorUpdateCount: 0,
  79. failureReason: null,
  80. error: null,
  81. isError: false,
  82. isFetched: true,
  83. isFetchedAfterMount: true,
  84. isFetching: false,
  85. isLoading: false,
  86. isLoadingError: false,
  87. isInitialLoading: false,
  88. isPaused: false,
  89. isPlaceholderData: false,
  90. isPreviousData: false,
  91. isRefetchError: false,
  92. isRefetching: false,
  93. isStale: false,
  94. isSuccess: true,
  95. status: 'success',
  96. fetchStatus: 'idle',
  97. dataUpdatedAt: Date.now(),
  98. errorUpdatedAt: Date.now(),
  99. refetch: traceMetaQueryResults.refetch,
  100. remove: traceMetaQueryResults.remove,
  101. };
  102. }
  103. return traceMetaQueryResults;
  104. }