transactionProfileIdProvider.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import {createContext, useContext, useEffect, useMemo} from 'react';
  2. import * as Sentry from '@sentry/react';
  3. import type {PageFilters} from 'sentry/types/core';
  4. import {useProfileEvents} from 'sentry/utils/profiling/hooks/useProfileEvents';
  5. const TransactionProfileContext = createContext<string | null | undefined>(undefined);
  6. interface TransactionToProfileIdProviderProps {
  7. children: React.ReactNode;
  8. timestamp: string | undefined;
  9. transactionId: string | undefined;
  10. projectId?: string | undefined;
  11. }
  12. export function TransactionProfileIdProvider({
  13. projectId,
  14. timestamp,
  15. transactionId,
  16. children,
  17. }: TransactionToProfileIdProviderProps) {
  18. // create a 24h timeframe relative from the transaction timestamp to use for
  19. // the profile events query
  20. const datetime: PageFilters['datetime'] | undefined = useMemo(() => {
  21. if (!timestamp) {
  22. return undefined;
  23. }
  24. const ts = new Date(timestamp);
  25. const start = new Date(new Date(ts).setHours(ts.getHours() - 12));
  26. const end = new Date(new Date(ts).setHours(ts.getHours() + 12));
  27. return {
  28. start,
  29. end,
  30. period: null,
  31. utc: true,
  32. };
  33. }, [timestamp]);
  34. const transactionIdColumn = 'id';
  35. const {status, data, error} = useProfileEvents({
  36. projects: projectId ? [projectId] : undefined,
  37. fields: ['profile.id'],
  38. referrer: 'transactionToProfileProvider',
  39. limit: 1,
  40. sort: {
  41. key: 'id',
  42. order: 'asc',
  43. },
  44. query: `${transactionIdColumn}:${transactionId}`,
  45. enabled: Boolean(transactionId),
  46. datetime,
  47. });
  48. useEffect(() => {
  49. if (status !== 'error') {
  50. return;
  51. }
  52. if (error.status !== 404) {
  53. Sentry.captureException(error);
  54. }
  55. }, [status, error]);
  56. const profileId = (data?.data[0]?.['profile.id'] as string | undefined) ?? null;
  57. return (
  58. <TransactionProfileContext.Provider value={profileId}>
  59. {children}
  60. </TransactionProfileContext.Provider>
  61. );
  62. }
  63. TransactionProfileIdProvider.Context = TransactionProfileContext;
  64. export function useTransactionProfileId() {
  65. const ctx = useContext(TransactionProfileContext);
  66. if (typeof ctx === 'undefined') {
  67. throw new Error(`useTransactionProfile called outside of TransactionProfileProvider`);
  68. }
  69. return ctx;
  70. }