profileGroupProvider.tsx 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import {createContext, useContext, useMemo} from 'react';
  2. import * as Sentry from '@sentry/react';
  3. import type {Frame} from 'sentry/utils/profiling/frame';
  4. import type {ProfileGroup} from 'sentry/utils/profiling/profile/importProfile';
  5. import {importProfile} from 'sentry/utils/profiling/profile/importProfile';
  6. type ProfileGroupContextValue = ProfileGroup;
  7. const ProfileGroupContext = createContext<ProfileGroupContextValue | null>(null);
  8. export function useProfileGroup() {
  9. const context = useContext(ProfileGroupContext);
  10. if (!context) {
  11. throw new Error('useProfileGroup was called outside of ProfileGroupProvider');
  12. }
  13. return context;
  14. }
  15. export const LOADING_PROFILE_GROUP: Readonly<ProfileGroup> = {
  16. name: 'Loading',
  17. activeProfileIndex: 0,
  18. transactionID: null,
  19. metadata: {},
  20. measurements: {},
  21. traceID: '',
  22. profiles: [],
  23. };
  24. interface ProfileGroupProviderProps {
  25. children: React.ReactNode;
  26. input: Readonly<Profiling.ProfileInput> | null;
  27. traceID: string;
  28. type: 'flamegraph' | 'flamechart';
  29. frameFilter?: (frame: Frame) => boolean;
  30. }
  31. export function ProfileGroupProvider(props: ProfileGroupProviderProps) {
  32. const profileGroup = useMemo(() => {
  33. if (!props.input) {
  34. return LOADING_PROFILE_GROUP;
  35. }
  36. try {
  37. return importProfile(props.input, props.traceID, props.type, props.frameFilter);
  38. } catch (err) {
  39. Sentry.captureException(err);
  40. return LOADING_PROFILE_GROUP;
  41. }
  42. }, [props.input, props.traceID, props.type, props.frameFilter]);
  43. return (
  44. <ProfileGroupContext.Provider value={profileGroup}>
  45. {props.children}
  46. </ProfileGroupContext.Provider>
  47. );
  48. }