Skip to content

Instantly share code, notes, and snippets.

@hakimelek
Created August 22, 2017 20:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hakimelek/357d33a6cb7ae0b11c09a07c200a22cf to your computer and use it in GitHub Desktop.
Save hakimelek/357d33a6cb7ae0b11c09a07c200a22cf to your computer and use it in GitHub Desktop.
Web performance object
/**
* Web performance object example:
*/
import 'performance-polyfill';
class WebPerfMetrics {
constructor() {
this.performance = window.performance || window.mozPerformance || window.msPerformance || window.webkitPerformance || {};
this.timing = (this.performance && this.performance.timing) ? this.performance.timing : null;
}
/*
* Latency (responseStart – fetchStart)
*
* @description
* How long it takes the response to get to the user’s browser.
* This includes the time it takes for the request to get to
* the server, the time it takes the server to render a response,
* and the time until the first byte of that response
* gets back to the user’s browser.
*
* @return {Number} Latency - How long it takes the response to get to the user’s browser (ms)
*/
getLatency() {
const timing = this.timing;
return timing ? timing.responseStart - timing.fetchStart : 0;
}
/*
* Transfer (responseEnd – responseStart)
*
* @description
* How long it takes the browser to download the response
* from the server.
*
* @return {Number} Transfer - How long it takes the browser to download the response from the server (ms)
*/
getTransfer() {
const timing = this.timing;
return timing ? timing.responseEnd - timing.responseStart : 0;
}
/*
* DOM Processing to Interactive (domInteractive – domLoading)
*
* @description
* How long the browser spends loading the webpage until the
* user can starting interacting with it.
*
* @return {Number} DomProcessingToInteractive - How long the browser spends loading the webpage until the user can starting interacting with it. (ms)
*/
getDomProcessingToInteractive() {
const timing = this.timing;
return timing ? timing.domInteractive - timing.domLoading : 0;
}
/*
* DOM Interactive to Complete (domComplete – domInteractive)
*
* @description
* How long it takes for the browser to load
* images/videos and execute any Javascript code
* listening for the DOMContentLoaded event.
*
* @return {Number} DomInteractiveToComplete - How long the browser spends loading the webpage until the user can starting interacting with it. (ms)
*/
getDomInteractiveToComplete() {
const timing = this.timing;
return timing ? timing.domComplete - timing.domInteractive : 0;
}
/*
* Onload (loadEventEnd – loadEventStart)
*
* @description
* How long it takes the browser to execute
* Javascript code waiting for the window.load event.
*
* @return {Number} onLoad - How long it takes the browser to execute Javascript code waiting for the window.load event. (ms)
*/
getOnload() {
const timing = this.timing;
return timing ? timing.loadEventEnd - timing.loadEventStart : 0;
}
/*
* getPerformanceData
*
* @description
* A function that returns the splunk performance data
* within a promise
*
* @return {Promise} - return the Splunk object containing performance data
*/
getPerformanceData() {
const self = this;
const promise = new Promise(
// The resolver function is called with the ability to resolve or
// reject the promise
(resolve, reject) => {
window.onload = function() {
setTimeout(function() {
let performanceEntries = [];
let getEntriesByTypeExists = false;
if (typeof self.performance.getEntries !== 'undefined' && typeof self.performance.getEntries === 'function') {
performanceEntries = self.performance.getEntries();
}
if (typeof self.performance.getEntriesByType !== 'undefined' && typeof self.performance.getEntriesByType === 'function') {
getEntriesByTypeExists = true;
}
const memory = self.performance.memory ? self.performance.memory : {};
const count = function(ary, classifier) {
return ary.reduce(function(counter, item) {
const p = (classifier || String)(item);
counter[p] = counter.hasOwnProperty(p) ? counter[p] + 1 : 1;
return counter;
}, {});
};
const performanceObj = {
timing: {
raw: self.performance.timing,
calculated: {
latency: self.getLatency(),
transfer: self.getTransfer(),
domProcessingToInteractive: self.getDomProcessingToInteractive(),
domInteractiveToComplete: self.getDomInteractiveToComplete(),
onLoad: self.getOnload(),
total: self.getLatency() + self.getTransfer() + self.getDomProcessingToInteractive() + self.getDomInteractiveToComplete() + self.getOnload()
}
},
memory: {
raw: {
jsHeapSizeLimit: memory ? memory.jsHeapSizeLimit : null,
totalJSHeapSize: memory ? memory.totalJSHeapSize : null,
usedJSHeapSize: memory ? memory.usedJSHeapSize : null
}
},
requests: {
totalEncodedBodySize: performanceEntries.reduce((entry, curr) => entry + (curr.encodedBodySize ? curr.encodedBodySize : 0), 0),
totalDecodedBodySize: performanceEntries.reduce((entry, curr) => entry + (curr.decodedBodySize ? curr.decodedBodySize : 0), 0),
totalDuration: performanceEntries.reduce((entry, curr) => entry + (curr.duration ? curr.duration : 0), 0),
initiatorType: count(performanceEntries, (item) => item.initiatorType),
count: {
frame: getEntriesByTypeExists ? self.performance.getEntriesByType('frame').length : null,
mark: getEntriesByTypeExists ? self.performance.getEntriesByType('mark').length : null,
measure: getEntriesByTypeExists ? self.performance.getEntriesByType('measure').length : null,
navigation: getEntriesByTypeExists ? self.performance.getEntriesByType('navigation').length : null,
resource: getEntriesByTypeExists ? self.performance.getEntriesByType('resource').length : null,
server: getEntriesByTypeExists ? self.performance.getEntriesByType('server').length : null,
total: performanceEntries.length
}
}
};
resolve(performanceObj);
}, 0);
};
});
return promise;
}
};
export default new WebPerfMetrics();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment