useReplaysCount.tsx 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import {useCallback, useEffect, useMemo, useState} from 'react';
  2. import * as Sentry from '@sentry/react';
  3. import {Organization, Project} from 'sentry/types';
  4. import {TableData} from 'sentry/utils/discover/discoverQuery';
  5. import EventView from 'sentry/utils/discover/eventView';
  6. import {doDiscoverQuery} from 'sentry/utils/discover/genericDiscoverQuery';
  7. import projectSupportsReplay from 'sentry/utils/replays/projectSupportsReplay';
  8. import toArray from 'sentry/utils/toArray';
  9. import useApi from 'sentry/utils/useApi';
  10. import {useLocation} from 'sentry/utils/useLocation';
  11. type Options = {
  12. organization: Organization;
  13. project: undefined | Project;
  14. groupIds?: string | string[];
  15. transactionNames?: string | string[];
  16. };
  17. function useReplaysCount({groupIds, transactionNames, organization, project}: Options) {
  18. const api = useApi();
  19. const location = useLocation();
  20. const [replayCounts, setReplayCounts] = useState<Record<string, undefined | number>>(
  21. {}
  22. );
  23. const [condition, fieldName] = useMemo(() => {
  24. if (groupIds === undefined && transactionNames === undefined) {
  25. throw new Error('Missing groupId or transactionName in useReplaysCount()');
  26. }
  27. if (groupIds && groupIds.length) {
  28. return [`issue.id:[${toArray(groupIds).join(',')}]`, 'issue.id'];
  29. }
  30. if (transactionNames && transactionNames.length) {
  31. return [
  32. `event.type:transaction transaction:[${toArray(transactionNames).join(',')}]`,
  33. 'transaction',
  34. ];
  35. }
  36. return [null, null];
  37. }, [groupIds, transactionNames]);
  38. const eventView = useMemo(
  39. () =>
  40. EventView.fromNewQueryWithLocation(
  41. {
  42. id: '',
  43. name: `Errors within replay`,
  44. version: 2,
  45. fields: ['count_unique(replayId)', String(fieldName)],
  46. query: `!replayId:"" ${condition}`,
  47. projects: [],
  48. },
  49. location
  50. ),
  51. [location, condition, fieldName]
  52. );
  53. const fetchReplayCount = useCallback(async () => {
  54. try {
  55. if (!condition || !fieldName) {
  56. return;
  57. }
  58. const [data] = await doDiscoverQuery<TableData>(
  59. api,
  60. `/organizations/${organization.slug}/events/`,
  61. eventView.getEventsAPIPayload(location)
  62. );
  63. const counts = data.data.reduce((obj, record) => {
  64. const key = record[fieldName];
  65. const val = record['count_unique(replayId)'];
  66. obj[key] = val;
  67. return obj;
  68. }, {});
  69. setReplayCounts(counts);
  70. } catch (err) {
  71. Sentry.captureException(err);
  72. }
  73. }, [api, location, organization.slug, condition, fieldName, eventView]);
  74. useEffect(() => {
  75. const hasSessionReplay =
  76. organization.features.includes('session-replay-ui') &&
  77. projectSupportsReplay(project);
  78. if (hasSessionReplay) {
  79. fetchReplayCount();
  80. }
  81. }, [fetchReplayCount, organization, project]);
  82. return replayCounts;
  83. }
  84. export default useReplaysCount;