boomerangjs
Version:
boomerang always comes back, except when it hits something
168 lines (141 loc) • 4.76 kB
JavaScript
/**
* Plugin to measure DNS latency.
*
* This code is based on Carlos Bueno's guide to DNS on the
* [Facebook Note](https://www.facebook.com/note.php?note_id=10150212498738920)
*
* For information on how to include this plugin, see the {@tutorial building} tutorial.
*
* ## Setup
*
* Measuring DNS requires some server-side set up, as
* [documented in detail](https://www.facebook.com/note.php?note_id=10150212498738920) by
* Facebook engineer Carlos Bueno, so go read his post for everything you'll need to set this up.
*
* In brief, the points he covers are:
*
* 1. Set up a wildcard hostname, perferably one that does not share cookies with
* your main site. Give it a low TTL, say, 60 seconds, so you don't pollute downstream caches.
* 2. Set up a webserver for the wildcard hostname that serves the images named `A.gif`
* and `B.gif` (from the `images/` subdirectory) as fast as possible. Make sure
* that KeepAlive, Nagle, and any caching headers are turned off.
* 3. Include the DNS plugin (see {@tutorial building})
* 4. Tell the DNS plugin where to get its images from
* via {@link BOOMR.plugins.DNS.init DNS.base_url}
*
* Steps 1 and 2 are complicated, and if you don't have full control over your
* DNS server, then it may be impossible for you to use this plugin.
*
* ## Beacon Parameters
*
* This plugin adds the following parameters to the beacon:
*
* * `dns.t`: The worst-case DNS latency from the user's browser to your DNS server.
*
* @class BOOMR.plugins.DNS
*/
(function() {
BOOMR = window.BOOMR || {};
BOOMR.plugins = BOOMR.plugins || {};
if (BOOMR.plugins.DNS) {
return;
}
var impl = {
complete: false,
base_url: "",
t_start: null,
t_dns: null,
t_http: null,
img: null,
gen_url: "",
start: function() {
if (impl.gen_url) {
// already running
return;
}
var random = BOOMR.utils.generateId(10);
impl.gen_url = impl.base_url.replace(/\*/, random);
impl.img = new Image();
impl.img.onload = impl.A_loaded;
impl.t_start = new Date().getTime();
impl.img.src = impl.gen_url + "image-l.gif?t=" + random;
},
A_loaded: function() {
var random = BOOMR.utils.generateId(10);
impl.t_dns = new Date().getTime() - impl.t_start;
impl.img = new Image();
impl.img.onload = impl.B_loaded;
impl.t_start = new Date().getTime();
impl.img.src = impl.gen_url + "image-l.gif?t=" + random;
},
B_loaded: function() {
impl.t_http = new Date().getTime() - impl.t_start;
impl.img = null;
impl.done();
},
done: function() {
// DNS time is the time to load the image with uncached DNS
// minus the time to load the image with cached DNS
var dns = impl.t_dns - impl.t_http;
BOOMR.addVar("dns.t", dns);
impl.complete = true;
impl.gen_url = "";
BOOMR.sendBeacon();
}
};
BOOMR.plugins.DNS = {
/**
* Initializes the plugin.
*
* @param {object} config Configuration
* @param {string} config.DNS.base_url The `base_url` parameter tells the DNS
* plugin where it can find its DNS testing images. This URL must contain
* a wildcard character (`*`) which will be replaced with a random string.
*
* The images will be appended to this string without any other modification.
*
* If you have any pages served over HTTPS, then this URL should be configured
* to work over HTTPS as well as HTTP.
*
* The protocol part of the URL will be automatically changed to fit the
* current document.
*
* @returns {@link BOOMR.plugins.DNS} The DNS plugin for chaining
* @example
* BOOMR.init({
* DNS: {
* base_url: "http://*.yoursite.com/images/"
* }
* });
* @memberof BOOMR.plugins.DNS
*/
init: function(config) {
BOOMR.utils.pluginConfig(impl, config, "DNS", ["base_url"]);
if (config && config.wait) {
return this;
}
if (!impl.base_url) {
BOOMR.warn("DNS.base_url is not set. Cannot run DNS test.", "dns");
// set to true so that is_complete doesn't block other plugins
impl.complete = true;
return this;
}
// do not run test over https
if (BOOMR.window.location.protocol === "https:") {
impl.complete = true;
return this;
}
BOOMR.subscribe("page_ready", impl.start, null, impl);
return this;
},
/**
* Whether or not this plugin is complete
*
* @returns {boolean} `true` if the plugin is complete
* @memberof BOOMR.plugins.DNS
*/
is_complete: function() {
return impl.complete;
}
};
}());