From 773af07bf84d813eb05f1f1bf7742cc632eee504 Mon Sep 17 00:00:00 2001 From: Sam Beam Date: Wed, 12 Nov 2014 17:01:16 -0500 Subject: [PATCH] send deltas between sequential navigation.timing events used standard set to avoid browser misimplementations or additions (msFirstPaint). Ignored unloadEvent since that depends on the previous document and is not always in the same sequence. --- bucky.coffee | 21 ++++++++++++++++----- bucky.js | 16 +++++++++++++--- bucky.min.js | 2 +- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/bucky.coffee b/bucky.coffee index b5baa9a..a3ec955 100644 --- a/bucky.coffee +++ b/bucky.coffee @@ -82,9 +82,9 @@ exportDef = -> tagOptions[key] = true else if tagOptions[key]?.toString().toLowerCase is 'false' tagOptions[key] = null - + options = extend {}, defaults, tagOptions - + TYPE_MAP = 'timer': 'ms' 'gauge': 'g' @@ -96,6 +96,11 @@ exportDef = -> HISTORY = [] + EVENTS = ['navigationStart', 'redirectStart', 'redirectEnd', 'fetchStart', 'domainLookupStart', 'domainLookupEnd', \ + 'connectStart', 'connectEnd', 'secureConnectionStart', 'requestStart', 'responseStart', 'responseEnd', \ + 'domLoading', 'domInteractive', 'domContentLoadedEventStart', 'domContentLoadedEventEnd', \ + 'domComplete', 'loadEventStart', 'loadEventEnd'] + setOptions = (opts) -> extend options, opts @@ -171,11 +176,11 @@ exportDef = -> sameOrigin = false else # Relative URL - + sameOrigin = true sendStart = now() - + body = '' for name, val of data body += "#{ name }:#{ val }\n" @@ -384,9 +389,15 @@ exportDef = -> sentPerformanceData = true start = window.performance.timing.navigationStart - for key, time of window.performance.timing when typeof time is 'number' + for key, time of window.performance.timing when typeof time is 'number' and key != 'navigationStart' timer.send "#{ path }.#{ key }", (time - start) + for event in EVENTS + if typeof window.performance.timing[event] is 'number' and window.performance.timing[event] > 0 + if typeof lastEvent != 'undefined' + timer.send "#{ path }.#{ event }.delta", (window.performance.timing[event] - window.performance.timing[lastEvent]) + lastEvent = event + return true requests = { diff --git a/bucky.js b/bucky.js index 360710a..47f52d6 100644 --- a/bucky.js +++ b/bucky.js @@ -50,7 +50,7 @@ }; exportDef = function() { - var $tag, ACTIVE, HISTORY, TYPE_MAP, client, considerSending, defaults, enqueue, flush, key, latencySent, makeClient, makeRequest, maxTimeout, options, queue, round, sendQueue, sendTimeout, setOptions, tagOptions, updateActive, updateLatency, _i, _len, _ref, _ref1, _ref2; + var $tag, ACTIVE, EVENTS, HISTORY, TYPE_MAP, client, considerSending, defaults, enqueue, flush, key, latencySent, makeClient, makeRequest, maxTimeout, options, queue, round, sendQueue, sendTimeout, setOptions, tagOptions, updateActive, updateLatency, _i, _len, _ref, _ref1, _ref2; defaults = { host: '/bucky', maxInterval: 30000, @@ -91,6 +91,7 @@ return ACTIVE = options.active && Math.random() < options.sample; })(); HISTORY = []; + EVENTS = ['navigationStart', 'redirectStart', 'redirectEnd', 'fetchStart', 'domainLookupStart', 'domainLookupEnd', 'connectStart', 'connectEnd', 'secureConnectionStart', 'requestStart', 'responseStart', 'responseEnd', 'domLoading', 'domInteractive', 'domContentLoadedEventStart', 'domContentLoadedEventEnd', 'domComplete', 'loadEventStart', 'loadEventEnd']; setOptions = function(opts) { extend(options, opts); if ('sample' in opts || 'active' in opts) { @@ -365,7 +366,7 @@ }; sentPerformanceData = false; sendPagePerformance = function(path) { - var start, time, _ref3, _ref4, _ref5, + var event, lastEvent, start, time, _j, _len1, _ref3, _ref4, _ref5, _this = this; if ((typeof window !== "undefined" && window !== null ? (_ref3 = window.performance) != null ? _ref3.timing : void 0 : void 0) == null) { return false; @@ -391,10 +392,19 @@ _ref5 = window.performance.timing; for (key in _ref5) { time = _ref5[key]; - if (typeof time === 'number') { + if (typeof time === 'number' && key !== 'navigationStart') { timer.send("" + path + "." + key, time - start); } } + for (_j = 0, _len1 = EVENTS.length; _j < _len1; _j++) { + event = EVENTS[_j]; + if (typeof window.performance.timing[event] === 'number' && window.performance.timing[event] > 0) { + if (typeof lastEvent !== 'undefined') { + timer.send("" + path + "." + event + ".delta", window.performance.timing[event] - window.performance.timing[lastEvent]); + } + lastEvent = event; + } + } return true; }; requests = { diff --git a/bucky.min.js b/bucky.min.js index efd40ce..7d645d2 100644 --- a/bucky.min.js +++ b/bucky.min.js @@ -1,2 +1,2 @@ /*! bucky 0.2.8 */ -(function(){var a,b,c,d,e,f,g,h=[].slice;e="undefined"!=typeof module&&null!==module&&!("undefined"!=typeof window&&null!==window?window.module:void 0),e?(a=require("xmlhttprequest").XMLHttpRequest,g=function(){var a;return a=process.hrtime(),1e3*(a[0]+a[1]/1e9)}):g=function(){var a,b;return null!=(a=null!=(b=window.performance)&&"function"==typeof b.now?b.now():void 0)?a:+new Date},d=+new Date,c=function(){var a,b,c,d,e,f,g;for(a=arguments[0],d=2<=arguments.length?h.call(arguments,1):[],f=0,g=d.length;g>f;f++){c=d[f];for(b in c)e=c[b],a[b]=e}return a},f=function(){var a,b;return a=1<=arguments.length?h.call(arguments,0):[],null!=("undefined"!=typeof console&&null!==console&&null!=(b=console.log)?b.call:void 0)?console.log.apply(console,a):void 0},f.error=function(){var a,b;return a=1<=arguments.length?h.call(arguments,0):[],null!=("undefined"!=typeof console&&null!==console&&null!=(b=console.error)?b.call:void 0)?console.error.apply(console,a):void 0},b=function(){var b,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I;if(n={host:"/bucky",maxInterval:3e4,aggregationInterval:5e3,decimalPrecision:3,sendLatency:!1,sample:1,active:!0},B={},!e&&(b="function"==typeof document.querySelector?document.querySelector("[data-bucky-host],[data-bucky-page],[data-bucky-requests]"):void 0))for(B={host:b.getAttribute("data-bucky-host"),pagePerformanceKey:b.getAttribute("data-bucky-page"),requestsKey:b.getAttribute("data-bucky-requests")},G=["pagePerformanceKey","requestsKey"],E=0,F=G.length;F>E;E++)q=G[E],"true"===(null!=(H=B[q])?H.toString().toLowerCase():void 0)||""===B[q]?B[q]=!0:"false"===(null!=(I=B[q])?I.toString().toLowerCase:void 0)&&(B[q]=null);return v=c({},n,B),k={timer:"ms",gauge:"g",counter:"c"},i=v.active,(C=function(){return i=v.active&&Math.random()k;k++)g=o[k],e=l.transforms.mapping[g],null!=e?"function"!=typeof e?(e instanceof RegExp&&(e=[e,""]),i=i.replace(e[0],e[1])):i=e(i,a,b,c):f.error("Bucky Error: Attempted to enable a mapping which is not defined: "+g);return i=decodeURIComponent(i),i=i.replace(/[^a-zA-Z0-9\-\.\/ ]+/g,"_"),j=d+i.replace(/[\/ ]/g,"."),j=j.replace(/(^\.)|(\.$)/g,""),j=j.replace(/\.com/,""),j=j.replace(/www\./,""),c&&(j=c+"."+j),b&&(j=j+"."+b.toLowerCase()),j=j.replace(/\.\./g,".")},getFullUrl:function(a,b){return null==b&&(b=document.location),/^\//.test(a)?b.hostname+a:/https?:\/\//i.test(a)?a:b.toString()+a},monitor:function(a){var b,d,e;return a&&a!==!0||(a=l.urlToKey(document.location.toString())+".requests"),d=this,b=function(b){var e,f,h,i,j,k,l,n;return l=b.type,n=b.url,f=b.event,i=b.request,h=b.readyStateTimes,j=b.startTime,null!=j?(e=g()-j,n=d.getFullUrl(n),k=d.urlToKey(n,l,a),m(k,e,"timer"),d.sendReadyStateTimes(k,h),null!=(null!=i?i.status:void 0)?(i.status>12e3?c(""+k+".0"):0!==i.status&&c(""+k+"."+i.status.toString().charAt(0)+"xx"),c(""+k+"."+i.status)):void 0):void 0},e=window.XMLHttpRequest,window.XMLHttpRequest=function(){var a,c,d,h,i,j;d=new e;try{h=null,c={},i=d.open,d.open=function(a,e){var j;try{c[0]=g(),d.addEventListener("readystatechange",function(){return c[d.readyState]=g()},!1),d.addEventListener("loadend",function(f){return null==d.bucky||d.bucky.track!==!1?b({type:a,url:e,event:f,startTime:h,readyStateTimes:c,request:d}):void 0},!1)}catch(k){j=k,f.error("Bucky error monitoring XHR open call",j)}return i.apply(d,arguments)},j=d.send,d.send=function(){return h=g(),j.apply(d,arguments)}}catch(k){a=k,f.error("Bucky error monitoring XHR",a)}return d}}},k=function(b){var c;return null==b&&(b=""),c=null!=a?a:"",c&&b&&(c+="."),b&&(c+=b),s(c)},e={send:m,count:c,timer:t,now:g,requests:l,sendPagePerformance:n,flush:p,setOptions:A,options:v,history:j,active:i};for(q in e)u=e[q],k[q]=u;return k},l=s(),v.pagePerformanceKey&&l.sendPagePerformance(v.pagePerformanceKey),v.requestsKey&&l.requests.monitor(v.requestsKey),l},"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():window.Bucky=b()}).call(this); \ No newline at end of file +(function(){var a,b,c,d,e,f,g,h=[].slice;e="undefined"!=typeof module&&null!==module&&!("undefined"!=typeof window&&null!==window?window.module:void 0),e?(a=require("xmlhttprequest").XMLHttpRequest,g=function(){var a;return a=process.hrtime(),1e3*(a[0]+a[1]/1e9)}):g=function(){var a,b;return null!=(a=null!=(b=window.performance)&&"function"==typeof b.now?b.now():void 0)?a:+new Date},d=+new Date,c=function(){var a,b,c,d,e,f,g;for(a=arguments[0],d=2<=arguments.length?h.call(arguments,1):[],f=0,g=d.length;g>f;f++){c=d[f];for(b in c)e=c[b],a[b]=e}return a},f=function(){var a,b;return a=1<=arguments.length?h.call(arguments,0):[],null!=("undefined"!=typeof console&&null!==console&&null!=(b=console.log)?b.call:void 0)?console.log.apply(console,a):void 0},f.error=function(){var a,b;return a=1<=arguments.length?h.call(arguments,0):[],null!=("undefined"!=typeof console&&null!==console&&null!=(b=console.error)?b.call:void 0)?console.error.apply(console,a):void 0},b=function(){var b,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J;if(o={host:"/bucky",maxInterval:3e4,aggregationInterval:5e3,decimalPrecision:3,sendLatency:!1,sample:1,active:!0},C={},!e&&(b="function"==typeof document.querySelector?document.querySelector("[data-bucky-host],[data-bucky-page],[data-bucky-requests]"):void 0))for(C={host:b.getAttribute("data-bucky-host"),pagePerformanceKey:b.getAttribute("data-bucky-page"),requestsKey:b.getAttribute("data-bucky-requests")},H=["pagePerformanceKey","requestsKey"],F=0,G=H.length;G>F;F++)r=H[F],"true"===(null!=(I=C[r])?I.toString().toLowerCase():void 0)||""===C[r]?C[r]=!0:"false"===(null!=(J=C[r])?J.toString().toLowerCase:void 0)&&(C[r]=null);return w=c({},o,C),l={timer:"ms",gauge:"g",counter:"c"},i=w.active,(D=function(){return i=w.active&&Math.random()f;f++)b=j[f],"number"==typeof window.performance.timing[b]&&window.performance.timing[b]>0&&("undefined"!=typeof c&&u.send(""+a+"."+b+".delta",window.performance.timing[b]-window.performance.timing[c]),c=b);return!0},m={transforms:{mapping:{guid:/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,sha1:/\/[0-9a-f]{40}/gi,md5:/\/[0-9a-f]{32}/gi,id:/\/[0-9;_\-]+/g,email:/\/[^/]+@[^/]+/g,domain:[/\/[^/]+\.[a-z]{2,3}\//gi,"/"]},enabled:["guid","sha1","md5","id","email","domain"],enable:function(a,b,c){return null==c&&(c=""),null!=b&&(this.mapping[a]=[b,c]),this.enabled.splice(0,0,a)},disable:function(a){var b,c,d;d=this.enabled;for(b in d)if(c=d[b],c===a)return void this.enabled.splice(b,1)}},sendReadyStateTimes:function(a,b){var c,d,e,f,g,h,i,j;if(null!=b){d={1:"sending",2:"headers",3:"waiting",4:"receiving"},e={},f=null;for(c in b)h=b[c],null!=f&&null!=d[c]&&(e[d[c]]=h-f),f=h;j=[];for(g in e)i=e[g],j.push(u.send(""+a+"."+g,i));return j}},urlToKey:function(a,b,c){var d,e,g,h,i,j,k,l,n,o;for(a=a.replace(/https?:\/\//i,""),h=/([^/:]*)(?::\d+)?(\/[^\?#]*)?.*/i.exec(a),d=h[1],i=null!=(n=h[2])?n:"",o=m.transforms.enabled,k=0,l=o.length;l>k;k++)g=o[k],e=m.transforms.mapping[g],null!=e?"function"!=typeof e?(e instanceof RegExp&&(e=[e,""]),i=i.replace(e[0],e[1])):i=e(i,a,b,c):f.error("Bucky Error: Attempted to enable a mapping which is not defined: "+g);return i=decodeURIComponent(i),i=i.replace(/[^a-zA-Z0-9\-\.\/ ]+/g,"_"),j=d+i.replace(/[\/ ]/g,"."),j=j.replace(/(^\.)|(\.$)/g,""),j=j.replace(/\.com/,""),j=j.replace(/www\./,""),c&&(j=c+"."+j),b&&(j=j+"."+b.toLowerCase()),j=j.replace(/\.\./g,".")},getFullUrl:function(a,b){return null==b&&(b=document.location),/^\//.test(a)?b.hostname+a:/https?:\/\//i.test(a)?a:b.toString()+a},monitor:function(a){var b,d,e;return a&&a!==!0||(a=m.urlToKey(document.location.toString())+".requests"),d=this,b=function(b){var e,f,h,i,j,k,l,m;return l=b.type,m=b.url,f=b.event,i=b.request,h=b.readyStateTimes,j=b.startTime,null!=j?(e=g()-j,m=d.getFullUrl(m),k=d.urlToKey(m,l,a),n(k,e,"timer"),d.sendReadyStateTimes(k,h),null!=(null!=i?i.status:void 0)?(i.status>12e3?c(""+k+".0"):0!==i.status&&c(""+k+"."+i.status.toString().charAt(0)+"xx"),c(""+k+"."+i.status)):void 0):void 0},e=window.XMLHttpRequest,window.XMLHttpRequest=function(){var a,c,d,h,i,j;d=new e;try{h=null,c={},i=d.open,d.open=function(a,e){var j;try{c[0]=g(),d.addEventListener("readystatechange",function(){return c[d.readyState]=g()},!1),d.addEventListener("loadend",function(f){return null==d.bucky||d.bucky.track!==!1?b({type:a,url:e,event:f,startTime:h,readyStateTimes:c,request:d}):void 0},!1)}catch(k){j=k,f.error("Bucky error monitoring XHR open call",j)}return i.apply(d,arguments)},j=d.send,d.send=function(){return h=g(),j.apply(d,arguments)}}catch(k){a=k,f.error("Bucky error monitoring XHR",a)}return d}}},l=function(b){var c;return null==b&&(b=""),c=null!=a?a:"",c&&b&&(c+="."),b&&(c+=b),t(c)},e={send:n,count:c,timer:u,now:g,requests:m,sendPagePerformance:o,flush:q,setOptions:B,options:w,history:k,active:i};for(r in e)v=e[r],l[r]=v;return l},m=t(),w.pagePerformanceKey&&m.sendPagePerformance(w.pagePerformanceKey),w.requestsKey&&m.requests.monitor(w.requestsKey),m},"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():window.Bucky=b()}).call(this); \ No newline at end of file