profileGroupProvider.tsx 1.5 KB

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