@@ -74,6 +74,11 @@ function popActivity(activity: number | null): void {
74
74
( globalTracingIntegration as any ) . constructor . popActivity ( activity , undefined ) ;
75
75
}
76
76
77
+ /**
78
+ * Obtain a span given an activity id.
79
+ * Is a no-op if invalid Tracing integration.
80
+ * @param activity activity id associated with obtained span
81
+ */
77
82
function getActivitySpan ( activity : number | null ) : Span | undefined {
78
83
if ( globalTracingIntegration === null ) {
79
84
return undefined ;
@@ -86,13 +91,14 @@ function getActivitySpan(activity: number | null): Span | undefined {
86
91
export type ProfilerProps = {
87
92
// The name of the component being profiled.
88
93
name : string ;
89
- // If the Profiler is disabled. False by default.
94
+ // If the Profiler is disabled. False by default. This is useful if you want to disable profilers
95
+ // in certain environments.
90
96
disabled ?: boolean ;
91
97
// If time component is on page should be displayed as spans. False by default.
92
98
hasRenderSpan ?: boolean ;
93
99
// If component updates should be displayed as spans. True by default.
94
100
hasUpdateSpan ?: boolean ;
95
- // props from child component
101
+ // props given to component being profiled.
96
102
updateProps : { [ key : string ] : any } ;
97
103
} ;
98
104
@@ -147,25 +153,33 @@ class Profiler extends React.Component<ProfilerProps> {
147
153
}
148
154
}
149
155
150
- public componentDidUpdate ( prevProps : ProfilerProps ) : void {
151
- const { hasUpdateSpan = true } = prevProps ;
152
- if ( hasUpdateSpan && this . mountSpan && prevProps . updateProps !== this . props . updateProps ) {
153
- const changedProps = Object . keys ( prevProps ) . filter ( k => prevProps . updateProps [ k ] !== this . props . updateProps [ k ] ) ;
156
+ public componentDidUpdate ( { updateProps, hasUpdateSpan = true } : ProfilerProps ) : void {
157
+ // Only generate an update span if hasUpdateSpan is true, if there is a valid mountSpan,
158
+ // and if the updateProps have changed. It is ok to not do a deep equality check here as it is expensive.
159
+ // We are just trying to give baseline clues for further investigation.
160
+ if ( hasUpdateSpan && this . mountSpan && updateProps !== this . props . updateProps ) {
161
+ // See what props haved changed between the previous props, and the current props. This is
162
+ // set as data on the span. We just store the prop keys as the values could be potenially very large.
163
+ const changedProps = Object . keys ( updateProps ) . filter ( k => updateProps [ k ] !== this . props . updateProps [ k ] ) ;
154
164
if ( changedProps . length > 0 ) {
165
+ // The update span is a point in time span with 0 duration, just signifying that the component
166
+ // has been updated.
155
167
const now = timestampWithMs ( ) ;
156
- const updateSpan = this . mountSpan . startChild ( {
157
- description : `<${ prevProps . name } >` ,
168
+ this . mountSpan . startChild ( {
169
+ data : {
170
+ changedProps,
171
+ } ,
172
+ description : `<${ this . props . name } >` ,
158
173
endTimestamp : now ,
159
174
op : `react.update` ,
160
175
startTimestamp : now ,
161
176
} ) ;
162
-
163
- updateSpan . setData ( 'changedProps' , changedProps ) ;
164
177
}
165
178
}
166
179
}
167
180
168
- // If a component doesn't mount, the render activity will be end when the
181
+ // If a component is unmounted, we can say it is no longer on the screen.
182
+ // This means we can finish the span representing the component render.
169
183
public componentWillUnmount ( ) : void {
170
184
if ( this . renderSpan ) {
171
185
this . renderSpan . finish ( ) ;
@@ -179,13 +193,16 @@ class Profiler extends React.Component<ProfilerProps> {
179
193
180
194
/**
181
195
* withProfiler is a higher order component that wraps a
182
- * component in a {@link Profiler} component.
196
+ * component in a {@link Profiler} component. It is recommended that
197
+ * the higher order component be used over the regular {@link Profiler} component.
183
198
*
184
199
* @param WrappedComponent component that is wrapped by Profiler
185
200
* @param options the {@link ProfilerProps} you can pass into the Profiler
186
201
*/
187
202
function withProfiler < P extends object > (
188
203
WrappedComponent : React . ComponentType < P > ,
204
+ // We do not want to have `updateProps` given in options, it is instead filled through
205
+ // the HOC.
189
206
options ?: Pick < Partial < ProfilerProps > , Exclude < keyof ProfilerProps , 'updateProps' > > ,
190
207
) : React . FC < P > {
191
208
const componentDisplayName =
0 commit comments