1
- import { createContext , useContext , useLayoutEffect , useMemo , useState } from 'react' ;
2
- import * as Sentry from '@sentry/react' ;
1
+ import { useMemo , useState } from 'react' ;
3
2
4
- import type { Client } from 'sentry/api' ;
5
3
import { ContinuousProfileHeader } from 'sentry/components/profiling/continuousProfileHeader' ;
6
4
import type { RequestState } from 'sentry/types/core' ;
7
5
import type { EventTransaction } from 'sentry/types/event' ;
8
- import type { Organization } from 'sentry/types/organization' ;
9
- import type { Project } from 'sentry/types/project' ;
10
6
import { useSentryEvent } from 'sentry/utils/profiling/hooks/useSentryEvent' ;
11
7
import { decodeScalar } from 'sentry/utils/queryString' ;
12
- import useApi from 'sentry/utils/useApi' ;
13
8
import { useLocation } from 'sentry/utils/useLocation' ;
14
9
import useOrganization from 'sentry/utils/useOrganization' ;
15
10
import { useParams } from 'sentry/utils/useParams' ;
16
- import useProjects from 'sentry/utils/useProjects' ;
17
11
18
- interface ContinuousProfileQueryParams {
19
- end : string ;
20
- profiler_id : string ;
21
- start : string ;
22
- }
23
-
24
- function fetchContinuousProfileFlamegraph (
25
- api : Client ,
26
- query : ContinuousProfileQueryParams ,
27
- projectSlug : Project [ 'slug' ] ,
28
- orgSlug : Organization [ 'slug' ]
29
- ) : Promise < Profiling . ProfileInput > {
30
- return api
31
- . requestPromise ( `/organizations/${ orgSlug } /profiling/chunks/` , {
32
- method : 'GET' ,
33
- query : {
34
- ...query ,
35
- project : projectSlug ,
36
- } ,
37
- includeAllArgs : true ,
38
- } )
39
- . then ( ( [ data ] ) => data . chunk ) ;
40
- }
41
-
42
- type ContinuousProfileProviderValue = RequestState < Profiling . ProfileInput > ;
43
- export const ContinuousProfileContext =
44
- createContext < ContinuousProfileProviderValue | null > ( null ) ;
45
-
46
- export function useContinuousProfile ( ) {
47
- const context = useContext ( ContinuousProfileContext ) ;
48
- if ( ! context ) {
49
- throw new Error ( 'useContinuousProfile was called outside of ProfileProvider' ) ;
50
- }
51
- return context ;
52
- }
53
-
54
- type ContinuousProfileSegmentProviderValue = RequestState < EventTransaction > ;
55
- export const ContinuousProfileSegmentContext =
56
- createContext < ContinuousProfileSegmentProviderValue | null > ( null ) ;
57
-
58
- export function useContinuousProfileSegment ( ) {
59
- const context = useContext ( ContinuousProfileSegmentContext ) ;
60
- if ( ! context ) {
61
- throw new Error (
62
- 'useContinuousProfileSegment was called outside of ContinuousProfileSegmentProvider'
63
- ) ;
64
- }
65
- return context ;
66
- }
12
+ import { ContinuousProfileProvider , ProfileTransactionContext } from './profilesProvider' ;
67
13
68
14
function isValidDate ( date : string ) : boolean {
69
15
return ! isNaN ( Date . parse ( date ) ) ;
@@ -73,7 +19,9 @@ interface FlamegraphViewProps {
73
19
children : React . ReactNode ;
74
20
}
75
21
76
- function ProfilesAndTransactionProvider ( props : FlamegraphViewProps ) : React . ReactElement {
22
+ export default function ProfileAndTransactionProvider (
23
+ props : FlamegraphViewProps
24
+ ) : React . ReactElement {
77
25
const organization = useOrganization ( ) ;
78
26
const params = useParams ( ) ;
79
27
const location = useLocation ( ) ;
@@ -100,88 +48,33 @@ function ProfilesAndTransactionProvider(props: FlamegraphViewProps): React.React
100
48
} ;
101
49
} , [ location . query . start , location . query . end , location . query . profilerId ] ) ;
102
50
51
+ const [ profile , setProfile ] = useState < RequestState < Profiling . ProfileInput > > ( {
52
+ type : 'initial' ,
53
+ } ) ;
54
+
103
55
const profileTransaction = useSentryEvent < EventTransaction > (
104
56
organization . slug ,
105
57
projectSlug ! ,
106
58
decodeScalar ( location . query . eventId ) || null
107
59
) ;
108
60
109
61
return (
110
- < ProfilesProvider
62
+ < ContinuousProfileProvider
111
63
orgSlug = { organization . slug }
112
64
profileMeta = { profileMeta }
113
65
projectSlug = { projectSlug }
66
+ profile = { profile }
67
+ setProfile = { setProfile }
114
68
>
115
- < ContinuousProfileSegmentContext . Provider value = { profileTransaction } >
69
+ < ProfileTransactionContext . Provider value = { profileTransaction } >
116
70
< ContinuousProfileHeader
117
71
projectId = { projectSlug }
118
72
transaction = {
119
73
profileTransaction . type === 'resolved' ? profileTransaction . data : null
120
74
}
121
75
/>
122
76
{ props . children }
123
- </ ContinuousProfileSegmentContext . Provider >
124
- </ ProfilesProvider >
77
+ </ ProfileTransactionContext . Provider >
78
+ </ ContinuousProfileProvider >
125
79
) ;
126
80
}
127
-
128
- interface ProfilesProviderProps {
129
- children : React . ReactNode ;
130
- orgSlug : Organization [ 'slug' ] ;
131
- profileMeta : ContinuousProfileQueryParams | null ;
132
- projectSlug : Project [ 'slug' ] ;
133
- onUpdateProfiles ?: ( profiles : RequestState < Profiling . ProfileInput > ) => void ;
134
- }
135
-
136
- export function ProfilesProvider ( {
137
- children,
138
- onUpdateProfiles,
139
- orgSlug,
140
- profileMeta,
141
- projectSlug,
142
- } : ProfilesProviderProps ) {
143
- const api = useApi ( ) ;
144
- const { projects} = useProjects ( ) ;
145
-
146
- const [ profiles , setProfiles ] = useState < RequestState < Profiling . ProfileInput > > ( {
147
- type : 'initial' ,
148
- } ) ;
149
-
150
- useLayoutEffect ( ( ) => {
151
- if ( ! profileMeta ) {
152
- Sentry . captureMessage (
153
- 'Failed to fetch continuous profile - invalid chunk parameters.'
154
- ) ;
155
- return undefined ;
156
- }
157
-
158
- const project = projects . find ( p => p . slug === projectSlug ) ;
159
- if ( ! project ) {
160
- Sentry . captureMessage ( 'Failed to fetch continuous profile - project not found.' ) ;
161
- return undefined ;
162
- }
163
-
164
- setProfiles ( { type : 'loading' } ) ;
165
-
166
- fetchContinuousProfileFlamegraph ( api , profileMeta , project . id , orgSlug )
167
- . then ( p => {
168
- setProfiles ( { type : 'resolved' , data : p } ) ;
169
- onUpdateProfiles ?.( { type : 'resolved' , data : p } ) ;
170
- } )
171
- . catch ( err => {
172
- setProfiles ( { type : 'errored' , error : 'Failed to fetch profiles' } ) ;
173
- onUpdateProfiles ?.( { type : 'errored' , error : 'Failed to fetch profiles' } ) ;
174
- Sentry . captureException ( err ) ;
175
- } ) ;
176
-
177
- return ( ) => api . clear ( ) ;
178
- } , [ api , onUpdateProfiles , profileMeta , orgSlug , projectSlug , projects ] ) ;
179
-
180
- return (
181
- < ContinuousProfileContext . Provider value = { profiles } >
182
- { children }
183
- </ ContinuousProfileContext . Provider >
184
- ) ;
185
- }
186
-
187
- export default ProfilesAndTransactionProvider ;
0 commit comments