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