@@ -10,35 +10,6 @@ const TRACING_GETTER = ({
10
10
id : 'Tracing' ,
11
11
} as any ) as IntegrationClass < Integration > ;
12
12
13
- /**
14
- *
15
- * Based on implementation from Preact:
16
- * https:github.com/preactjs/preact/blob/9a422017fec6dab287c77c3aef63c7b2fef0c7e1/hooks/src/index.js#L301-L313
17
- *
18
- * Schedule a callback to be invoked after the browser has a chance to paint a new frame.
19
- * Do this by combining requestAnimationFrame (rAF) + setTimeout to invoke a callback after
20
- * the next browser frame.
21
- *
22
- * Also, schedule a timeout in parallel to the the rAF to ensure the callback is invoked
23
- * even if RAF doesn't fire (for example if the browser tab is not visible)
24
- *
25
- * This is what we use to tell if a component activity has finished
26
- *
27
- */
28
- function afterNextFrame ( callback : Function ) : void {
29
- let timeout : number | undefined ;
30
- let raf : number ;
31
-
32
- const done = ( ) => {
33
- window . clearTimeout ( timeout ) ;
34
- window . cancelAnimationFrame ( raf ) ;
35
- window . setTimeout ( callback ) ;
36
- } ;
37
-
38
- raf = window . requestAnimationFrame ( done ) ;
39
- timeout = window . setTimeout ( done , 100 ) ;
40
- }
41
-
42
13
let globalTracingIntegration : Integration | null = null ;
43
14
const getTracingIntegration = ( ) => {
44
15
if ( globalTracingIntegration ) {
@@ -119,6 +90,8 @@ export type ProfilerProps = {
119
90
disabled ?: boolean ;
120
91
// If component updates should be displayed as spans. False by default.
121
92
generateUpdateSpans ?: boolean ;
93
+ // If time component is on page should be displayed as spans. True by default.
94
+ generateRenderSpans ?: boolean ;
122
95
// props from child component
123
96
updateProps : { [ key : string ] : any } ;
124
97
} ;
@@ -131,14 +104,14 @@ class Profiler extends React.Component<ProfilerProps> {
131
104
// The activity representing how long it takes to mount a component.
132
105
public mountActivity : number | null = null ;
133
106
// The span of the mount activity
134
- public span : Span | undefined = undefined ;
135
- // The activity representing how long a component was on the page.
136
- public renderActivity : number | null = null ;
107
+ public mountSpan : Span | undefined = undefined ;
108
+ // The span of the render
137
109
public renderSpan : Span | undefined = undefined ;
138
110
139
111
public static defaultProps : Partial < ProfilerProps > = {
140
112
disabled : false ,
141
- generateUpdateSpans : true ,
113
+ generateRenderSpans : true ,
114
+ generateUpdateSpans : false ,
142
115
} ;
143
116
144
117
public constructor ( props : ProfilerProps ) {
@@ -158,28 +131,26 @@ class Profiler extends React.Component<ProfilerProps> {
158
131
159
132
// If a component mounted, we can finish the mount activity.
160
133
public componentDidMount ( ) : void {
161
- // afterNextFrame(() => {
162
- this . span = getActivitySpan ( this . mountActivity ) ;
134
+ this . mountSpan = getActivitySpan ( this . mountActivity ) ;
163
135
popActivity ( this . mountActivity ) ;
164
136
this . mountActivity = null ;
165
137
166
138
// If we were able to obtain the spanId of the mount activity, we should set the
167
139
// next activity as a child to the component mount activity.
168
- if ( this . span ) {
169
- this . renderSpan = this . span . startChild ( {
140
+ if ( this . mountSpan ) {
141
+ this . renderSpan = this . mountSpan . startChild ( {
170
142
description : `<${ this . props . name } >` ,
171
143
op : `react.render` ,
172
144
} ) ;
173
145
}
174
- // });
175
146
}
176
147
177
148
public componentDidUpdate ( prevProps : ProfilerProps ) : void {
178
- if ( prevProps . generateUpdateSpans && this . span && prevProps !== this . props ) {
149
+ if ( prevProps . generateUpdateSpans && this . mountSpan && prevProps . updateProps !== this . props . updateProps ) {
179
150
const changedProps = Object . keys ( prevProps ) . filter ( k => prevProps . updateProps [ k ] !== this . props . updateProps [ k ] ) ;
180
151
if ( changedProps . length > 0 ) {
181
152
const now = timestampWithMs ( ) ;
182
- const updateSpan = this . span . startChild ( {
153
+ const updateSpan = this . mountSpan . startChild ( {
183
154
description : `<${ prevProps . name } >` ,
184
155
endTimestamp : now ,
185
156
op : `react.update` ,
@@ -193,13 +164,9 @@ class Profiler extends React.Component<ProfilerProps> {
193
164
194
165
// If a component doesn't mount, the render activity will be end when the
195
166
public componentWillUnmount ( ) : void {
196
- afterNextFrame ( ( ) => {
197
- if ( this . renderSpan ) {
198
- this . renderSpan . finish ( ) ;
199
- }
200
- // popActivity(this.renderActivity);
201
- // this.renderActivity = null;
202
- } ) ;
167
+ if ( this . renderSpan ) {
168
+ this . renderSpan . finish ( ) ;
169
+ }
203
170
}
204
171
205
172
public render ( ) : React . ReactNode {
@@ -243,17 +210,31 @@ function withProfiler<P extends object>(
243
210
* @param name displayName of component being profiled
244
211
*/
245
212
function useProfiler ( name : string ) : void {
246
- const [ activity ] = React . useState ( ( ) => pushActivity ( name , 'mount' ) ) ;
213
+ const [ mountActivity ] = React . useState ( ( ) => {
214
+ if ( getTracingIntegration ( ) ) {
215
+ return pushActivity ( name , 'mount' ) ;
216
+ }
217
+
218
+ warnAboutTracing ( name ) ;
219
+ return null ;
220
+ } ) ;
247
221
248
222
React . useEffect ( ( ) => {
249
- afterNextFrame ( ( ) => {
250
- popActivity ( activity ) ;
251
- const renderActivity = pushActivity ( name , 'render' ) ;
252
-
253
- return ( ) => {
254
- popActivity ( renderActivity ) ;
255
- } ;
256
- } ) ;
223
+ const mountSpan = getActivitySpan ( mountActivity ) ;
224
+ popActivity ( mountActivity ) ;
225
+
226
+ const renderSpan = mountSpan
227
+ ? mountSpan . startChild ( {
228
+ description : `<${ name } >` ,
229
+ op : `react.render` ,
230
+ } )
231
+ : undefined ;
232
+
233
+ return ( ) => {
234
+ if ( renderSpan ) {
235
+ renderSpan . finish ( ) ;
236
+ }
237
+ } ;
257
238
} , [ ] ) ;
258
239
}
259
240
0 commit comments