Skip to content

Commit

Permalink
Add a few NavigationTiming2 fields if available
Browse files Browse the repository at this point in the history
  • Loading branch information
nicjansma committed Apr 4, 2018
1 parent 6f1acad commit b18ef55
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 45 deletions.
61 changes: 59 additions & 2 deletions plugins/navtiming.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,29 @@ see: http://www.w3.org/TR/navigation-timing/
return;
}

/**
* Calculates a NavigationTiming timestamp for the beacon, in milliseconds
* since the Unix Epoch.
*
* The offset should be 0 if using a timestamp from performance.timing (which
* are already in milliseconds since Unix Epoch), or the value of navigationStart
* if using getEntriesByType("navigation") (which are DOMHighResTimestamps).
*
* The number is stripped of any decimals.
*
* @param {number} offset navigationStart offset (0 if using NavTiming1)
* @param {number} val DOMHighResTimestamp
*
* @returns {number} Timestamp for beacon
*/
function calcNavTimingTimestamp(offset, val) {
if (typeof val !== "number") {
return undefined;
}

return Math.floor((offset || 0) + val);
}

// A private object to encapsulate all your implementation details
var impl = {
complete: false,
Expand Down Expand Up @@ -118,7 +141,7 @@ see: http://www.w3.org/TR/navigation-timing/
},

done: function() {
var w = BOOMR.window, p, pn, pt, data, cinf;
var w = BOOMR.window, p, pn, chromeTimes, pt, data, cinf, offset = 0;

if (this.complete) {
return this;
Expand Down Expand Up @@ -146,13 +169,47 @@ see: http://www.w3.org/TR/navigation-timing/
}

p = BOOMR.getPerformance();

// This is Chrome only, so will not conflict with nt_first_paint below
if (w.chrome && w.chrome.loadTimes) {
chromeTimes = w.chrome.loadTimes();
if (chromeTimes) {
cinf = chromeTimes.connectionInfo;

data = {
nt_spdy: (chromeTimes.wasFetchedViaSpdy ? 1 : 0),
nt_cinf: cinf
};

// Chrome firstPaintTime is in seconds.microseconds, so
// we need to multiply it by 1000 to be consistent with
// msFirstPaint and other NavigationTiming timestamps that
// are in milliseconds.microseconds.
if (typeof chromeTimes.firstPaintTime === "number" && chromeTimes.firstPaintTime !== 0) {
data.nt_first_paint = Math.round(chromeTimes.firstPaintTime * 1000);
}

BOOMR.addVar(data);

try {
impl.addedVars.push.apply(impl.addedVars, Object.keys(data));
}
catch (ignore) {
// NOP
}
}
}

if (p) {
if (typeof p.getEntriesByType === "function") {
pt = p.getEntriesByType("navigation");
if (pt && pt.length) {
BOOMR.info("This user agent supports NavigationTiming.", "nt");
BOOMR.info("This user agent supports NavigationTiming2", "nt");

pt = pt[0];

// ensure DOMHighResTimestamps are added to navigationStart
offset = p.timing ? p.timing.navigationStart : 0;
}
else {
pt = undefined;
Expand Down
120 changes: 77 additions & 43 deletions tests/page-templates/19-navtiming/00-onload.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,30 @@

describe("e2e/19-navtiming/00-onload", function() {
var tf = BOOMR.plugins.TestFramework;
var t = BOOMR_test;

var NT_PROPERTIES = [
"nt_nav_st",
"nt_red_st",
"nt_red_end",
"nt_fet_st",
"nt_dns_st",
"nt_dns_end",
"nt_con_st",
"nt_con_end",
"nt_req_st",
"nt_res_st",
"nt_res_end",
"nt_domloading",
"nt_domint",
"nt_domcontloaded_st",
"nt_domcontloaded_end",
"nt_domcomp",
"nt_load_st",
"nt_load_end",
"nt_unload_st",
"nt_unload_end"
];

it("Should have sent a beacon", function() {
// ensure we fired a beacon ('onbeacon')
Expand All @@ -18,74 +42,87 @@ describe("e2e/19-navtiming/00-onload", function() {
assert.isString(tf.lastBeacon().v);
});

it("Should have set nt_* properties", function() {
var p = BOOMR.getPerformance();
if (!p || !p.timing) {
// NT not supported
return;
}

assert.isNumber(tf.lastBeacon().nt_nav_st, "nt_nav_st");
assert.isNumber(tf.lastBeacon().nt_red_st, "nt_red_st");
assert.isNumber(tf.lastBeacon().nt_red_end, "nt_red_end");
assert.isNumber(tf.lastBeacon().nt_fet_st, "nt_fet_st");
assert.isNumber(tf.lastBeacon().nt_dns_st, "nt_dns_st");
assert.isNumber(tf.lastBeacon().nt_dns_end, "nt_dns_end");
assert.isNumber(tf.lastBeacon().nt_con_st, "nt_con_st");
assert.isNumber(tf.lastBeacon().nt_con_end, "nt_con_end");
assert.isNumber(tf.lastBeacon().nt_req_st, "nt_req_st");
assert.isNumber(tf.lastBeacon().nt_res_st, "nt_res_st");
assert.isNumber(tf.lastBeacon().nt_res_end, "nt_res_end");
assert.isNumber(tf.lastBeacon().nt_domloading, "nt_domloading");
assert.isNumber(tf.lastBeacon().nt_domint, "nt_domint");
assert.isNumber(tf.lastBeacon().nt_domcontloaded_st, "nt_domcontloaded_st");
assert.isNumber(tf.lastBeacon().nt_domcontloaded_end, "nt_domcontloaded_end");
assert.isNumber(tf.lastBeacon().nt_domcomp, "nt_domcomp");
assert.isNumber(tf.lastBeacon().nt_load_st, "nt_load_st");
assert.isNumber(tf.lastBeacon().nt_load_end, "nt_load_end");
assert.isNumber(tf.lastBeacon().nt_unload_st, "nt_unload_st");
assert.isNumber(tf.lastBeacon().nt_unload_end, "nt_unload_end");
it("Should have set nt_* properties (if NavigationTiming is supported)", function() {
if (!t.isNavigationTimingSupported()) {
return this.skip();
}

for (var i = 0; i < NT_PROPERTIES.length; i++) {
assert.isNumber(tf.lastBeacon()[NT_PROPERTIES[i]], NT_PROPERTIES[i]);
}

if (location.protocol === "https:") {
assert.isNumber(tf.lastBeacon().nt_ssl_st, "nt_ssl_st");
}
});

it("Should have set Chrome nt_* properties", function() {
it("Should have set set nt_* properties as Unix-epoch timestamps, not DOMHighResTimestamps (if NavigationTiming is supported)", function() {
if (!t.isNavigationTimingSupported()) {
return this.skip();
}

for (var i = 0; i < NT_PROPERTIES.length; i++) {
// Jan 1 2000
assert.operator(parseInt(tf.lastBeacon()[NT_PROPERTIES[i]], 10), ">=", 946684800, NT_PROPERTIES[i]);

// Jan 1 2050
assert.operator(parseInt(tf.lastBeacon()[NT_PROPERTIES[i]], 10), "<=", 2524658358000, NT_PROPERTIES[i]);

// make sure it's not decimal
assert.notInclude(tf.lastBeacon()[NT_PROPERTIES[i]], ".");
}
});

it("Should have set set nt_* properties as full numbers, not decimals (if NavigationTiming is supported)", function() {
if (!t.isNavigationTimingSupported()) {
return this.skip();
}

for (var i = 0; i < NT_PROPERTIES.length; i++) {
assert.notInclude(tf.lastBeacon()[NT_PROPERTIES[i]], ".", NT_PROPERTIES[i]);
}
});

it("Should have set Chrome nt_* properties (if Chrome)", function() {
var pt;
if (window.chrome && window.chrome.loadTimes) {
pt = window.chrome.loadTimes();
}
if (!pt) {
// Not supported
return;
return this.skip();
}

assert.isNumber(tf.lastBeacon().nt_spdy, "nt_spdy");
assert.isNotEmpty(tf.lastBeacon().nt_cinf, "nt_cinf");
assert.isDefined(tf.lastBeacon().nt_cinf, "nt_cinf");

// validation of firstPaint
assert.isNumber(tf.lastBeacon().nt_first_paint, "nt_first_paint");
assert.operator(parseInt(tf.lastBeacon().nt_first_paint, 10), ">=", parseInt(tf.lastBeacon().nt_nav_st, 10));
});

it("Should have set IE's nt_first_paint property", function() {
it("Should have set IE's nt_first_paint property (if IE)", function() {
var p = BOOMR.getPerformance();
if (!p || !p.timing || !p.timing.msFirstPaint) {
// NT first paint supported
return;
// NT first paint not supported
return this.skip();
}

assert.isNumber(tf.lastBeacon().nt_first_paint, "nt_first_paint");
assert.operator(parseInt(tf.lastBeacon().nt_first_paint, 10), ">=", parseInt(tf.lastBeacon().nt_nav_st, 10));
});

it("Should have set NT2 properties", function() {
it("Should have set NT2 properties (if NavigationTiming2 is supported)", function() {
var pt, p = BOOMR.getPerformance();
if (!p || typeof p.getEntriesByType !== "function") {
// NT2 not supported
return;
return this.skip();
}

pt = p.getEntriesByType("navigation");
if (!pt || !pt.length) {
// NT2 not supported
return;
return this.skip();
}
pt = pt[0];

Expand All @@ -100,20 +137,17 @@ describe("e2e/19-navtiming/00-onload", function() {
}

if (pt.nextHopProtocol) {
assert.isNotEmpty(tf.lastBeacon().nt_cinf, "nt_cinf");
assert.isDefined(tf.lastBeacon().nt_cinf, "nt_cinf");
assert.equal(tf.lastBeacon().nt_cinf, pt.nextHopProtocol, "nt_cinf");
}
});

it("Should have set nt_* navigation properties", function() {
var p = BOOMR.getPerformance();
if (!p || !p.navigation) {
// NT not supported
return;
it("Should have set nt_* navigation properties (if NavigationTiming is supported)", function() {
if (!t.isNavigationTimingSupported()) {
return this.skip();
}

assert.isNumber(tf.lastBeacon().nt_red_cnt, "nt_red_cnt");
assert.isNumber(tf.lastBeacon().nt_nav_type, "nt_nav_type");
});

});

0 comments on commit b18ef55

Please sign in to comment.