-
Notifications
You must be signed in to change notification settings - Fork 314
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Add logger to measure performance metrics (#782)
- Loading branch information
1 parent
4a84274
commit 7aa67da
Showing
35 changed files
with
752 additions
and
67 deletions.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
// @flow | ||
import * as React from 'react'; | ||
import noop from 'lodash/noop'; | ||
import uuidv4 from 'uuid/v4'; | ||
import { isMarkSupported } from '../../../utils/performance'; | ||
import { EVENT_JS_READY } from './constants'; | ||
import { METRIC_TYPE_PREVIEW, METRIC_TYPE_ELEMENTS_LOAD_METRIC } from '../../../constants'; | ||
|
||
type ElementsMetric = { | ||
component: ElementOrigin, | ||
name: string, | ||
sessionId: string, | ||
timestamp: string, | ||
type: MetricType, | ||
} & ElementsLoadMetricData; | ||
|
||
type Props = { | ||
fileId?: string, | ||
onMetric: (data: Object) => void, | ||
children: React.ChildrenArray<React.Element<any>>, | ||
source: ElementOrigin, | ||
startMarkName?: string, | ||
}; | ||
|
||
const SESSION_ID = uuidv4(); | ||
const uniqueEvents: Set<string> = new Set(); | ||
|
||
class Logger extends React.Component<Props> { | ||
static defaultProps = { | ||
onMetric: noop, | ||
}; | ||
|
||
constructor(props: Props) { | ||
super(props); | ||
this.loggerProps = { | ||
onPreviewMetric: this.handlePreviewMetric, | ||
onReadyMetric: this.handleReadyMetric, | ||
}; | ||
} | ||
|
||
loggerProps: LoggerProps; | ||
|
||
get uniqueEvents(): Set<string> { | ||
return uniqueEvents; | ||
} | ||
|
||
get sessionId(): string { | ||
return SESSION_ID; | ||
} | ||
|
||
/** | ||
* Creates an event name meant for use with an event which is unique and meant to be logged only once | ||
* | ||
* @param {string} name - The event name | ||
* @returns {string} A string containing the component and event name | ||
*/ | ||
createEventName(name: string): string { | ||
const { source } = this.props; | ||
return `${source}::${name}`; | ||
} | ||
|
||
/** | ||
* Checks to see if the specified event for the component has already been fired. | ||
* | ||
* @param {string} component - the component name | ||
* @param {string} name - the event name | ||
* @returns {boolean} True if the event has already been fired | ||
*/ | ||
hasLoggedEvent(name: string): boolean { | ||
return this.uniqueEvents.has(name); | ||
} | ||
|
||
/** | ||
* Invokes the provided metric logging callback. | ||
* | ||
* @param {string} type - the type of the event | ||
* @param {string} name - the name of the event | ||
* @param {Object} data - the event data | ||
*/ | ||
logMetric(type: MetricType, name: string, data: Object): void { | ||
const { onMetric, source } = this.props; | ||
const metric: ElementsMetric = { | ||
...data, | ||
component: source, | ||
name, | ||
timestamp: this.getTimestamp(), | ||
sessionId: this.sessionId, | ||
type, | ||
}; | ||
|
||
onMetric(metric); | ||
} | ||
|
||
/** | ||
* Logs a unique metric event. Prevents duplicate events from being logged in the session. | ||
* | ||
* @param {string} type - the type of the event | ||
* @param {string} name - the name of the event | ||
* @param {Object} data - the event data | ||
*/ | ||
logUniqueMetric(type: MetricType, name: string, data: Object): void { | ||
const eventName = this.createEventName(name); | ||
if (this.hasLoggedEvent(eventName)) { | ||
return; | ||
} | ||
|
||
this.logMetric(type, name, data); | ||
this.uniqueEvents.add(eventName); | ||
} | ||
|
||
/** | ||
* Preview metric handler | ||
* | ||
* @param {Object} data - the metric data | ||
* @returns {void} | ||
*/ | ||
handlePreviewMetric = (data: Object) => { | ||
const { onMetric } = this.props; | ||
onMetric({ | ||
...data, | ||
type: METRIC_TYPE_PREVIEW, | ||
}); | ||
}; | ||
|
||
/** | ||
* JS ready metric handler | ||
* | ||
* @param {Object} data - the metric data | ||
* @returns {void} | ||
*/ | ||
handleReadyMetric = (data: ElementsLoadMetricData) => { | ||
if (!isMarkSupported) { | ||
return; | ||
} | ||
|
||
const { startMarkName } = this.props; | ||
const metricData = { | ||
...data, | ||
startMarkName, | ||
}; | ||
this.logUniqueMetric(METRIC_TYPE_ELEMENTS_LOAD_METRIC, EVENT_JS_READY, metricData); | ||
}; | ||
|
||
/** | ||
* Create an ISO Timestamp for right now. | ||
* | ||
* @returns {string} | ||
*/ | ||
getTimestamp(): string { | ||
return new Date().toISOString(); | ||
} | ||
|
||
render() { | ||
const { children, onMetric, startMarkName, ...rest } = this.props; | ||
|
||
return React.cloneElement(children, { | ||
...rest, | ||
logger: this.loggerProps, | ||
}); | ||
} | ||
} | ||
|
||
export default Logger; |
Oops, something went wrong.