@@ -3,19 +3,14 @@ import { Integration, IntegrationClass } from '@sentry/types';
33import { logger } from '@sentry/utils' ;
44import * as React from 'react' ;
55
6- /** The Props Injected by the HOC */
7- interface InjectedProps {
8- /** Called when a transaction is finished */
9- finishProfile ( ) : void ;
10- }
11-
12- const DEFAULT_DURATION = 30000 ;
6+ export const DEFAULT_DURATION = 30000 ;
7+ export const UNKNOWN_COMPONENT = 'unknown' ;
138
149const TRACING_GETTER = ( {
1510 id : 'Tracing' ,
1611} as any ) as IntegrationClass < Integration > ;
1712
18- const getInitActivity = ( componentDisplayName : string , timeout = DEFAULT_DURATION ) : number | null => {
13+ const getInitActivity = ( componentDisplayName : string , timeout : number ) : number | null => {
1914 const tracingIntegration = getCurrentHub ( ) . getIntegration ( TRACING_GETTER ) ;
2015
2116 if ( tracingIntegration !== null ) {
@@ -37,45 +32,63 @@ const getInitActivity = (componentDisplayName: string, timeout = DEFAULT_DURATIO
3732 return null ;
3833} ;
3934
40- /**
41- * withProfiler() is a HOC that leverages the Sentry AM tracing integration to
42- * send transactions about a React component.
43- * @param WrappedComponent The component profiled
44- * @param timeout A maximum timeout for the component render
45- */
46- export const withProfiler = < P extends object > ( WrappedComponent : React . ComponentType < P > , timeout ?: number ) => {
47- const componentDisplayName = WrappedComponent . displayName || WrappedComponent . name || 'Component' ;
35+ interface ProfilerProps {
36+ componentDisplayName ?: string ;
37+ timeout ?: number ;
38+ }
4839
49- return class extends React . Component < Omit < P , keyof InjectedProps > , { activity : number | null } > {
50- public static displayName : string = `profiler(${ componentDisplayName } )` ;
40+ interface ProfilerState {
41+ activity : number | null ;
42+ }
5143
52- public constructor ( props : P ) {
53- super ( props ) ;
44+ class Profiler extends React . Component < ProfilerProps , ProfilerState > {
45+ public constructor ( props : ProfilerProps ) {
46+ super ( props ) ;
5447
55- this . state = {
56- activity : getInitActivity ( componentDisplayName , timeout ) ,
57- } ;
58- }
48+ const { componentDisplayName = UNKNOWN_COMPONENT , timeout = DEFAULT_DURATION } = this . props ;
5949
60- public componentWillUnmount ( ) : void {
61- this . finishProfile ( ) ;
62- }
63-
64- public finishProfile = ( ) => {
65- if ( ! this . state . activity ) {
66- return ;
67- }
68-
69- const tracingIntegration = getCurrentHub ( ) . getIntegration ( TRACING_GETTER ) ;
70- if ( tracingIntegration !== null ) {
71- // tslint:disable-next-line:no-unsafe-any
72- ( tracingIntegration as any ) . constructor . popActivity ( this . state . activity ) ;
73- this . setState ( { activity : null } ) ;
74- }
50+ this . state = {
51+ activity : getInitActivity ( componentDisplayName , timeout ) ,
7552 } ;
53+ }
54+
55+ public componentWillUnmount ( ) : void {
56+ this . finishProfile ( ) ;
57+ }
58+
59+ public finishProfile = ( ) => {
60+ if ( ! this . state . activity ) {
61+ return ;
62+ }
7663
77- public render ( ) : React . ReactNode {
78- return < WrappedComponent { ...this . props as P } /> ;
64+ const tracingIntegration = getCurrentHub ( ) . getIntegration ( TRACING_GETTER ) ;
65+ if ( tracingIntegration !== null ) {
66+ // tslint:disable-next-line:no-unsafe-any
67+ ( tracingIntegration as any ) . constructor . popActivity ( this . state . activity ) ;
68+ this . setState ( { activity : null } ) ;
7969 }
8070 } ;
81- } ;
71+
72+ public render ( ) : React . ReactNode {
73+ return this . props . children ;
74+ }
75+ }
76+
77+ function withProfiler < P extends object > (
78+ WrappedComponent : React . ComponentType < P > ,
79+ profilerProps ?: ProfilerProps ,
80+ ) : React . FC < P > {
81+ const componentDisplayName = WrappedComponent . displayName || WrappedComponent . name || UNKNOWN_COMPONENT ;
82+
83+ const Wrapped : React . FC < P > = ( props : P ) => (
84+ < Profiler componentDisplayName = { componentDisplayName } { ...profilerProps } >
85+ < WrappedComponent { ...props } />
86+ </ Profiler >
87+ ) ;
88+
89+ Wrapped . displayName = `profiler(${ componentDisplayName } )` ;
90+
91+ return Wrapped ;
92+ }
93+
94+ export { withProfiler , Profiler } ;
0 commit comments