1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/bc34e6a879f7/ Changeset: bc34e6a879f7 User: carlfeberhard Date: 2014-04-18 18:58:20 Summary: QA: more testing of metrics logger Affected #: 4 files diff -r 47285f0d20f4cbcb150a894f343fd8cbf1bed4a7 -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 static/scripts/packed/galaxy-app-base.js --- a/static/scripts/packed/galaxy-app-base.js +++ b/static/scripts/packed/galaxy-app-base.js @@ -1,1 +1,1 @@ -define(["mvc/user/user-model","utils/metrics-logger","utils/add-logging","utils/localization","bootstrapped-data"],function(b,d,g,e,a){function h(n){var m=this;return m._init(n||{})}g(h,"GalaxyApp");h.prototype.defaultOptions={patchExisting:true,root:"/"};h.prototype._init=function k(n){var m=this;_.extend(m,Backbone.Events);m._processOptions(n);m.debug("GalaxyApp.options: ",m.options);m._patchGalaxy(window.Galaxy);m.debug("GalaxyApp.options: ",m.options);m._initLogger(n.loggerOptions||{});m.debug("GalaxyApp.logger: ",m.logger);m._initLocale();m.debug("GalaxyApp.localize: ",m.localize);m.config=n.config||a.config||{};m.debug("GalaxyApp.config: ",m.config);m._initUser(n.user||a.user||{});m.debug("GalaxyApp.user: ",m.user);m.trigger("ready",m);return m};h.prototype._processOptions=function f(o){var n=this,p=n.defaultOptions;n.debug("_processOptions: ",o);n.options={};for(var m in p){if(p.hasOwnProperty(m)){n.options[m]=(o.hasOwnProperty(m))?(o[m]):(p[m])}}return n};h.prototype._patchGalaxy=function f(m){var o=this;if(o.options.patchExisting&&m){o.debug("found existing Galaxy object:",m);for(var n in m){if(m.hasOwnProperty(n)){o.debug("\t patching in "+n+" to Galaxy");o[n]=m[n]}}}};h.prototype._initLogger=function l(n){var m=this;m.debug("_initLogger:",n);m.logger=new d.MetricsLogger(n);return m};h.prototype._initLocale=function j(n){var m=this;m.debug("_initLocale:",n);m.localize=e;window._l=m.localize;return m};h.prototype._initUser=function i(n){var m=this;m.debug("_initUser:",n);m.user=new b.User(n);m.currUser=m.user;return m};h.prototype.toString=function c(){var m=this.user.get("email")||"(anonymous)";return"GalaxyApp("+m+")"};return{GalaxyApp:h}}); \ No newline at end of file +define(["mvc/user/user-model","utils/metrics-logger","utils/add-logging","utils/localization","bootstrapped-data"],function(b,d,g,e,a){function h(n){var m=this;return m._init(n||{})}g(h,"GalaxyApp");h.prototype.defaultOptions={patchExisting:true,root:"/"};h.prototype._init=function k(n){var m=this;_.extend(m,Backbone.Events);m._processOptions(n);m.debug("GalaxyApp.options: ",m.options);m._patchGalaxy(window.Galaxy);m._initLogger(n.loggerOptions||{});m.debug("GalaxyApp.logger: ",m.logger);m._initLocale();m.debug("GalaxyApp.localize: ",m.localize);m.config=n.config||a.config||{};m.debug("GalaxyApp.config: ",m.config);m._initUser(n.user||a.user||{});m.debug("GalaxyApp.user: ",m.user);m.trigger("ready",m);return m};h.prototype._processOptions=function f(o){var n=this,p=n.defaultOptions;n.debug("_processOptions: ",o);n.options={};for(var m in p){if(p.hasOwnProperty(m)){n.options[m]=(o.hasOwnProperty(m))?(o[m]):(p[m])}}return n};h.prototype._patchGalaxy=function f(m){var o=this;if(o.options.patchExisting&&m){o.debug("found existing Galaxy object:",m);for(var n in m){if(m.hasOwnProperty(n)){o.debug("\t patching in "+n+" to Galaxy");o[n]=m[n]}}}};h.prototype._initLogger=function l(n){var m=this;m.debug("_initLogger:",n);m.logger=new d.MetricsLogger(n);return m};h.prototype._initLocale=function j(n){var m=this;m.debug("_initLocale:",n);m.localize=e;window._l=m.localize;return m};h.prototype._initUser=function i(n){var m=this;m.debug("_initUser:",n);m.user=new b.User(n);m.currUser=m.user;return m};h.prototype.toString=function c(){var m=this.user.get("email")||"(anonymous)";return"GalaxyApp("+m+")"};return{GalaxyApp:h}}); \ No newline at end of file diff -r 47285f0d20f4cbcb150a894f343fd8cbf1bed4a7 -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 static/scripts/packed/utils/metrics-logger.js --- a/static/scripts/packed/utils/metrics-logger.js +++ b/static/scripts/packed/utils/metrics-logger.js @@ -1,1 +1,1 @@ -define([],function(){function h(z){z=z||{};var y=this;y.consoleLogger=z.consoleLogger||null;y._init(z);return y}h.ALL=0;h.DEBUG=10;h.INFO=20;h.WARN=30;h.ERROR=40;h.METRIC=50;h.NONE=100;h.defaultOptions={logLevel:h.NONE,consoleLevel:h.NONE,defaultNamespace:"Galaxy",clientPrefix:"client.",maxCacheSize:3000,postSize:1000,addTime:true,postUrl:"/api/metrics",getPingData:undefined,onServerResponse:undefined};h.prototype._init=function i(A){var z=this;z.options={};for(var y in h.defaultOptions){if(h.defaultOptions.hasOwnProperty(y)){z.options[y]=(A.hasOwnProperty(y))?(A[y]):(h.defaultOptions[y])}}z.options.logLevel=z._parseLevel(z.options.logLevel);z.options.consoleLevel=z._parseLevel(z.options.consoleLevel);z._sending=false;z._postSize=z.options.postSize;z._initCache();return z};h.prototype._initCache=function a(){this.cache=new w({maxSize:this.options.maxCacheSize})};h.prototype._parseLevel=function j(A){var z=typeof A;if(z==="number"){return A}if(z==="string"){var y=A.toUpperCase();if(h.hasOwnProperty(y)){return h[y]}}throw new Error("Unknown log level: "+A)};h.prototype.emit=function m(B,A,z){var y=this;A=A||y.options.defaultNamespace;if(!B||!z){return y}B=y._parseLevel(B);if(B>=y.options.logLevel){y._addToCache(B,A,z)}if(y.consoleLogger&&B>=y.options.consoleLevel){y._emitToConsole(B,A,z)}return y};h.prototype._addToCache=function b(D,A,z){this._emitToConsole("debug","MetricsLogger",["_addToCache:",arguments,this.options.addTime,this.cache.length()]);var y=this;try{var C=y.cache.add(y._buildEntry(D,A,z));if(C>=y._postSize){y._postCache()}}catch(B){if(y.options.consoleLevel<=h.WARN){console.warn("Metrics logger could not stringify logArguments:",A,z);console.error(B)}}return y};h.prototype._buildEntry=function r(B,z,y){this._emitToConsole("debug","MetricsLogger",["_buildEntry:",arguments]);var A={level:B,namespace:this.options.clientPrefix+z,args:y};if(this.options.addTime){A.time=new Date().toISOString()}return A};h.prototype._postCache=function s(B){B=B||{};this._emitToConsole("info","MetricsLogger",["_postCache",B,this._postSize]);if(!this.options.postUrl||this._sending){return jQuery.when({})}var A=this,D=B.count||A._postSize,y=A.cache.get(D),C=y.length,z=(typeof A.options.getPingData==="function")?(A.options.getPingData()):({});z.metrics=A._preprocessCache(y);A._sending=true;return jQuery.post(A.options.postUrl,z).always(function(){A._sending=false}).fail(function(){A._postSize=A.options.maxCacheSize}).done(function(E){if(typeof A.options.onServerResponse==="function"){A.options.onServerResponse(E)}A.cache.remove(C);console.debug("removed entries:",C,"size now:",A.cache.length());A._postSize=A.options.postSize})};h.prototype._preprocessCache=function f(y){return["[",(y.join(",\n")),"]"].join("\n")};h.prototype._emitToConsole=function c(C,B,A){var y=this;if(!y.consoleLogger){return y}var z=Array.prototype.slice.call(A,0);z.unshift(B);if(C>=h.METRIC&&typeof(y.consoleLogger.info)==="function"){return y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.ERROR&&typeof(y.consoleLogger.error)==="function"){return y.consoleLogger.error.apply(y.consoleLogger,z)}else{if(C>=h.WARN&&typeof(y.consoleLogger.warn)==="function"){y.consoleLogger.warn.apply(y.consoleLogger,z)}else{if(C>=h.INFO&&typeof(y.consoleLogger.info)==="function"){y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.DEBUG&&typeof(y.consoleLogger.debug)==="function"){y.consoleLogger.debug.apply(y.consoleLogger,z)}else{if(typeof(y.consoleLogger.log)==="function"){y.consoleLogger.log.apply(y.consoleLogger,z)}}}}}}return y};h.prototype.debug=function l(){this.emit(h.DEBUG,this.options.defaultNamespace,arguments)};h.prototype.log=function g(){this.emit(1,this.options.defaultNamespace,arguments)};h.prototype.info=function u(){this.emit(h.INFO,this.options.defaultNamespace,arguments)};h.prototype.warn=function t(){this.emit(h.WARN,this.options.defaultNamespace,arguments)};h.prototype.error=function p(){this.emit(h.ERROR,this.options.defaultNamespace,arguments)};h.prototype.metric=function n(){this.emit(h.METRIC,this.options.defaultNamespace,arguments)};function w(z){var y=this;y._cache=[];return y._init(z||{})}w.defaultOptions={maxSize:5000};w.prototype._init=function i(y){this.maxSize=y.maxSize||w.defaultOptions.maxSize;return this};w.prototype.add=function k(A){var z=this,y=(z.length()+1)-z.maxSize;if(y>0){z.remove(y)}z._cache.push(z._preprocessEntry(A));return z.length()};w.prototype._preprocessEntry=function q(y){return JSON.stringify(y)};w.prototype.length=function e(){return this._cache.length};w.prototype.get=function v(y){return this._cache.slice(0,y)};w.prototype.remove=function x(y){return this._cache.splice(0,y)};w.prototype.stringify=function o(y){return["[",(this.get(y).join(",\n")),"]"].join("\n")};w.prototype.print=function d(){this._cache.forEach(function(y){console.log(y)})};return{MetricsLogger:h,LoggingCache:w}}); \ No newline at end of file +define([],function(){function h(z){z=z||{};var y=this;y.consoleLogger=z.consoleLogger||null;y._init(z);return y}h.ALL=0;h.DEBUG=10;h.INFO=20;h.WARN=30;h.ERROR=40;h.METRIC=50;h.NONE=100;h.defaultOptions={logLevel:h.NONE,consoleLevel:h.NONE,defaultNamespace:"Galaxy",clientPrefix:"client.",maxCacheSize:3000,postSize:1000,addTime:true,postUrl:"/api/metrics",getPingData:undefined,onServerResponse:undefined};h.prototype._init=function i(A){var z=this;z.options={};for(var y in h.defaultOptions){if(h.defaultOptions.hasOwnProperty(y)){z.options[y]=(A.hasOwnProperty(y))?(A[y]):(h.defaultOptions[y])}}z.options.logLevel=z._parseLevel(z.options.logLevel);z.options.consoleLevel=z._parseLevel(z.options.consoleLevel);z._sending=false;z._postSize=z.options.postSize;z._initCache();return z};h.prototype._initCache=function a(){this.cache=new w({maxSize:this.options.maxCacheSize})};h.prototype._parseLevel=function j(A){var z=typeof A;if(z==="number"){return A}if(z==="string"){var y=A.toUpperCase();if(h.hasOwnProperty(y)){return h[y]}}throw new Error("Unknown log level: "+A)};h.prototype.emit=function m(B,A,z){var y=this;A=A||y.options.defaultNamespace;if(!B||!z){return y}B=y._parseLevel(B);if(B>=y.options.logLevel){y._addToCache(B,A,z)}if(y.consoleLogger&&B>=y.options.consoleLevel){y._emitToConsole(B,A,z)}return y};h.prototype._addToCache=function b(D,A,z){this._emitToConsole("debug","MetricsLogger",["_addToCache:",arguments,this.options.addTime,this.cache.length()]);var y=this;try{var C=y.cache.add(y._buildEntry(D,A,z));if(C>=y._postSize){y._postCache()}}catch(B){if(y.options.consoleLevel<=h.WARN){console.warn("Metrics logger could not stringify logArguments:",A,z);console.error(B)}}return y};h.prototype._buildEntry=function r(B,z,y){this._emitToConsole("debug","MetricsLogger",["_buildEntry:",arguments]);var A={level:B,namespace:this.options.clientPrefix+z,args:y};if(this.options.addTime){A.time=new Date().toISOString()}return A};h.prototype._postCache=function s(B){B=B||{};this._emitToConsole("info","MetricsLogger",["_postCache",B,this._postSize]);if(!this.options.postUrl||this._sending){return jQuery.when({})}var A=this,D=B.count||A._postSize,y=A.cache.get(D),C=y.length,z=(typeof A.options.getPingData==="function")?(A.options.getPingData()):({});z.metrics=A._preprocessCache(y);A._sending=true;return jQuery.post(A.options.postUrl,z).always(function(){A._sending=false}).fail(function(){A._postSize=A.options.maxCacheSize}).done(function(E){if(typeof A.options.onServerResponse==="function"){A.options.onServerResponse(E)}A.cache.remove(C);A._postSize=A.options.postSize})};h.prototype._preprocessCache=function f(y){return["[",(y.join(",\n")),"]"].join("\n")};h.prototype._emitToConsole=function c(C,B,A){var y=this;if(!y.consoleLogger){return y}var z=Array.prototype.slice.call(A,0);z.unshift(B);if(C>=h.METRIC&&typeof(y.consoleLogger.info)==="function"){return y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.ERROR&&typeof(y.consoleLogger.error)==="function"){return y.consoleLogger.error.apply(y.consoleLogger,z)}else{if(C>=h.WARN&&typeof(y.consoleLogger.warn)==="function"){y.consoleLogger.warn.apply(y.consoleLogger,z)}else{if(C>=h.INFO&&typeof(y.consoleLogger.info)==="function"){y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.DEBUG&&typeof(y.consoleLogger.debug)==="function"){y.consoleLogger.debug.apply(y.consoleLogger,z)}else{if(typeof(y.consoleLogger.log)==="function"){y.consoleLogger.log.apply(y.consoleLogger,z)}}}}}}return y};h.prototype.debug=function l(){this.emit(h.DEBUG,this.options.defaultNamespace,arguments)};h.prototype.log=function g(){this.emit(1,this.options.defaultNamespace,arguments)};h.prototype.info=function u(){this.emit(h.INFO,this.options.defaultNamespace,arguments)};h.prototype.warn=function t(){this.emit(h.WARN,this.options.defaultNamespace,arguments)};h.prototype.error=function p(){this.emit(h.ERROR,this.options.defaultNamespace,arguments)};h.prototype.metric=function n(){this.emit(h.METRIC,this.options.defaultNamespace,arguments)};function w(z){var y=this;y._cache=[];return y._init(z||{})}w.defaultOptions={maxSize:5000};w.prototype._init=function i(y){this.maxSize=y.maxSize||w.defaultOptions.maxSize;return this};w.prototype.add=function k(A){var z=this,y=(z.length()+1)-z.maxSize;if(y>0){z.remove(y)}z._cache.push(z._preprocessEntry(A));return z.length()};w.prototype._preprocessEntry=function q(y){return JSON.stringify(y)};w.prototype.length=function e(){return this._cache.length};w.prototype.get=function v(y){return this._cache.slice(0,y)};w.prototype.remove=function x(y){return this._cache.splice(0,y)};w.prototype.stringify=function o(y){return["[",(this.get(y).join(",\n")),"]"].join("\n")};w.prototype.print=function d(){this._cache.forEach(function(y){console.log(y)})};return{MetricsLogger:h,LoggingCache:w}}); \ No newline at end of file diff -r 47285f0d20f4cbcb150a894f343fd8cbf1bed4a7 -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 static/scripts/utils/metrics-logger.js --- a/static/scripts/utils/metrics-logger.js +++ b/static/scripts/utils/metrics-logger.js @@ -224,7 +224,7 @@ } // only remove if post successful self.cache.remove( entriesLength ); - console.debug( 'removed entries:', entriesLength, 'size now:', self.cache.length() ); + //console.debug( 'removed entries:', entriesLength, 'size now:', self.cache.length() ); // if we succeeded, reset the post target to the normal num of entries self._postSize = self.options.postSize; }); diff -r 47285f0d20f4cbcb150a894f343fd8cbf1bed4a7 -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 test/qunit/tests/metrics-logger.js --- a/test/qunit/tests/metrics-logger.js +++ b/test/qunit/tests/metrics-logger.js @@ -9,11 +9,22 @@ $, sinon ){ - /*globals equal test module expect deepEqual strictEqual throws */ + /*globals equal test module expect deepEqual strictEqual throws ok */ "use strict"; + var MockConsole = function(){ + var self = this; + self.lastMessage = null; + [ 'log', 'debug', 'info', 'warn', 'error' ].forEach( function( fnName ){ + self[ fnName ] = function(){ + self.lastMessage = { level: fnName, args: Array.prototype.slice.call( arguments, 0 ) }; + }; + }); + }; + module( "Metrics logger tests" ); + // ======================================================================== MetricsLogger test( "logger construction/initializiation defaults", function() { var logger = new metrics.MetricsLogger({}); equal( logger.consoleLogger, null ); @@ -24,6 +35,9 @@ equal( logger.options.postSize, 1000 ); equal( logger.options.maxCacheSize, 3000 ); equal( logger.options.addTime, true ); + equal( logger.options.postUrl, '/api/metrics' ); + equal( logger.options.getPingData, undefined ); + equal( logger.options.onServerResponse, undefined ); equal( logger._postSize, 1000 ); equal( logger.cache.constructor, metrics.LoggingCache ); @@ -47,10 +61,105 @@ logger._parseLevel( 'nope' ); }, /Unknown log level/, 'Unknown log level throws error' ); }); + + // ------------------------------------------------------------------------ Emit to cache + test( "emit to cache at level", function() { + var logger = new metrics.MetricsLogger({ + logLevel : 'metric' + }); + equal( logger.options.logLevel, metrics.MetricsLogger.METRIC ); + logger.emit( 'metric', 'test', [ 1, 2, { three: 3 }] ); + equal( logger.cache.length(), 1 ); + + var cached = JSON.parse( logger.cache.get( 1 ) ); + equal( cached.level, metrics.MetricsLogger.METRIC ); + equal( cached.namespace, 'client.test' ); + equal( cached.args.length, 3 ); + equal( cached.args[2].three, 3 ); + ok( typeof cached.time === 'string' ); + ok( cached.time === new Date( cached.time ).toISOString() ); + }); + + test( "emit to cache below does not cache", function() { + var logger = new metrics.MetricsLogger({ + logLevel : 'metric' + }); + logger.emit( 'error', 'test', [ 1, 2, { three: 3 }] ); + equal( logger.cache.length(), 0 ); + }); + + test( "emit to cache (silently) drops non-parsable", function() { + var logger = new metrics.MetricsLogger({ + logLevel : 'metric' + }); + logger.emit( 'metric', 'test', [{ window: window }] ); + equal( logger.cache.length(), 0 ); + }); + // ======================================================================== LoggingCache test( "cache construction/initializiation defaults", function() { var cache = new metrics.LoggingCache(); equal( cache.maxSize, 5000 ); equal( $.type( cache._cache ), 'array' ); }); + + test( "cache construction/initializiation setting max cache size", function() { + var cache = new metrics.LoggingCache({ + maxSize : 5 + }); + equal( cache.maxSize, 5 ); + }); + + test( "cache plays well with no data", function() { + var cache = new metrics.LoggingCache(); + + equal( cache._cache.length, 0 ); + equal( cache.length(), 0 ); + var get = cache.get( 10 ); + ok( jQuery.type( get ) === 'array' && get.length === 0 ); + var remove = cache.remove( 10 ); + ok( jQuery.type( remove ) === 'array' && remove.length === 0 ); + equal( cache.length(), 0 ); + }); + + test( "cache add properly adds and removes data", function() { + var cache = new metrics.LoggingCache({ + maxSize : 5 + }); + var entry1 = [{ one: 1 }, 'two' ]; + cache.add( entry1 ); + + equal( cache._cache.length, 1 ); + equal( cache.length(), 1 ); + equal( cache._cache[0], JSON.stringify( entry1 ) ); + equal( cache.get( 1 ), JSON.stringify( entry1 ) ); + + var entry2 = { blah: { one: 1 }, bler: [ 'three', { two: 2 } ] }; + cache.add( entry2 ); + equal( cache.length(), 2 ); + equal( cache.stringify( 2 ), '[\n' + JSON.stringify( entry1 ) + ',\n' + JSON.stringify( entry2 ) + '\n]' ); + + // FIFO + var returned = cache.remove( 1 ); + equal( cache.length(), 1 ); + ok( jQuery.type( returned ) === 'array' && returned.length === 1 ); + var returned0 = returned[0]; + ok( jQuery.type( returned0 ) === 'string' && returned0 === JSON.stringify( entry1 ) ); + }); + + test( "cache past max loses oldest", function() { + var cache = new metrics.LoggingCache({ + maxSize : 5 + }); + for( var i=0; i<10; i+=1 ){ + cache.add({ index: i }); + } + equal( cache.length(), 5 ); + var get = cache.get( 5 ); + ok( JSON.parse( get[0] ).index === 5 ); + ok( JSON.parse( get[1] ).index === 6 ); + ok( JSON.parse( get[2] ).index === 7 ); + ok( JSON.parse( get[3] ).index === 8 ); + ok( JSON.parse( get[4] ).index === 9 ); + }); }); Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.