Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Packaging for deploy

  • Loading branch information...
commit 7afd5d22c1d44b93c7cb2250ea9e05ef7b8451f8 1 parent 150247e
Loren West authored
View
5 History.md
@@ -1,3 +1,8 @@
+0.6.10 / 2014-05-16
+===================
+
+ * Added cron/interval polling to RecipeProbe
+
0.6.9 / 2014-03-26
===================
View
90 dist/monitor-all.js
@@ -1,4 +1,4 @@
-/* monitor - v0.6.9 - 2014-03-26 */
+/* monitor - v0.6.10 - 2014-05-16 */
// Underscore.js 1.4.4
// http://underscorejs.org
@@ -10554,9 +10554,10 @@ if (typeof define === "function" && define.amd) {
// Module loading - this runs server-side only
var Monitor = root.Monitor || require('../Monitor'),
+ _ = Monitor._,
+ Cron = Monitor.Cron,
logger = Monitor.getLogger('RecipeProbe'),
vm = Monitor.commonJS ? require('vm') : null,
- _ = Monitor._,
Probe = Monitor.Probe;
/**
@@ -10585,6 +10586,18 @@ if (typeof define === "function" && define.amd) {
* monitors by name.
* @param [recipeName] {String} - Recipe name for logging
* @param [autoStart=false] {boolean} - Call the start control on instantiation?
+ * @param [triggeredBy] {Object} - Trigger the recipe by the items in the object.
+ * Items can include: 'interval', 'cron', and/or monitorName(s)
+ * If 'interval' is the key, the value is the interval in milliseconds
+ * If 'cron' is the key, the value is a string representing the cron pattern
+ * If any monitor name is the key, the value is the monitor event to trigger on.
+ * Example:
+ * triggeredBy: {
+ * interval: 5000, // This triggers the recipe every 5 seconds
+ * cron: '* * * * * *', // [second] [minute] [hour] [day of month] [month] [day of week]
+ * myMonitor: 'change:someAttribute change:someOtherAttribute'
+ * }
+ * If triggeredBy isn't specified, any monitor change will trigger the recipe.
* @param [started] {boolean} - Is the recipe started and currently active?
*/
var RecipeProbe = Monitor.RecipeProbe = Probe.extend({
@@ -10596,12 +10609,17 @@ if (typeof define === "function" && define.amd) {
monitors: {},
script: '',
autoStart: false,
- started: false
+ started: false,
+ triggeredBy: null
},
initialize: function(attributes, options){
var t = this;
+ // Periodic triggers
+ t.interval = null;
+ t.cronJob = null;
+
// Precondition test
if (_.size(t.get('monitors')) === 0) {
logger.error('initialize', 'No monitors defined in the recipe');
@@ -10629,7 +10647,7 @@ if (typeof define === "function" && define.amd) {
/**
* Start the recipe
*
- * This connects to each monitor and watches for change events
+ * This connects to each monitor and sets up the recipe triggers
*
* @method start_control
*/
@@ -10722,23 +10740,66 @@ if (typeof define === "function" && define.amd) {
* @method connectListeners
*/
connectListeners: function(connect) {
- var t = this;
- for (var monitorName in t.monitors) {
- t.monitors[monitorName][connect ? 'on' : 'off']('change', t.onChange, t);
+ var t = this,
+ triggeredBy = t.get('triggeredBy'),
+ onTrigger = t.onTrigger.bind(t);
+
+ // Default to listen on changes to all monitors
+ if (!triggeredBy) {
+ for (var monitorName in t.monitors) {
+ t.monitors[monitorName][connect ? 'on' : 'off']('change', t.onTrigger, t);
+ }
+ return;
+ }
+
+ // Process the elements in triggeredBy
+ for (var name in triggeredBy) {
+ var value = triggeredBy[name];
+
+ // Construct a new cron job
+ if (name === 'cron') {
+ if (connect) {
+ t.cronJob = new Cron.CronJob(value, onTrigger);
+ }
+ else {
+ if (t.cronJob.initiated) {
+ clearInterval(t.CronJob.timer);
+ }
+ else {
+ setTimeout(function(){clearInterval(t.cronJob.timer);}, 1000);
+ }
+ }
+ }
+
+ // Set a polling interval
+ else if (name === 'interval') {
+ if (connect) {
+ t.interval = setInterval(onTrigger, value);
+ }
+ else {
+ clearInterval(t.interval);
+ t.interval = null;
+ }
+ }
+
+ // Must be a monitor name
+ else {
+ t.monitors[name][connect ? 'on' : 'off'](value, onTrigger);
+ }
}
},
/**
- * Called when a change is detected
+ * Called when a trigger is fired
*
* @private
- * @method onChange
+ * @method onTrigger
*/
- onChange: function() {
+ onTrigger: function() {
var t = this;
t.run_control({}, function(error){
if (error) {
- logger.error('onChange', error);
+ logger.error('onTrigger', error);
}
});
},
@@ -10840,8 +10901,11 @@ if (typeof define === "function" && define.amd) {
(function(root){
// Module loading
- var Monitor = root.Monitor || require('../Monitor'), Probe = Monitor.Probe,
- Cron = Monitor.Cron, _ = Monitor._, Backbone = Monitor.Backbone;
+ var Monitor = root.Monitor || require('../Monitor'),
+ _ = Monitor._,
+ Cron = Monitor.Cron,
+ Probe = Monitor.Probe,
+ Backbone = Monitor.Backbone;
// Constants
var DEFAULT_POLL_INTERVAL = 1000;
View
4 dist/monitor-all.min.js
2 additions, 2 deletions not shown
View
90 dist/monitor.js
@@ -1,4 +1,4 @@
-/* monitor - v0.6.9 - 2014-03-26 */
+/* monitor - v0.6.10 - 2014-05-16 */
// Monitor.js (c) 2010-2014 Loren West and other contributors
// May be freely distributed under the MIT license.
@@ -3809,9 +3809,10 @@
// Module loading - this runs server-side only
var Monitor = root.Monitor || require('../Monitor'),
+ _ = Monitor._,
+ Cron = Monitor.Cron,
logger = Monitor.getLogger('RecipeProbe'),
vm = Monitor.commonJS ? require('vm') : null,
- _ = Monitor._,
Probe = Monitor.Probe;
/**
@@ -3840,6 +3841,18 @@
* monitors by name.
* @param [recipeName] {String} - Recipe name for logging
* @param [autoStart=false] {boolean} - Call the start control on instantiation?
+ * @param [triggeredBy] {Object} - Trigger the recipe by the items in the object.
+ * Items can include: 'interval', 'cron', and/or monitorName(s)
+ * If 'interval' is the key, the value is the interval in milliseconds
+ * If 'cron' is the key, the value is a string representing the cron pattern
+ * If any monitor name is the key, the value is the monitor event to trigger on.
+ * Example:
+ * triggeredBy: {
+ * interval: 5000, // This triggers the recipe every 5 seconds
+ * cron: '* * * * * *', // [second] [minute] [hour] [day of month] [month] [day of week]
+ * myMonitor: 'change:someAttribute change:someOtherAttribute'
+ * }
+ * If triggeredBy isn't specified, any monitor change will trigger the recipe.
* @param [started] {boolean} - Is the recipe started and currently active?
*/
var RecipeProbe = Monitor.RecipeProbe = Probe.extend({
@@ -3851,12 +3864,17 @@
monitors: {},
script: '',
autoStart: false,
- started: false
+ started: false,
+ triggeredBy: null
},
initialize: function(attributes, options){
var t = this;
+ // Periodic triggers
+ t.interval = null;
+ t.cronJob = null;
+
// Precondition test
if (_.size(t.get('monitors')) === 0) {
logger.error('initialize', 'No monitors defined in the recipe');
@@ -3884,7 +3902,7 @@
/**
* Start the recipe
*
- * This connects to each monitor and watches for change events
+ * This connects to each monitor and sets up the recipe triggers
*
* @method start_control
*/
@@ -3977,23 +3995,66 @@
* @method connectListeners
*/
connectListeners: function(connect) {
- var t = this;
- for (var monitorName in t.monitors) {
- t.monitors[monitorName][connect ? 'on' : 'off']('change', t.onChange, t);
+ var t = this,
+ triggeredBy = t.get('triggeredBy'),
+ onTrigger = t.onTrigger.bind(t);
+
+ // Default to listen on changes to all monitors
+ if (!triggeredBy) {
+ for (var monitorName in t.monitors) {
+ t.monitors[monitorName][connect ? 'on' : 'off']('change', t.onTrigger, t);
+ }
+ return;
+ }
+
+ // Process the elements in triggeredBy
+ for (var name in triggeredBy) {
+ var value = triggeredBy[name];
+
+ // Construct a new cron job
+ if (name === 'cron') {
+ if (connect) {
+ t.cronJob = new Cron.CronJob(value, onTrigger);
+ }
+ else {
+ if (t.cronJob.initiated) {
+ clearInterval(t.CronJob.timer);
+ }
+ else {
+ setTimeout(function(){clearInterval(t.cronJob.timer);}, 1000);
+ }
+ }
+ }
+
+ // Set a polling interval
+ else if (name === 'interval') {
+ if (connect) {
+ t.interval = setInterval(onTrigger, value);
+ }
+ else {
+ clearInterval(t.interval);
+ t.interval = null;
+ }
+ }
+
+ // Must be a monitor name
+ else {
+ t.monitors[name][connect ? 'on' : 'off'](value, onTrigger);
+ }
}
},
/**
- * Called when a change is detected
+ * Called when a trigger is fired
*
* @private
- * @method onChange
+ * @method onTrigger
*/
- onChange: function() {
+ onTrigger: function() {
var t = this;
t.run_control({}, function(error){
if (error) {
- logger.error('onChange', error);
+ logger.error('onTrigger', error);
}
});
},
@@ -4095,8 +4156,11 @@
(function(root){
// Module loading
- var Monitor = root.Monitor || require('../Monitor'), Probe = Monitor.Probe,
- Cron = Monitor.Cron, _ = Monitor._, Backbone = Monitor.Backbone;
+ var Monitor = root.Monitor || require('../Monitor'),
+ _ = Monitor._,
+ Cron = Monitor.Cron,
+ Probe = Monitor.Probe,
+ Backbone = Monitor.Backbone;
// Constants
var DEFAULT_POLL_INTERVAL = 1000;
View
4 dist/monitor.min.js
@@ -1,2 +1,2 @@
-/* monitor - v0.6.9 - 2014-03-26 */
-(function(e){var t=typeof exports!="undefined",n=t?require("backbone"):e.Backbone,r=t?require("underscore")._:e._,i=null,s=null,o=[],u=t?require("cron"):null,a=4,f=n.Model.extend({defaults:{id:"",name:"",probeName:"",probeClass:"",initParams:{},hostName:"",appName:"",appInstance:"",probeId:"",writableAttributes:[]},initialize:function(e,t){i.info("init",e)},connect:function(e){var t=this,n=Date.now();f.getRouter().connectMonitor(t,function(r){!r&&t.get("writableAttributes").length>0&&t.on("change",t.onChange,t),e&&e(r),r||(t.trigger("connect",t),t.trigger("change",t),i.info("connected",{initParams:t.get("initParams"),probeId:t.get("probeId")}),s.time("connect",Date.now()-n))})},getConnection:function(){var e=this;return e.probe&&e.probe.connection?e.probe.connection:null},isConnected:function(){var e=this;return e.probe!=null},disconnect:function(e){var t=this,n="manual_disconnect",r=Date.now(),o=t.get("probeId");t.off("change",t.onChange,t),f.getRouter().disconnectMonitor(t,n,function(n,u){e&&e(n),n?i.error("disconnect",{error:n}):(t.trigger("disconnect",u),i.info("disconnected",{reason:u,probeId:o}),s.time("disconnect",Date.now()-r))})},onChange:function(){var e=this,t=e.get("writableAttributes"),n={},s=e.toProbeJSON();delete s.id;for(var o in s){var u=t==="*"||t.indexOf(o)>=0;u&&!r.isEqual(e.attributes[o],e._probeValues[o])&&(n[o]=e.attributes[o])}f._.size(n)&&e.control("set",n,function(t){t&&i.error("probeSet","Problem setting writable value",n,e.toMonitorJSON())})},control:function(e,t,n){var r=this,o=r.probe,u="control."+r.get("probeClass")+"."+e,a=Date.now();typeof t=="function"&&(n=t,t=null),i.info(u,t);var f=function(e,t){e?i.error(u,e):(i.info("return."+u,t),s.time(u,Date.now()-a)),n&&n.apply(r,arguments)};if(!o)return f("Probe not connected");o.connection?o.connection.emit("probe:control",{probeId:r.get("probeId"),name:e,params:t},f):o.onControl(e,t,f)},toProbeJSON:function(e){var t=this,n={id:t.get("probeId")};return r.each(t.toJSON(e),function(e,r){r in t.defaults||(n[r]=e)}),n},toMonitorJSON:function(e){var t=this,n={};return r.each(t.toJSON(e),function(e,r){r in t.defaults&&(n[r]=e)}),n},toServerString:function(){return f.toServerString(this.toMonitorJSON())}});f.generateUniqueId=function(){function e(){return((1+Math.random())*65536|0).toString(16).substring(1)}return s.increment("generateUniqueId"),e()+e()+"-"+e()+"-"+e()+"-"+e()+"-"+e()+e()+e()},f.generateUniqueCollectionId=function(e,t){var n="";return t=t||"",e.idSequence||(e.idSequence=0,e.forEach(function(n){var r=n.get("id")||"",i=+r.substr(t.length);e.idSequence<=i&&(e.idSequence=i+1)})),t+e.idSequence++},f.getRouter=function(){return f.defaultRouter||(f.defaultRouter=new f.Router,e.io&&f.defaultRouter.setGateway({socket:e.io.connect()})),f.defaultRouter},f.start=function(e,t){return i.info("start",e),t=t||function(){},f.defaultServer?t():(f.defaultServer=new f.Server,f.defaultServer.start(e,t)),f},f.stop=function(e){i.info("stop"),e=e||function(){},f.defaultServer?(f.defaultServer.stop(e),delete f.defaultServer):e()},f.toServerString=function(e){var t=e.hostName;return e.appName&&(t+=":"+e.appName,e.appInstance&&(t+=":"+e.appInstance)),t},f.deepCopy=function(e,t){t=typeof t=="undefined"?a:t;if(typeof e!="object"&&typeof e!="function")return e;var n="[Object]";typeof e=="function"?n="[Function]":Array.isArray(e)&&(n="[Array]");if(t<=0)return n;var i=Array.isArray(e)?[]:{};for(var s in e)if(!e.hasOwnProperty||e.hasOwnProperty(s)){var o=e[s];typeof o=="object"||typeof o=="function"?i[s]=f.deepCopy(o,t-1):i[s]=o}return typeof e=="function"&&(r.isEmpty(i)?i=n:i=r.extend({constructor:n},i)),i},f.stringify=function(e,t,n){return n=typeof n=="undefined"?2:n,JSON.stringify(f.deepCopy(e,t),null,n)},f.setStatLoggerClass=function(e){f.getStatLogger=function(t){return new e(t)},s=f.getStatLogger("Monitor")},f.setLoggerClass=function(e){f.getLogger=function(t){return new e(t)},i=f.getLogger("Monitor")},f.List=n.Collection.extend({model:f});var l={appName:"unknown",serviceBasePort:42e3,portsToScan:20,allowExternalConnections:!1,consoleLogListener:{pattern:"{trace,warn,error,fatal}.*"},autoStart:[]};t?(f.Config=require("config"),f.Config.setModuleDefaults("Monitor",l)):f.Config={Monitor:l},f._=r,f.Backbone=n,f.Cron=u,f.commonJS=t,t?module.exports=f:e.Monitor=f;var c=f.Config.Monitor.autoStart;f._.size(c)&&setTimeout(function(){f._.each(c,function(e){var t=new f(e);t.connect(function(n){n&&i.error("autoStart","Error auto-starting monitor",e,n),o.push(t)})})},0)})(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.commonJS?require("events").EventEmitter.prototype:t.Backbone.Events,r=t._,i=!1,s=t.Stat=function(e){var t=this;t.module=e},o=s.prototype;s.eventRegex={},o.increment=function(e,t){t=r.isNumber(t)?t:1,s._emit(this.module,e,t,"c")},o.decrement=function(e,t){t=r.isNumber(t)?t:1,s._emit(this.module,e,t*-1,"c")},o.gauge=function(e,t){s._emit(this.module,e,t,"g")},o.time=function(e,t){s._emit(this.module,e,t,"ms")},s._emit=function(e,t,n,r){var o,u;if(i)return;i=!0;for(o in s._events){u||(u=e+"."+t);var a=s.eventRegex[o];a||(a=s.eventRegex[o]=s._buildRegex(o)),a.test(u)&&s.emit(o,e,t,n,r)}i=!1},s._buildRegex=function(e){var t="",n="",r=e.length-1,i=!1;if(/^\/[^\/]*\/i*$/.test(e))/i$/.test(e)&&(n="i",e=e.replace(/i$/,"")),t="^"+e.replace(/^\//,"").replace(/\/$/,"")+"$";else{for(var s=0,o=e.length;s<o;s++){var u=e.substr(s,1);switch(u){case".":u="\\.";break;case"*":u=s===r?".*":"[^\\.]*";break;case"{":u="(",i=!0;break;case"}":u=")",i=!1;break;case",":i&&(u="|")}t+=u}t="^"+t+"$"}return new RegExp(t,n)},r.extend(s,n),t.setStatLoggerClass(s)}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.commonJS?require("events").EventEmitter.prototype:t.Backbone.Events,r=t.Stat,i=new r("Log"),s=t._,o=!1,u=t.Log=function(e){var t=this;t.module=e},a=u.prototype;u.eventRegex={},["trace","debug","info","warn","error","fatal"].forEach(function(e){a[e]=function(t){u._emit(e,this.module,t,arguments)}}),u._emit=function(e,t,n,a){var f,l=e+"."+t+"."+n;if(o)return;o=!0,i.increment(l);for(f in u._events){var c=u.eventRegex[f];c||(c=u.eventRegex[f]=r._buildRegex(f));if(c.test(l)){var h=s.toArray(a),p=u.emit||u.trigger;h.splice(0,1,f,e,t,n),p.apply(u,h)}}o=!1},s.extend(u,n),t.setLoggerClass(u),u.console=function(e,n,r){var i=(new Date).toJSON(),o=s.toArray(arguments),u="["+i+"] ["+e.toUpperCase()+"] "+n;o.splice(0,3),o.length===0?o=[r]:u+="."+r,u+=" - ";if(o.length===1&&typeof o[0]=="string")u+=o[0];else try{u+=JSON.stringify(o)}catch(a){u+=t.stringify(o)}e==="error"||e==="fatal"?console.error(u):console.log(u)};var f=t.Config.Monitor.consoleLogListener.pattern;f&&u.on(f,u.console)}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.getLogger("Probe"),r=t.getStatLogger("Probe"),i=t.Cron,s=t._,o=t.Backbone,u=t.Probe=o.Model.extend({defaults:{id:null},initialize:function(e,t){var r=this;n.info("init",r.toJSON(),t)},release:function(){var e=this;n.info("release",e.toJSON())},onControl:function(e,t,i){var s=this,o=s[e+"_control"],u=Date.now(),a,f="onControl."+s.probeClass+"."+e;t=t||{},i=i||function(){},n.info(f,s.get("id"),t);if(!o)return a="No control function: "+e,n.error(f,a),i({msg:a});var l=function(e){if(e)return n.error(f+".whenDone",e),i(e);var o=Date.now()-u;n.info(f,t),r.time(s.logId,o),i.apply(null,arguments)};setTimeout(function(){try{o.call(s,t,l)}catch(n){a="Error calling control: "+s.probeClass+":"+e,l({msg:a,err:n.toString()})}},0)},set_control:function(e,t){var r=this,i=r.get("writableAttributes")||[];if(i!=="*")for(var s in e)if(i.indexOf(s)<0)return t({code:"NOT_WRITABLE",msg:"Attribute not writable: "+s});var o=null;return r.set(e)||(o={code:"VALIDATION_ERROR",msg:"Data set failed validation"},n.warn("set_control",o)),t(o)},ping_control:function(e,t){return t(null,"pong")}});u.classes={},u.extend=function(e){var t=this,n=o.Model.extend.apply(t,arguments);return e.probeClass&&(u.classes[e.probeClass]=n),n},u.List=o.Collection.extend({model:u})}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.Cron,r=t._,i=t.Backbone,s=t.getLogger("Connection"),o=t.getStatLogger("Connection"),u=t.Config,a=e.io||require("socket.io-client"),f=t.Probe,l=1,c=t.Connection=i.Model.extend({defaults:{hostName:"",hostPort:null,url:null,socket:null,gateway:!1,firewall:!1,remoteHostName:null,remoteAppName:null,remoteAppInstance:0,remotePID:0,remoteProbeClasses:[],remoteGateway:!1,remoteFirewall:!1},initialize:function(e){var t=this;t.connecting=!0,t.connected=!1,t.socketEvents=null,t.remoteProbeIdsByKey={},t.remoteProbesById={},t.incomingMonitorsById={},t.logId=l++ +".",e.socket?(t.bindConnectionEvents(),s.info(t.logId+"connect",{socketId:e.socket.id})):e.url||e.hostName&&e.hostPort?(t.connect(),s.info(t.logId+"connect",{url:t.get("url")})):s.error("init","Connection must supply a socket, url, or host name/port")},connect:function(){var e=this,t=e.get("hostName"),n=e.get("hostPort"),r=e.get("url");r||(r=e.attributes.url="http://"+t+":"+n,e.set("url",r));var i={"force new connection":!0,reconnect:!1},s=a.connect(r,i);e.set({socket:s}).bindConnectionEvents()},ping:function(e){var t=this;e=e||function(){};var n=function(){t.off("pong",n),e()};t.on("pong",n),t.emit("connection:ping")},disconnect:function(e){var t=this,n=t.get("socket");t.connecting=!1,t.connected=!1,t.socketEvents&&(t.removeAllEvents(),n.disconnect(),t.trigger("disconnect",e),s.info(t.logId+"disconnect",e))},isThisHost:function(e){var t=this,n=e.toLowerCase(),r=t.get("hostName"),i=t.get("remoteHostName");return r=r&&r.toLowerCase(),i=i&&i.toLowerCase(),n===r||n===i},emit:function(){var e=this,n=e.get("socket");s.info(e.logId+"emit",t.deepCopy(arguments,5)),n.emit.apply(n,arguments)},addEvent:function(e,t){var n=this,r=n.get("socket");n.socketEvents=n.socketEvents||{};if(n.socketEvents[e])throw new Error("Event already connected: "+e);return r.on(e,t),n.socketEvents[e]=t,n},removeEvent:function(e){var t=this,n=t.get("socket");return t.socketEvents&&t.socketEvents[e]&&(n.removeListener(e,t.socketEvents[e]),delete t.socketEvents[e]),t},removeAllEvents:function(){var e=this,t=e.get("socket");for(var n in e.socketEvents)t.removeListener(n,e.socketEvents[n]);return e.socketEvents=null,e},bindConnectionEvents:function(){var e=this,n=e.get("socket");if(e.socketEvents)throw new Error("Already connected");e.socketEvents={},e.addEvent("connect_failed",function(){e.trigger("error","connect failed"),e.disconnect("connect failed")}),e.addEvent("disconnect",function(){e.disconnect("remote_disconnect")}),e.addEvent("error",function(t){e.trigger("error",t),e.disconnect("connect error")}),e.addEvent("probe:connect",e.probeConnect.bind(e)),e.addEvent("probe:disconnect",e.probeDisconnect.bind(e)),e.addEvent("probe:control",e.probeControl.bind(e)),e.addEvent("connection:ping",function(){n.emit("connection:pong")}),e.addEvent("connection:pong",function(){e.trigger("pong")}),e.addEvent("connection:info",function(t){e.set({remoteHostName:t.hostName,remoteAppName:t.appName,remoteAppInstance:t.appInstance,remotePID:t.pid,remoteProbeClasses:t.probeClasses,remoteGateway:t.gateway,remoteFirewall:t.firewall}),e.connecting=!1,e.connected=!0,e.trigger("connect")});var i=typeof process=="undefined"?1:process.pid,s=""+(typeof process=="undefined"?i:process.env.NODE_APP_INSTANCE||i);n.emit("connection:info",{hostName:t.getRouter().getHostName(),appName:u.Monitor.appName,appInstance:s,pid:i,probeClasses:r.keys(f.classes),gateway:e.get("gateway"),firewall:e.get("firewall")})},probeConnect:function(e,n){n=n||function(){};var i=this,u="",a=t.getRouter(),f=i.get("gateway"),l=Date.now(),c=i.get("firewall"),h=r.extend({},e);if(c)return u="firewalled",s.error("probeConnect",u,h),n(u);a.determineConnection(e,f,function(r,u){if(r)return n(r);if(u&&!f)return n("Not a gateway");var c=function(r,u){if(r)return s.error(i.logId+"probeConnect",r,h),n(r);var a=u.get("id");h.id=a;var f=i.incomingMonitorsById[a];if(f!=null)return u.refCount--,h.dupDetected=!0,h.refCount=u.refCount,s.info(i.logId+"probeConnected",h),n(null,f.probe.toJSON());f=new t(e),f.set("probeId",a),i.incomingMonitorsById[a]=f,f.probe=u,f.probeChange=function(){try{i.emit("probe:change:"+a,u.changedAttributes())}catch(e){s.error("probeChange",e,u,h)}},u.connectTime=Date.now();var c=u.connectTime-l;h.duration=c,h.refCount=u.refCount,s.info(i.logId+"probeConnected",h),o.time(i.logId+"probeConnected",c),n(null,u.toJSON()),u.on("change",f.probeChange),i.on("disconnect",function(){i.probeDisconnect({probeId:a})})};u?a.connectExternal(e,u,c):a.connectInternal(e,c)})},probeDisconnect:function(e,n){n=n||function(){};var r=this,i="",u=t.getRouter(),a=e.probeId,f=r.incomingMonitorsById[a],l=r.get("firewall"),c=null,h=null;if(!f||!f.probe)return n(null);h=f.probe,c={probeClass:f.get("probeClass"),initParams:f.get("initParams"),probeId:a};var p=function(e){if(e)return s.error(r.logId+"probeDisconnect",e),n(e);var t=c.duration=Date.now()-h.connectTime;return h.off("change",f.probeChange),f.probe=f.probeChange=null,delete r.incomingMonitorsById[a],s.info(r.logId+"probeDisconnected",c),o.time(r.logId+"probeDisconnected",t),n(null)};h&&h.connection?u.disconnectExternal(h.connection,a,p):u.disconnectInternal(a,p)},probeControl:function(e,n){n=n||function(){};var r=this,i="",u=r.logId+"probeControl",a=Date.now(),f=t.getRouter(),l=r.get("firewall");if(l)return i="firewalled",s.error(u,i),n(i);var c=function(e){if(e)return s.error(u,e),n(e);var t=Date.now()-a;return s.info(u+".return",{duration:t,returnArgs:arguments}),o.time(u,t),n.apply(null,arguments)},h=f.runningProbesById[e.probeId];if(!h){var p=r.incomingMonitorsById[e.probeId];return p?p.control(e.name,e.params,function(e,t){c(e,t)}):(i="Probe id not found: "+e.probeId,s.error(i),n(i))}return u=u+"."+h.probeClass+"."+e.name,s.info(u+".request",{params:e.params,probeId:e.probeId}),h.onControl(e.name,e.params,c)}});c.List=i.Collection.extend({model:c})}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.Config,r=t._,i=t.Backbone,s=t.getLogger("Server"),o=t.getStatLogger("Server"),u=t.Connection,a=t.commonJS?require("http"):null,f=e.io||require("socket.io"),l=t.Server=i.Model.extend({initialize:function(e){var t=this;t.isListening=!1,t.connections=new u.List},start:function(e,t){typeof e=="function"&&(t=e,e=null),e=e||{},t=t||function(){};var r=this,i=r.get("server"),o,u=Date.now(),f=e.port||n.Monitor.serviceBasePort,l=e.attempt||1,c=n.Monitor.allowExternalConnections;if(l>n.Monitor.portsToScan)return o={err:"connect:failure",msg:"no ports available"},s.error("start",o),t(o);if(i)r.bindEvents(t);else{i=a.createServer(),i.on("error",function(e){if(e.code==="EADDRINUSE")return r.get("port")?(s.error("portInUse",{host:h,port:f}),t({err:"portInUse"})):(s.info("portInUse",{host:h,port:f}),r.start({port:f+1,attempt:l+1},t));t(e)});var h=c?"0.0.0.0":"127.0.0.1";i.listen(f,h,function(){process.env.NODE_APP_INSTANCE||(process.env.NODE_APP_INSTANCE=""+(f-n.Monitor.serviceBasePort+1)),r.set({server:i,port:f}),r.bindEvents(t),s.info("listening",{appName:n.Monitor.appName,NODE_APP_INSTANCE:process.env.NODE_APP_INSTANCE,listeningOn:h,port:f})})}},bindEvents:function(e){var n=this,r=n.get("server");r.on("clientError",function(e){s.error("bindEvents","clientError detected on server",e),n.trigger("error",e)}),r.on("close",function(e){r.hasEmittedClose=!0,s.info("bindEvents.serverClose","Server has closed",e),n.stop()});var i={log:!1};n.socketServer=f.listen(r,i),n.socketServer.sockets.on("connection",function(e){var r=t.getRouter().addConnection({socket:e,gateway:n.get("gateway")});n.connections.add(r);var i=function(e){n.connections.remove(r),t.getRouter().removeConnection(r),r.off("disconnect",i),s.info("client.disconnect","Disconnected client socket")};r.on("disconnect",i),s.info("client.connect","Connected client socket")}),n.isListening=!0,e&&e(null),n.trigger("start")},stop:function(e){var n=this,r=n.get("server"),i=t.getRouter();return e=e||function(){},n.isListening?(n.connections.each(i.removeConnection,i),n.connections.reset(),n.isListening=!1,r.close(),n.trigger("stop"),e()):e()}});l.List=i.Collection.extend({model:l})}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.getLogger("Router"),r=t.getStatLogger("Router"),i=t.Cron,s=t._,o=t.Backbone,u=t.Config,a=t.Probe,f=t.Connection,l=t.Server,c=e.io||require("socket.io"),h=t.commonJS?require("os").hostname():null,p=1e4,d=t.Router=o.Model.extend({initialize:function(){var e=this;e.defaultGateway=null,e.firewall=!1,e.connections=new f.List,e.runningProbesByKey={},e.runningProbesById={},e.addHostCallbacks={},n.info("init","Router initialized")},setFirewall:function(e){var r=t.getRouter();r.firewall=e,n.info("setFirewall",e)},setGateway:function(e){var t=this;return e.gateway=!1,e.firewall=!0,t.defaultGateway=t.addConnection(e)},getHostName:function(){var n=e.localStorage;return h||(n&&(h=n.hostName),h=h||t.generateUniqueId(),n&&(n.hostName=h)),h},setHostName:function(e){h=e,n.info("setHostName",e)},addConnection:function(e){var r=this,i=Date.now();s.isUndefined(e.firewall)&&(e=s.extend({},e,{firewall:r.firewall})),e.id=t.generateUniqueCollectionId(r.connections);var o="Conn_"+e.id;e.hostName&&(o+=" - "+e.hostName+":"+e.hostPort),n.info("addConnection",o);var u=new f(e),a=function(){r.trigger("connection:add",u),n.info("connected",o,Date.now()-i+"ms")},l=function(){r.removeConnection(u),u.off("connect",a),u.off("disconnect",a),n.info("disconnected",o,Date.now()-i+"ms")};return u.on("connect",a),u.on("disconnect",l),r.connections.add(u),u},removeConnection:function(e){var t=this;n.info("removeConnection","Conn_"+e.id),e.disconnect("connection_removed"),t.connections.remove(e),t.trigger("connection:remove",e)},connectMonitor:function(e,t){t=t||function(){};var r=this,i=e.toMonitorJSON(),o=null,u=i.probeName,a=i.probeClass,f=Date.now(),l=a+"."+e.toServerString().replace(/:/g,".");if(!a&&!u){var c="probeName or probeClass must be set";return n.error("connectMonitor",c),t(c)}r.determineConnection(i,!0,function(u,a){if(u)return t(u);var f=function(r,i){if(r)return t(r);o=i.toJSON(),o.probeId=o.id,delete o.id,e.probe=i,e._probeValues=s.clone(o),e.set(o,{silent:!0}),e.probeChange=function(){var t=i.changedAttributes();t&&(e._probeValues=s.clone(i.toJSON()),e.set(i.changedAttributes()),n.info("probeChange",{probeId:o.probeId,changed:i.changedAttributes()}))},i.on("change",e.probeChange),t(null)};a?r.connectExternal(i,a,f):r.connectInternal(i,f)})},disconnectMonitor:function(e,t,n){n=n||function(){};var r=this,i=e.probe,s=e.get("probeId");if(!i)return n("Monitor must be connected");var o=function(r){return r?n(r):(i.off("change",e.probeChange),e.set({probeId:null}),e.probe=e.probeChange=null,n(null,t))};i.connection?r.disconnectExternal(i.connection,s,o):r.disconnectInternal(s,o)},buildProbeKey:function(e){var t=e.probeClass,n=e.initParams;return e.probeName?e.probeName:(n&&s.keys(n).sort().forEach(function(e){t+=":"+e+"="+n[e]}),t)},determineConnection:function(e,r,i){var s=this,o=null,f=e.probeName,l=e.probeClass,c="",h=e.hostName,p=e.appName,d=e.appInstance,v=s.getHostName().toLowerCase(),m=u.Monitor.appName||"unknown",g=typeof process!="undefined"?process.env.NODE_APP_INSTANCE:"1",y=function(t){t||(delete e.hostName,delete e.appName,delete e.appInstance);var r=function(){u(),i(null,o)},s=function(e){u(),n.error("connect.error",e),i({msg:"connection error",err:e})},u=function(){o.off("connect",r),o.off("error",s)};if(o&&o.connecting){o.on("connect",r),o.on("error",s);return}return o&&!o.connected?(o.on("connect",r),o.on("error",s),o.connect()):i(null,o)};h=h?h.toLowerCase():null;var b=!h||h===v,w=!p||p===m,E=!d||d===g;if(b&&w&&E){if(s.runningProbesByKey[f]||a.classes[l]!=null)return i(null,null);var S=t.Config.Monitor.autoStart;if(f&&!l&&S.length){var x=t._.find(S,function(e){return e.probeName===f});if(x){setTimeout(function(){s.determineConnection(e,r,i)},10);return}}return s.defaultGateway?(o=s.defaultGateway,y(!0)):(c='Probe class "'+l+'" not available in this process',n.error("connect.internal",c),i({err:c}))}o=s.findConnection(h,p,d);if(o)return y();if(s.defaultGateway)return o=s.defaultGateway,y(!0);if(h&&r){s.addHostConnections(h,function(r){return r?(n.error("connect.toHost",r),i(r)):(o=s.findConnection(h,p,d),o?y():(c="No route to host: "+t.toServerString(e),n.error("connect.toHost",c),i({err:c})))});return}return h?(c="Not a gateway to remote monitors",n.error("connect",c),i({msg:c})):(c="No host specified for app: "+p,n.error("connect",c),i({msg:c},null))},findConnection:function(e,t,n){var r=this,i=0;return r.connections.find(function(r){var i=!e||r.isThisHost(e),s=!t||t===r.get("remoteAppName"),o=!n||n===r.get("remoteAppInstance"),u=r.get("remoteFirewall");return!u&&i&&s&&o})},findConnections:function(e,t){var n=this;return n.connections.filter(function(n){var r=!e||n.isThisHost(e),i=!t||t===n.get("remoteAppName"),s=n.get("remoteFirewall");return!s&&r&&i})},addHostConnections:function(e,t){var r=this,i="",s=[],o=u.Monitor.serviceBasePort,a=u.Monitor.serviceBasePort+u.Monitor.portsToScan-1;r.addHostCallbacks[e]||(r.addHostCallbacks[e]=[]);if(r.addHostCallbacks[e].push(t)>1)return;var f=function(t){r.addHostCallbacks[e].forEach(function(e){e(t)}),delete r.addHostCallbacks[e]};r.connections.each(function(t){var n=t.get("hostName").toLowerCase(),r=t.get("hostPort");n===e&&r>=o&&r<=a&&s.push(r)});var l=u.Monitor.portsToScan-s.length;if(l===0)return i="All monitor ports in use. Increase the Config.Monitor.portsToScan configuration",n.error("addHostConnections",i),f(i);var c=function(){var e=this;e.off("connect disconnect error",c);if(--l===0)return f()};for(var h=o;h<=a;h++)if(s.indexOf(h)<0){var p=r.addConnection({hostName:e,hostPort:h});p.on("connect disconnect error",c,p)}},connectInternal:function(e,r){var i=this,s=i.buildProbeKey(e),o=e.probeName,u=e.probeClass,f=e.initParams,l=null,c=function(e){setTimeout(function(){if(e){if(l){delete i.runningProbesByKey[s],delete i.runningProbesById[l.id];try{l.release()}catch(t){}}return r(e)}l.refCount++,n.info("connectInternal",{probeKey:s,probeId:l.id}),r(null,l)},0)};l=i.runningProbesByKey[s];if(!l){var h=a.classes[u];if(!h)return c({msg:"Probe not available: "+u});var p={asyncInit:!1,callback:c};try{var d=t.deepCopy(f);o&&(d.probeName=o),l=new h(d,p),l.set({id:t.generateUniqueId(),writableAttributes:h.prototype.writableAttributes||[]}),l.refCount=0,l.probeKey=s,i.runningProbesByKey[s]=l,i.runningProbesById[l.id]=l}catch(v){var m={msg:"Error instantiating probe "+u,error:v.message};return c(m)}if(p.asyncInit)return}c()},disconnectInternal:function(e,t){var n=this,r=n.runningProbesById[e];if(!r)return t("Probe not running");--r.refCount===0&&setTimeout(function(){if(r.refCount===0){try{r.release()}catch(t){}delete n.runningProbesByKey[r.probeKey],delete n.runningProbesById[e]}},p),t(null,r)},connectExternal:function(e,r,i){var s=this,o="",u=s.buildProbeKey(e),f=r.remoteProbeIdsByKey[u],l=r.remoteProbesById[f];if(!l){r.emit("probe:connect",e,function(s,c){return s?(o="probe:connect returned an error for probeClass '"+e.probeClass+"' on "+t.toServerString(e),i({err:s,msg:o})):(f=c.id,l=r.remoteProbesById[f],l?(l.refCount++,n.info("connectExternal.connected.existingProxy",{probeId:f,refCount:l.refCount,whileWaiting:!0}),i(null,l)):(l=new a(c),l.refCount=1,l.connection=r,r.remoteProbeIdsByKey[u]=f,r.remoteProbesById[f]=l,r.addEvent("probe:change:"+f,function(e){l.set(e)}),n.info("connectExternal.connected.newProxy",{probeId:f}),i(null,l)))});return}return l.refCount++,n.info("connectExternal.connected.existingProxy",{probeId:f,refCount:l.refCount}),i(null,l)},disconnectExternal:function(e,t,n){var r=this,i=e.remoteProbesById[t];if(!i)return n("Probe not running");if(--i.refCount===0)return i.release(),i.connection=null,delete e.remoteProbesById[t],delete e.remoteProbeIdsByKey[i.probeKey],e.removeEvent("probe:change:"+t),e.emit("probe:disconnect",{probeId:t},function(e){return n(e)});n(null)}})}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.getLogger("Sync"),r=t.Backbone,i=t._,s="create",o="read",u="update",a="delete";t.Sync=function(e,t){if(!e)throw new Error("Sync class name must be provided");var r=new f(e,t);return function(t,i,s){return n.info("sync",{className:e,method:t,model:i.toJSON(),options:s}),r._sync(t,i,s)}};var f=function(e,t){var r=this;n.info("syncInit",e,t),r.className=e,r.options=t||{}};f.prototype._sync=function(e,i,u){var a=this;u=u||{};if(u.liveSync&&i instanceof r.Collection)return u.error(null,"Cannot liveSync with a collection");if(!i.has("id")){if(e!==s)return u.error(null,"ID element must be set.");i.set({id:t.generateUniqueId()},{silent:!0}),n.info("_sync.generateUniqueId",a.className,i.toJSON(),u)}if(e===s&&u.liveSync){a._sync(e,i,{error:u.error,success:function(e){a._sync(o,i,u)}});return}var f=function(e,t){e?(u.silenceErrors||n.error("_sync.onComplete",a.className,e),u.error(null,e)):(n.info("_sync.onComplete",a.className,i.get("id")),u.success(t))};if(i.syncMonitor||a.syncMonitor&&!u.liveSync){var l=i.syncMonitor||a.syncMonitor,c=a._getOpts(e,i);l.control(e,c,f)}else u.liveSync?a._connectInstanceMonitor(e,i,u,f):a._connectClassMonitor(e,i,u,f)},f.prototype._connectClassMonitor=function(e,r,i,s){var o=this;n.info("connectClassMonitor",o.className,e,r.toJSON());var u=o._getMonitorParams(null),a=new t(u);a.connect(function(t){if(t)return i.silenceErrors||n.error("connectClassMonitor",t),s(t);o.syncMonitor=a;var u=o._getOpts(e,r);a.control(e,u,s)})},f.prototype._connectInstanceMonitor=function(e,r,s,u){var a=this,f,l=r.get("id"),c=function(e){if(e)return u(e);var t=function(){n.info("disconnectLiveSync",a.className,r.toJSON()),r.off("change",s),r.syncMonitor.off("change",o),r.syncMonitor.disconnect(),r.syncMonitor=null},s=function(e,s){s=s||{};if(i.isEqual(JSON.parse(JSON.stringify(r)),JSON.parse(JSON.stringify(r.syncMonitor.get("model"))))){n.info("modelListener.noChanges",a.className,r.toJSON());return}if(r.get("id")!==l)return n.info("modelListener.alteredId",a.className,r.toJSON()),t();s.isSyncChanging||(n.info("modelListener.saving",a.className,r.toJSON()),r.save())},o=function(e,s){var o=r.syncMonitor.get("model");if(i.isEqual(JSON.parse(JSON.stringify(r)),JSON.parse(JSON.stringify(o)))){n.info("monitorListener.noChanges",a.className,o);return}var u=i.size(o)===0;if(u||o.id!==l)n.info("modelListener.deleted",a.className,o),t();var f={isSyncChanging:!0};u?(n.info("modelListener.deleting",a.className,o),r.clear(f)):(n.info("modelListener.setting",a.className,o),r.clear({silent:!0}),r.set(o,f))};r.on("change",s),r.syncMonitor.on("change",o),n.info("connectInstanceMonitor.done",a.className,r.toJSON()),u(null,r.syncMonitor.get("model"))},h=a._getMonitorParams(l);f=new t(h),f.connect(function(t){if(t)return s.silenceErrors||n.error("connectInstanceMonitor.monitorConnect",t),c(t);r.syncMonitor=f;if(e===o)return c();var i=a._getOpts(e,r);n.info("connectInstanceMonitor.forwarding",e,a.className,r.toJSON()),f.control(e,i,c)})},f.prototype._getOpts=function(e,t){var n={};switch(e){case o:case a:n.id=t.get("id");break;case s:case u:n.model=t.toJSON()}return n},f.prototype._getMonitorParams=function(e){var t=this,n=i.pick(t.options,"hostName","appName","appInstance");return n.probeClass="Sync",n.initParams={className:t.className},e&&(n.initParams.modelId=e),n}}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t.DataModelProbe=t.Probe.extend({probeClass:"DataModel",writableAttributes:"*"})}(this),function(root){var Monitor=root.Monitor||require("../Monitor"),logger=Monitor.getLogger("RecipeProbe"),vm=Monitor.commonJS?require("vm"):null,_=Monitor._,Probe=Monitor.Probe,RecipeProbe=Monitor.RecipeProbe=Probe.extend({probeClass:"Recipe",writableAttributes:[],defaults:{recipeName:"",monitors:{},script:"",autoStart:!1,started:!1},initialize:function(e,t){var n=this;if(_.size(n.get("monitors"))===0){logger.error("initialize","No monitors defined in the recipe");return}n.monitors={},n.get("autoStart")&&(t.asyncInit=!0,n.start_control({},t.callback))},release:function(){var e=this,t=arguments;e.stop_control({},function(){Probe.prototype.release.apply(e,t)})},start_control:function(e,t){var n=this,r=!1,i=n.get("monitors");if(n.get("started")){var s={code:"RUNNING",msg:"Cannot start - the recipe is already running."};return logger.warn(s),t(s)}var o=function(e){if(r)return;if(e){var i={code:"CONNECT_ERROR",err:e};return r=!0,logger.error("start",i),t(i)}for(var s in n.monitors)if(!n.monitors[s].isConnected())return;n.set({started:!0}),n.connectListeners(!0),t()};for(var u in i)n.monitors[u]=new Monitor(i[u]),n.monitors[u].connect(o)},stop_control:function(e,t){var n=this,r=!1;if(!n.get("started")){var i={code:"NOT_RUNNING",msg:"The recipe is already stopped."};return logger.warn("precondition",i),t(i)}var s=function(e){if(r)return;if(e){var i={code:"DISONNECT_ERROR",err:e};return r=!0,logger.error("onDisconnect",i),t(i)}for(var s in n.monitors)if(n.monitors[s].isConnected())return;n.set({started:!1}),n.compiledScript=null,t()};n.connectListeners(!1),n.context=null;for(var o in n.monitors)n.monitors[o].disconnect(s)},connectListeners:function(e){var t=this;for(var n in t.monitors)t.monitors[n][e?"on":"off"]("change",t.onChange,t)},onChange:function(){var e=this;e.run_control({},function(e){e&&logger.error("onChange",e)})},run_control:function(e,t){var n=this,r=null;if(!n.get("started"))return r={code:"NOT_RUNNING",msg:"Cannot run - recipe not started."},logger.warn(r),t(r);n.name=n.get("probeName")||n.get("id");if(!n.context){n.context=vm?vm.createContext({}):{},n.context.console=console,n.context.logger=Monitor.getLogger("Recipe.run."+n.name);for(var i in n.monitors)n.context[i]=n.monitors[i]}try{n.run(n.context)}catch(s){r="Error running script: "+s.toString(),logger.error("run_control",r)}t(r)},run:function(context){var t=this,script=t.get("script");vm?(t.compiledScript||(t.compiledScript=vm.createScript(script)),t.compiledScript.runInContext(context,t.name)):(eval(t.bringLocal(context)),eval(script))},bringLocal:function(e){var t,n=[];for(t in e)n.push("var "+t+" = context."+t+";");return n.join("\n")}})}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t.Probe,r=t.Cron,i=t._,s=t.Backbone,o=1e3,u="* * * * * *",a=t.PollingProbe=n.extend({defaults:i.extend({},n.prototype.defaults,{pollInterval:null,cronPattern:u}),initialize:function(){var e=this,t=e.get("pollInterval"),i=e.get("cronPattern"),s=function(){e.poll()};n.prototype.initialize.apply(e,arguments),t==null&&i===u&&(t=o),e.poll();if(t!==0)if(t)e.timer=setInterval(s,t);else{if(!r)throw new Error("Cron is not available in this client");e.cronJob=new r.CronJob(i,s)}},release:function(){var e=this,t=e.cronJob?e.cronJob.timer:e.timer;e.cronJob&&!e.cronJob.initiated?setTimeout(function(){clearInterval(e.cronJob.timer)},1e3):e.timer&&clearInterval(t),e.timer=e.cron=null,n.prototype.release.apply(e,arguments)}})}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t.Probe,r=t._,i=1e3,s=t.StreamProbe=n.extend({defaults:r.extend({},n.prototype.defaults,{bundle:[],interval:i,sequence:0}),initialize:function(){var e=this;n.prototype.initialize.apply(e,arguments),e.interval=e.get("interval"),e.queue=[],e.timer=null,e.lastSendTime=0},queueItem:function(e){var t=this,n=Date.now(),r=n-t.lastSendTime;t.queue.push(e),r>t.interval?t._send():t.timer||(t.timer=setTimeout(function(){t._send()},t.interval-r))},_send:function(){var e=this,t=Date.now();e.lastSendTime=t,e.set({bundle:e.queue,sequence:e.get("sequence")+1}),e.queue=[],e.timer&&(clearTimeout(e.timer),e.timer=null)}})}(this),function(root){var Monitor=root.Monitor||require("../Monitor"),_=Monitor._,logger=Monitor.getLogger("InspectProbe"),Backbone=Monitor.Backbone,PollingProbe=Monitor.PollingProbe,DEFAULT_DEPTH=2,InspectProbe=Monitor.InspectProbe=PollingProbe.extend({probeClass:"Inspect",writableAttributes:["value"],initialize:function(e){var t=this;t.key=e.key,typeof e.key=="undefined"&&(t.key=typeof window=="undefined"?"global":"window"),typeof e.depth=="undefined"?!e.key&&t.key==="window"?t.depth=1:t.depth=DEFAULT_DEPTH:t.depth=e.depth,t.value=t._evaluate(t.key),t.isModel=t.value instanceof Backbone.Model,t.set({value:Monitor.deepCopy(t.value,t.depth),isModel:t.isModel}),t.isModel?t.value.on("change",t.poll,t):PollingProbe.prototype.initialize.apply(t,arguments)},set_control:function(e,t){var n=this;if(typeof e.value=="undefined")return t({code:"NO_VALUE"});if(n.isModel)n.value.set(e.value);else{var r=JSON.stringify(e.value);n._evaluate(n.key+" = "+r),n.set("value",e.value)}return t()},release:function(){var e=this;e.isModel?e.value.off("change",e.poll,e):PollingProbe.prototype.release.apply(e,arguments)},eval_control:function(e,t){var n=this;t=typeof t=="undefined"?DEFAULT_DEPTH:t;var r=n._evaluate(e);return Monitor.deepCopy(r,t)},_evaluate:function(expression){var t=this,value=null;try{value=eval(expression)}catch(e){var err='Unable to evaluate expression: "'+expression+'"';throw logger.error("evaluate",err),new Error(err)}return value},poll:function(){var e=this,t=e.eval_control(e.key,e.depth);_.isEqual(t,e.get("value"))||e.set({value:t})}})}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t._,r=t.StreamProbe,i=t.Stat,s="*",o=t.StatProbe=r.extend({probeClass:"Stat",defaults:n.extend({},r.prototype.defaults,{pattern:s}),initialize:function(){var e=this;r.prototype.initialize.apply(e,arguments),e.watcher=function(){var t=n.toArray(arguments);t.splice(0,0,JSON.stringify(new Date).substr(1,24)),e.queueItem.call(e,t)},i.on(e.get("pattern"),e.watcher)},release:function(){var e=this;i.off(e.get("pattern"),e.watcher)}})}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t._,r=t.StreamProbe,i=t.Log,s="*",o=t.LogProbe=r.extend({probeClass:"Log",defaults:n.extend({},r.prototype.defaults,{pattern:s}),initialize:function(){var e=this;r.prototype.initialize.apply(e,arguments),e.watcher=function(){var t=n.toArray(arguments);t.splice(0,0,JSON.stringify(new Date).substr(1,24)),e.queueItem.call(e,t)},i.on(e.get("pattern"),e.watcher)},release:function(){var e=this;i.off(e.get("pattern"),e.watcher)}})}(this);
+/* monitor - v0.6.10 - 2014-05-16 */
+(function(e){var t=typeof exports!="undefined",n=t?require("backbone"):e.Backbone,r=t?require("underscore")._:e._,i=null,s=null,o=[],u=t?require("cron"):null,a=4,f=n.Model.extend({defaults:{id:"",name:"",probeName:"",probeClass:"",initParams:{},hostName:"",appName:"",appInstance:"",probeId:"",writableAttributes:[]},initialize:function(e,t){i.info("init",e)},connect:function(e){var t=this,n=Date.now();f.getRouter().connectMonitor(t,function(r){!r&&t.get("writableAttributes").length>0&&t.on("change",t.onChange,t),e&&e(r),r||(t.trigger("connect",t),t.trigger("change",t),i.info("connected",{initParams:t.get("initParams"),probeId:t.get("probeId")}),s.time("connect",Date.now()-n))})},getConnection:function(){var e=this;return e.probe&&e.probe.connection?e.probe.connection:null},isConnected:function(){var e=this;return e.probe!=null},disconnect:function(e){var t=this,n="manual_disconnect",r=Date.now(),o=t.get("probeId");t.off("change",t.onChange,t),f.getRouter().disconnectMonitor(t,n,function(n,u){e&&e(n),n?i.error("disconnect",{error:n}):(t.trigger("disconnect",u),i.info("disconnected",{reason:u,probeId:o}),s.time("disconnect",Date.now()-r))})},onChange:function(){var e=this,t=e.get("writableAttributes"),n={},s=e.toProbeJSON();delete s.id;for(var o in s){var u=t==="*"||t.indexOf(o)>=0;u&&!r.isEqual(e.attributes[o],e._probeValues[o])&&(n[o]=e.attributes[o])}f._.size(n)&&e.control("set",n,function(t){t&&i.error("probeSet","Problem setting writable value",n,e.toMonitorJSON())})},control:function(e,t,n){var r=this,o=r.probe,u="control."+r.get("probeClass")+"."+e,a=Date.now();typeof t=="function"&&(n=t,t=null),i.info(u,t);var f=function(e,t){e?i.error(u,e):(i.info("return."+u,t),s.time(u,Date.now()-a)),n&&n.apply(r,arguments)};if(!o)return f("Probe not connected");o.connection?o.connection.emit("probe:control",{probeId:r.get("probeId"),name:e,params:t},f):o.onControl(e,t,f)},toProbeJSON:function(e){var t=this,n={id:t.get("probeId")};return r.each(t.toJSON(e),function(e,r){r in t.defaults||(n[r]=e)}),n},toMonitorJSON:function(e){var t=this,n={};return r.each(t.toJSON(e),function(e,r){r in t.defaults&&(n[r]=e)}),n},toServerString:function(){return f.toServerString(this.toMonitorJSON())}});f.generateUniqueId=function(){function e(){return((1+Math.random())*65536|0).toString(16).substring(1)}return s.increment("generateUniqueId"),e()+e()+"-"+e()+"-"+e()+"-"+e()+"-"+e()+e()+e()},f.generateUniqueCollectionId=function(e,t){var n="";return t=t||"",e.idSequence||(e.idSequence=0,e.forEach(function(n){var r=n.get("id")||"",i=+r.substr(t.length);e.idSequence<=i&&(e.idSequence=i+1)})),t+e.idSequence++},f.getRouter=function(){return f.defaultRouter||(f.defaultRouter=new f.Router,e.io&&f.defaultRouter.setGateway({socket:e.io.connect()})),f.defaultRouter},f.start=function(e,t){return i.info("start",e),t=t||function(){},f.defaultServer?t():(f.defaultServer=new f.Server,f.defaultServer.start(e,t)),f},f.stop=function(e){i.info("stop"),e=e||function(){},f.defaultServer?(f.defaultServer.stop(e),delete f.defaultServer):e()},f.toServerString=function(e){var t=e.hostName;return e.appName&&(t+=":"+e.appName,e.appInstance&&(t+=":"+e.appInstance)),t},f.deepCopy=function(e,t){t=typeof t=="undefined"?a:t;if(typeof e!="object"&&typeof e!="function")return e;var n="[Object]";typeof e=="function"?n="[Function]":Array.isArray(e)&&(n="[Array]");if(t<=0)return n;var i=Array.isArray(e)?[]:{};for(var s in e)if(!e.hasOwnProperty||e.hasOwnProperty(s)){var o=e[s];typeof o=="object"||typeof o=="function"?i[s]=f.deepCopy(o,t-1):i[s]=o}return typeof e=="function"&&(r.isEmpty(i)?i=n:i=r.extend({constructor:n},i)),i},f.stringify=function(e,t,n){return n=typeof n=="undefined"?2:n,JSON.stringify(f.deepCopy(e,t),null,n)},f.setStatLoggerClass=function(e){f.getStatLogger=function(t){return new e(t)},s=f.getStatLogger("Monitor")},f.setLoggerClass=function(e){f.getLogger=function(t){return new e(t)},i=f.getLogger("Monitor")},f.List=n.Collection.extend({model:f});var l={appName:"unknown",serviceBasePort:42e3,portsToScan:20,allowExternalConnections:!1,consoleLogListener:{pattern:"{trace,warn,error,fatal}.*"},autoStart:[]};t?(f.Config=require("config"),f.Config.setModuleDefaults("Monitor",l)):f.Config={Monitor:l},f._=r,f.Backbone=n,f.Cron=u,f.commonJS=t,t?module.exports=f:e.Monitor=f;var c=f.Config.Monitor.autoStart;f._.size(c)&&setTimeout(function(){f._.each(c,function(e){var t=new f(e);t.connect(function(n){n&&i.error("autoStart","Error auto-starting monitor",e,n),o.push(t)})})},0)})(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.commonJS?require("events").EventEmitter.prototype:t.Backbone.Events,r=t._,i=!1,s=t.Stat=function(e){var t=this;t.module=e},o=s.prototype;s.eventRegex={},o.increment=function(e,t){t=r.isNumber(t)?t:1,s._emit(this.module,e,t,"c")},o.decrement=function(e,t){t=r.isNumber(t)?t:1,s._emit(this.module,e,t*-1,"c")},o.gauge=function(e,t){s._emit(this.module,e,t,"g")},o.time=function(e,t){s._emit(this.module,e,t,"ms")},s._emit=function(e,t,n,r){var o,u;if(i)return;i=!0;for(o in s._events){u||(u=e+"."+t);var a=s.eventRegex[o];a||(a=s.eventRegex[o]=s._buildRegex(o)),a.test(u)&&s.emit(o,e,t,n,r)}i=!1},s._buildRegex=function(e){var t="",n="",r=e.length-1,i=!1;if(/^\/[^\/]*\/i*$/.test(e))/i$/.test(e)&&(n="i",e=e.replace(/i$/,"")),t="^"+e.replace(/^\//,"").replace(/\/$/,"")+"$";else{for(var s=0,o=e.length;s<o;s++){var u=e.substr(s,1);switch(u){case".":u="\\.";break;case"*":u=s===r?".*":"[^\\.]*";break;case"{":u="(",i=!0;break;case"}":u=")",i=!1;break;case",":i&&(u="|")}t+=u}t="^"+t+"$"}return new RegExp(t,n)},r.extend(s,n),t.setStatLoggerClass(s)}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.commonJS?require("events").EventEmitter.prototype:t.Backbone.Events,r=t.Stat,i=new r("Log"),s=t._,o=!1,u=t.Log=function(e){var t=this;t.module=e},a=u.prototype;u.eventRegex={},["trace","debug","info","warn","error","fatal"].forEach(function(e){a[e]=function(t){u._emit(e,this.module,t,arguments)}}),u._emit=function(e,t,n,a){var f,l=e+"."+t+"."+n;if(o)return;o=!0,i.increment(l);for(f in u._events){var c=u.eventRegex[f];c||(c=u.eventRegex[f]=r._buildRegex(f));if(c.test(l)){var h=s.toArray(a),p=u.emit||u.trigger;h.splice(0,1,f,e,t,n),p.apply(u,h)}}o=!1},s.extend(u,n),t.setLoggerClass(u),u.console=function(e,n,r){var i=(new Date).toJSON(),o=s.toArray(arguments),u="["+i+"] ["+e.toUpperCase()+"] "+n;o.splice(0,3),o.length===0?o=[r]:u+="."+r,u+=" - ";if(o.length===1&&typeof o[0]=="string")u+=o[0];else try{u+=JSON.stringify(o)}catch(a){u+=t.stringify(o)}e==="error"||e==="fatal"?console.error(u):console.log(u)};var f=t.Config.Monitor.consoleLogListener.pattern;f&&u.on(f,u.console)}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.getLogger("Probe"),r=t.getStatLogger("Probe"),i=t.Cron,s=t._,o=t.Backbone,u=t.Probe=o.Model.extend({defaults:{id:null},initialize:function(e,t){var r=this;n.info("init",r.toJSON(),t)},release:function(){var e=this;n.info("release",e.toJSON())},onControl:function(e,t,i){var s=this,o=s[e+"_control"],u=Date.now(),a,f="onControl."+s.probeClass+"."+e;t=t||{},i=i||function(){},n.info(f,s.get("id"),t);if(!o)return a="No control function: "+e,n.error(f,a),i({msg:a});var l=function(e){if(e)return n.error(f+".whenDone",e),i(e);var o=Date.now()-u;n.info(f,t),r.time(s.logId,o),i.apply(null,arguments)};setTimeout(function(){try{o.call(s,t,l)}catch(n){a="Error calling control: "+s.probeClass+":"+e,l({msg:a,err:n.toString()})}},0)},set_control:function(e,t){var r=this,i=r.get("writableAttributes")||[];if(i!=="*")for(var s in e)if(i.indexOf(s)<0)return t({code:"NOT_WRITABLE",msg:"Attribute not writable: "+s});var o=null;return r.set(e)||(o={code:"VALIDATION_ERROR",msg:"Data set failed validation"},n.warn("set_control",o)),t(o)},ping_control:function(e,t){return t(null,"pong")}});u.classes={},u.extend=function(e){var t=this,n=o.Model.extend.apply(t,arguments);return e.probeClass&&(u.classes[e.probeClass]=n),n},u.List=o.Collection.extend({model:u})}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.Cron,r=t._,i=t.Backbone,s=t.getLogger("Connection"),o=t.getStatLogger("Connection"),u=t.Config,a=e.io||require("socket.io-client"),f=t.Probe,l=1,c=t.Connection=i.Model.extend({defaults:{hostName:"",hostPort:null,url:null,socket:null,gateway:!1,firewall:!1,remoteHostName:null,remoteAppName:null,remoteAppInstance:0,remotePID:0,remoteProbeClasses:[],remoteGateway:!1,remoteFirewall:!1},initialize:function(e){var t=this;t.connecting=!0,t.connected=!1,t.socketEvents=null,t.remoteProbeIdsByKey={},t.remoteProbesById={},t.incomingMonitorsById={},t.logId=l++ +".",e.socket?(t.bindConnectionEvents(),s.info(t.logId+"connect",{socketId:e.socket.id})):e.url||e.hostName&&e.hostPort?(t.connect(),s.info(t.logId+"connect",{url:t.get("url")})):s.error("init","Connection must supply a socket, url, or host name/port")},connect:function(){var e=this,t=e.get("hostName"),n=e.get("hostPort"),r=e.get("url");r||(r=e.attributes.url="http://"+t+":"+n,e.set("url",r));var i={"force new connection":!0,reconnect:!1},s=a.connect(r,i);e.set({socket:s}).bindConnectionEvents()},ping:function(e){var t=this;e=e||function(){};var n=function(){t.off("pong",n),e()};t.on("pong",n),t.emit("connection:ping")},disconnect:function(e){var t=this,n=t.get("socket");t.connecting=!1,t.connected=!1,t.socketEvents&&(t.removeAllEvents(),n.disconnect(),t.trigger("disconnect",e),s.info(t.logId+"disconnect",e))},isThisHost:function(e){var t=this,n=e.toLowerCase(),r=t.get("hostName"),i=t.get("remoteHostName");return r=r&&r.toLowerCase(),i=i&&i.toLowerCase(),n===r||n===i},emit:function(){var e=this,n=e.get("socket");s.info(e.logId+"emit",t.deepCopy(arguments,5)),n.emit.apply(n,arguments)},addEvent:function(e,t){var n=this,r=n.get("socket");n.socketEvents=n.socketEvents||{};if(n.socketEvents[e])throw new Error("Event already connected: "+e);return r.on(e,t),n.socketEvents[e]=t,n},removeEvent:function(e){var t=this,n=t.get("socket");return t.socketEvents&&t.socketEvents[e]&&(n.removeListener(e,t.socketEvents[e]),delete t.socketEvents[e]),t},removeAllEvents:function(){var e=this,t=e.get("socket");for(var n in e.socketEvents)t.removeListener(n,e.socketEvents[n]);return e.socketEvents=null,e},bindConnectionEvents:function(){var e=this,n=e.get("socket");if(e.socketEvents)throw new Error("Already connected");e.socketEvents={},e.addEvent("connect_failed",function(){e.trigger("error","connect failed"),e.disconnect("connect failed")}),e.addEvent("disconnect",function(){e.disconnect("remote_disconnect")}),e.addEvent("error",function(t){e.trigger("error",t),e.disconnect("connect error")}),e.addEvent("probe:connect",e.probeConnect.bind(e)),e.addEvent("probe:disconnect",e.probeDisconnect.bind(e)),e.addEvent("probe:control",e.probeControl.bind(e)),e.addEvent("connection:ping",function(){n.emit("connection:pong")}),e.addEvent("connection:pong",function(){e.trigger("pong")}),e.addEvent("connection:info",function(t){e.set({remoteHostName:t.hostName,remoteAppName:t.appName,remoteAppInstance:t.appInstance,remotePID:t.pid,remoteProbeClasses:t.probeClasses,remoteGateway:t.gateway,remoteFirewall:t.firewall}),e.connecting=!1,e.connected=!0,e.trigger("connect")});var i=typeof process=="undefined"?1:process.pid,s=""+(typeof process=="undefined"?i:process.env.NODE_APP_INSTANCE||i);n.emit("connection:info",{hostName:t.getRouter().getHostName(),appName:u.Monitor.appName,appInstance:s,pid:i,probeClasses:r.keys(f.classes),gateway:e.get("gateway"),firewall:e.get("firewall")})},probeConnect:function(e,n){n=n||function(){};var i=this,u="",a=t.getRouter(),f=i.get("gateway"),l=Date.now(),c=i.get("firewall"),h=r.extend({},e);if(c)return u="firewalled",s.error("probeConnect",u,h),n(u);a.determineConnection(e,f,function(r,u){if(r)return n(r);if(u&&!f)return n("Not a gateway");var c=function(r,u){if(r)return s.error(i.logId+"probeConnect",r,h),n(r);var a=u.get("id");h.id=a;var f=i.incomingMonitorsById[a];if(f!=null)return u.refCount--,h.dupDetected=!0,h.refCount=u.refCount,s.info(i.logId+"probeConnected",h),n(null,f.probe.toJSON());f=new t(e),f.set("probeId",a),i.incomingMonitorsById[a]=f,f.probe=u,f.probeChange=function(){try{i.emit("probe:change:"+a,u.changedAttributes())}catch(e){s.error("probeChange",e,u,h)}},u.connectTime=Date.now();var c=u.connectTime-l;h.duration=c,h.refCount=u.refCount,s.info(i.logId+"probeConnected",h),o.time(i.logId+"probeConnected",c),n(null,u.toJSON()),u.on("change",f.probeChange),i.on("disconnect",function(){i.probeDisconnect({probeId:a})})};u?a.connectExternal(e,u,c):a.connectInternal(e,c)})},probeDisconnect:function(e,n){n=n||function(){};var r=this,i="",u=t.getRouter(),a=e.probeId,f=r.incomingMonitorsById[a],l=r.get("firewall"),c=null,h=null;if(!f||!f.probe)return n(null);h=f.probe,c={probeClass:f.get("probeClass"),initParams:f.get("initParams"),probeId:a};var p=function(e){if(e)return s.error(r.logId+"probeDisconnect",e),n(e);var t=c.duration=Date.now()-h.connectTime;return h.off("change",f.probeChange),f.probe=f.probeChange=null,delete r.incomingMonitorsById[a],s.info(r.logId+"probeDisconnected",c),o.time(r.logId+"probeDisconnected",t),n(null)};h&&h.connection?u.disconnectExternal(h.connection,a,p):u.disconnectInternal(a,p)},probeControl:function(e,n){n=n||function(){};var r=this,i="",u=r.logId+"probeControl",a=Date.now(),f=t.getRouter(),l=r.get("firewall");if(l)return i="firewalled",s.error(u,i),n(i);var c=function(e){if(e)return s.error(u,e),n(e);var t=Date.now()-a;return s.info(u+".return",{duration:t,returnArgs:arguments}),o.time(u,t),n.apply(null,arguments)},h=f.runningProbesById[e.probeId];if(!h){var p=r.incomingMonitorsById[e.probeId];return p?p.control(e.name,e.params,function(e,t){c(e,t)}):(i="Probe id not found: "+e.probeId,s.error(i),n(i))}return u=u+"."+h.probeClass+"."+e.name,s.info(u+".request",{params:e.params,probeId:e.probeId}),h.onControl(e.name,e.params,c)}});c.List=i.Collection.extend({model:c})}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.Config,r=t._,i=t.Backbone,s=t.getLogger("Server"),o=t.getStatLogger("Server"),u=t.Connection,a=t.commonJS?require("http"):null,f=e.io||require("socket.io"),l=t.Server=i.Model.extend({initialize:function(e){var t=this;t.isListening=!1,t.connections=new u.List},start:function(e,t){typeof e=="function"&&(t=e,e=null),e=e||{},t=t||function(){};var r=this,i=r.get("server"),o,u=Date.now(),f=e.port||n.Monitor.serviceBasePort,l=e.attempt||1,c=n.Monitor.allowExternalConnections;if(l>n.Monitor.portsToScan)return o={err:"connect:failure",msg:"no ports available"},s.error("start",o),t(o);if(i)r.bindEvents(t);else{i=a.createServer(),i.on("error",function(e){if(e.code==="EADDRINUSE")return r.get("port")?(s.error("portInUse",{host:h,port:f}),t({err:"portInUse"})):(s.info("portInUse",{host:h,port:f}),r.start({port:f+1,attempt:l+1},t));t(e)});var h=c?"0.0.0.0":"127.0.0.1";i.listen(f,h,function(){process.env.NODE_APP_INSTANCE||(process.env.NODE_APP_INSTANCE=""+(f-n.Monitor.serviceBasePort+1)),r.set({server:i,port:f}),r.bindEvents(t),s.info("listening",{appName:n.Monitor.appName,NODE_APP_INSTANCE:process.env.NODE_APP_INSTANCE,listeningOn:h,port:f})})}},bindEvents:function(e){var n=this,r=n.get("server");r.on("clientError",function(e){s.error("bindEvents","clientError detected on server",e),n.trigger("error",e)}),r.on("close",function(e){r.hasEmittedClose=!0,s.info("bindEvents.serverClose","Server has closed",e),n.stop()});var i={log:!1};n.socketServer=f.listen(r,i),n.socketServer.sockets.on("connection",function(e){var r=t.getRouter().addConnection({socket:e,gateway:n.get("gateway")});n.connections.add(r);var i=function(e){n.connections.remove(r),t.getRouter().removeConnection(r),r.off("disconnect",i),s.info("client.disconnect","Disconnected client socket")};r.on("disconnect",i),s.info("client.connect","Connected client socket")}),n.isListening=!0,e&&e(null),n.trigger("start")},stop:function(e){var n=this,r=n.get("server"),i=t.getRouter();return e=e||function(){},n.isListening?(n.connections.each(i.removeConnection,i),n.connections.reset(),n.isListening=!1,r.close(),n.trigger("stop"),e()):e()}});l.List=i.Collection.extend({model:l})}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.getLogger("Router"),r=t.getStatLogger("Router"),i=t.Cron,s=t._,o=t.Backbone,u=t.Config,a=t.Probe,f=t.Connection,l=t.Server,c=e.io||require("socket.io"),h=t.commonJS?require("os").hostname():null,p=1e4,d=t.Router=o.Model.extend({initialize:function(){var e=this;e.defaultGateway=null,e.firewall=!1,e.connections=new f.List,e.runningProbesByKey={},e.runningProbesById={},e.addHostCallbacks={},n.info("init","Router initialized")},setFirewall:function(e){var r=t.getRouter();r.firewall=e,n.info("setFirewall",e)},setGateway:function(e){var t=this;return e.gateway=!1,e.firewall=!0,t.defaultGateway=t.addConnection(e)},getHostName:function(){var n=e.localStorage;return h||(n&&(h=n.hostName),h=h||t.generateUniqueId(),n&&(n.hostName=h)),h},setHostName:function(e){h=e,n.info("setHostName",e)},addConnection:function(e){var r=this,i=Date.now();s.isUndefined(e.firewall)&&(e=s.extend({},e,{firewall:r.firewall})),e.id=t.generateUniqueCollectionId(r.connections);var o="Conn_"+e.id;e.hostName&&(o+=" - "+e.hostName+":"+e.hostPort),n.info("addConnection",o);var u=new f(e),a=function(){r.trigger("connection:add",u),n.info("connected",o,Date.now()-i+"ms")},l=function(){r.removeConnection(u),u.off("connect",a),u.off("disconnect",a),n.info("disconnected",o,Date.now()-i+"ms")};return u.on("connect",a),u.on("disconnect",l),r.connections.add(u),u},removeConnection:function(e){var t=this;n.info("removeConnection","Conn_"+e.id),e.disconnect("connection_removed"),t.connections.remove(e),t.trigger("connection:remove",e)},connectMonitor:function(e,t){t=t||function(){};var r=this,i=e.toMonitorJSON(),o=null,u=i.probeName,a=i.probeClass,f=Date.now(),l=a+"."+e.toServerString().replace(/:/g,".");if(!a&&!u){var c="probeName or probeClass must be set";return n.error("connectMonitor",c),t(c)}r.determineConnection(i,!0,function(u,a){if(u)return t(u);var f=function(r,i){if(r)return t(r);o=i.toJSON(),o.probeId=o.id,delete o.id,e.probe=i,e._probeValues=s.clone(o),e.set(o,{silent:!0}),e.probeChange=function(){var t=i.changedAttributes();t&&(e._probeValues=s.clone(i.toJSON()),e.set(i.changedAttributes()),n.info("probeChange",{probeId:o.probeId,changed:i.changedAttributes()}))},i.on("change",e.probeChange),t(null)};a?r.connectExternal(i,a,f):r.connectInternal(i,f)})},disconnectMonitor:function(e,t,n){n=n||function(){};var r=this,i=e.probe,s=e.get("probeId");if(!i)return n("Monitor must be connected");var o=function(r){return r?n(r):(i.off("change",e.probeChange),e.set({probeId:null}),e.probe=e.probeChange=null,n(null,t))};i.connection?r.disconnectExternal(i.connection,s,o):r.disconnectInternal(s,o)},buildProbeKey:function(e){var t=e.probeClass,n=e.initParams;return e.probeName?e.probeName:(n&&s.keys(n).sort().forEach(function(e){t+=":"+e+"="+n[e]}),t)},determineConnection:function(e,r,i){var s=this,o=null,f=e.probeName,l=e.probeClass,c="",h=e.hostName,p=e.appName,d=e.appInstance,v=s.getHostName().toLowerCase(),m=u.Monitor.appName||"unknown",g=typeof process!="undefined"?process.env.NODE_APP_INSTANCE:"1",y=function(t){t||(delete e.hostName,delete e.appName,delete e.appInstance);var r=function(){u(),i(null,o)},s=function(e){u(),n.error("connect.error",e),i({msg:"connection error",err:e})},u=function(){o.off("connect",r),o.off("error",s)};if(o&&o.connecting){o.on("connect",r),o.on("error",s);return}return o&&!o.connected?(o.on("connect",r),o.on("error",s),o.connect()):i(null,o)};h=h?h.toLowerCase():null;var b=!h||h===v,w=!p||p===m,E=!d||d===g;if(b&&w&&E){if(s.runningProbesByKey[f]||a.classes[l]!=null)return i(null,null);var S=t.Config.Monitor.autoStart;if(f&&!l&&S.length){var x=t._.find(S,function(e){return e.probeName===f});if(x){setTimeout(function(){s.determineConnection(e,r,i)},10);return}}return s.defaultGateway?(o=s.defaultGateway,y(!0)):(c='Probe class "'+l+'" not available in this process',n.error("connect.internal",c),i({err:c}))}o=s.findConnection(h,p,d);if(o)return y();if(s.defaultGateway)return o=s.defaultGateway,y(!0);if(h&&r){s.addHostConnections(h,function(r){return r?(n.error("connect.toHost",r),i(r)):(o=s.findConnection(h,p,d),o?y():(c="No route to host: "+t.toServerString(e),n.error("connect.toHost",c),i({err:c})))});return}return h?(c="Not a gateway to remote monitors",n.error("connect",c),i({msg:c})):(c="No host specified for app: "+p,n.error("connect",c),i({msg:c},null))},findConnection:function(e,t,n){var r=this,i=0;return r.connections.find(function(r){var i=!e||r.isThisHost(e),s=!t||t===r.get("remoteAppName"),o=!n||n===r.get("remoteAppInstance"),u=r.get("remoteFirewall");return!u&&i&&s&&o})},findConnections:function(e,t){var n=this;return n.connections.filter(function(n){var r=!e||n.isThisHost(e),i=!t||t===n.get("remoteAppName"),s=n.get("remoteFirewall");return!s&&r&&i})},addHostConnections:function(e,t){var r=this,i="",s=[],o=u.Monitor.serviceBasePort,a=u.Monitor.serviceBasePort+u.Monitor.portsToScan-1;r.addHostCallbacks[e]||(r.addHostCallbacks[e]=[]);if(r.addHostCallbacks[e].push(t)>1)return;var f=function(t){r.addHostCallbacks[e].forEach(function(e){e(t)}),delete r.addHostCallbacks[e]};r.connections.each(function(t){var n=t.get("hostName").toLowerCase(),r=t.get("hostPort");n===e&&r>=o&&r<=a&&s.push(r)});var l=u.Monitor.portsToScan-s.length;if(l===0)return i="All monitor ports in use. Increase the Config.Monitor.portsToScan configuration",n.error("addHostConnections",i),f(i);var c=function(){var e=this;e.off("connect disconnect error",c);if(--l===0)return f()};for(var h=o;h<=a;h++)if(s.indexOf(h)<0){var p=r.addConnection({hostName:e,hostPort:h});p.on("connect disconnect error",c,p)}},connectInternal:function(e,r){var i=this,s=i.buildProbeKey(e),o=e.probeName,u=e.probeClass,f=e.initParams,l=null,c=function(e){setTimeout(function(){if(e){if(l){delete i.runningProbesByKey[s],delete i.runningProbesById[l.id];try{l.release()}catch(t){}}return r(e)}l.refCount++,n.info("connectInternal",{probeKey:s,probeId:l.id}),r(null,l)},0)};l=i.runningProbesByKey[s];if(!l){var h=a.classes[u];if(!h)return c({msg:"Probe not available: "+u});var p={asyncInit:!1,callback:c};try{var d=t.deepCopy(f);o&&(d.probeName=o),l=new h(d,p),l.set({id:t.generateUniqueId(),writableAttributes:h.prototype.writableAttributes||[]}),l.refCount=0,l.probeKey=s,i.runningProbesByKey[s]=l,i.runningProbesById[l.id]=l}catch(v){var m={msg:"Error instantiating probe "+u,error:v.message};return c(m)}if(p.asyncInit)return}c()},disconnectInternal:function(e,t){var n=this,r=n.runningProbesById[e];if(!r)return t("Probe not running");--r.refCount===0&&setTimeout(function(){if(r.refCount===0){try{r.release()}catch(t){}delete n.runningProbesByKey[r.probeKey],delete n.runningProbesById[e]}},p),t(null,r)},connectExternal:function(e,r,i){var s=this,o="",u=s.buildProbeKey(e),f=r.remoteProbeIdsByKey[u],l=r.remoteProbesById[f];if(!l){r.emit("probe:connect",e,function(s,c){return s?(o="probe:connect returned an error for probeClass '"+e.probeClass+"' on "+t.toServerString(e),i({err:s,msg:o})):(f=c.id,l=r.remoteProbesById[f],l?(l.refCount++,n.info("connectExternal.connected.existingProxy",{probeId:f,refCount:l.refCount,whileWaiting:!0}),i(null,l)):(l=new a(c),l.refCount=1,l.connection=r,r.remoteProbeIdsByKey[u]=f,r.remoteProbesById[f]=l,r.addEvent("probe:change:"+f,function(e){l.set(e)}),n.info("connectExternal.connected.newProxy",{probeId:f}),i(null,l)))});return}return l.refCount++,n.info("connectExternal.connected.existingProxy",{probeId:f,refCount:l.refCount}),i(null,l)},disconnectExternal:function(e,t,n){var r=this,i=e.remoteProbesById[t];if(!i)return n("Probe not running");if(--i.refCount===0)return i.release(),i.connection=null,delete e.remoteProbesById[t],delete e.remoteProbeIdsByKey[i.probeKey],e.removeEvent("probe:change:"+t),e.emit("probe:disconnect",{probeId:t},function(e){return n(e)});n(null)}})}(this),function(e){var t=e.Monitor||require("./Monitor"),n=t.getLogger("Sync"),r=t.Backbone,i=t._,s="create",o="read",u="update",a="delete";t.Sync=function(e,t){if(!e)throw new Error("Sync class name must be provided");var r=new f(e,t);return function(t,i,s){return n.info("sync",{className:e,method:t,model:i.toJSON(),options:s}),r._sync(t,i,s)}};var f=function(e,t){var r=this;n.info("syncInit",e,t),r.className=e,r.options=t||{}};f.prototype._sync=function(e,i,u){var a=this;u=u||{};if(u.liveSync&&i instanceof r.Collection)return u.error(null,"Cannot liveSync with a collection");if(!i.has("id")){if(e!==s)return u.error(null,"ID element must be set.");i.set({id:t.generateUniqueId()},{silent:!0}),n.info("_sync.generateUniqueId",a.className,i.toJSON(),u)}if(e===s&&u.liveSync){a._sync(e,i,{error:u.error,success:function(e){a._sync(o,i,u)}});return}var f=function(e,t){e?(u.silenceErrors||n.error("_sync.onComplete",a.className,e),u.error(null,e)):(n.info("_sync.onComplete",a.className,i.get("id")),u.success(t))};if(i.syncMonitor||a.syncMonitor&&!u.liveSync){var l=i.syncMonitor||a.syncMonitor,c=a._getOpts(e,i);l.control(e,c,f)}else u.liveSync?a._connectInstanceMonitor(e,i,u,f):a._connectClassMonitor(e,i,u,f)},f.prototype._connectClassMonitor=function(e,r,i,s){var o=this;n.info("connectClassMonitor",o.className,e,r.toJSON());var u=o._getMonitorParams(null),a=new t(u);a.connect(function(t){if(t)return i.silenceErrors||n.error("connectClassMonitor",t),s(t);o.syncMonitor=a;var u=o._getOpts(e,r);a.control(e,u,s)})},f.prototype._connectInstanceMonitor=function(e,r,s,u){var a=this,f,l=r.get("id"),c=function(e){if(e)return u(e);var t=function(){n.info("disconnectLiveSync",a.className,r.toJSON()),r.off("change",s),r.syncMonitor.off("change",o),r.syncMonitor.disconnect(),r.syncMonitor=null},s=function(e,s){s=s||{};if(i.isEqual(JSON.parse(JSON.stringify(r)),JSON.parse(JSON.stringify(r.syncMonitor.get("model"))))){n.info("modelListener.noChanges",a.className,r.toJSON());return}if(r.get("id")!==l)return n.info("modelListener.alteredId",a.className,r.toJSON()),t();s.isSyncChanging||(n.info("modelListener.saving",a.className,r.toJSON()),r.save())},o=function(e,s){var o=r.syncMonitor.get("model");if(i.isEqual(JSON.parse(JSON.stringify(r)),JSON.parse(JSON.stringify(o)))){n.info("monitorListener.noChanges",a.className,o);return}var u=i.size(o)===0;if(u||o.id!==l)n.info("modelListener.deleted",a.className,o),t();var f={isSyncChanging:!0};u?(n.info("modelListener.deleting",a.className,o),r.clear(f)):(n.info("modelListener.setting",a.className,o),r.clear({silent:!0}),r.set(o,f))};r.on("change",s),r.syncMonitor.on("change",o),n.info("connectInstanceMonitor.done",a.className,r.toJSON()),u(null,r.syncMonitor.get("model"))},h=a._getMonitorParams(l);f=new t(h),f.connect(function(t){if(t)return s.silenceErrors||n.error("connectInstanceMonitor.monitorConnect",t),c(t);r.syncMonitor=f;if(e===o)return c();var i=a._getOpts(e,r);n.info("connectInstanceMonitor.forwarding",e,a.className,r.toJSON()),f.control(e,i,c)})},f.prototype._getOpts=function(e,t){var n={};switch(e){case o:case a:n.id=t.get("id");break;case s:case u:n.model=t.toJSON()}return n},f.prototype._getMonitorParams=function(e){var t=this,n=i.pick(t.options,"hostName","appName","appInstance");return n.probeClass="Sync",n.initParams={className:t.className},e&&(n.initParams.modelId=e),n}}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t.DataModelProbe=t.Probe.extend({probeClass:"DataModel",writableAttributes:"*"})}(this),function(root){var Monitor=root.Monitor||require("../Monitor"),_=Monitor._,Cron=Monitor.Cron,logger=Monitor.getLogger("RecipeProbe"),vm=Monitor.commonJS?require("vm"):null,Probe=Monitor.Probe,RecipeProbe=Monitor.RecipeProbe=Probe.extend({probeClass:"Recipe",writableAttributes:[],defaults:{recipeName:"",monitors:{},script:"",autoStart:!1,started:!1,triggeredBy:null},initialize:function(e,t){var n=this;n.interval=null,n.cronJob=null;if(_.size(n.get("monitors"))===0){logger.error("initialize","No monitors defined in the recipe");return}n.monitors={},n.get("autoStart")&&(t.asyncInit=!0,n.start_control({},t.callback))},release:function(){var e=this,t=arguments;e.stop_control({},function(){Probe.prototype.release.apply(e,t)})},start_control:function(e,t){var n=this,r=!1,i=n.get("monitors");if(n.get("started")){var s={code:"RUNNING",msg:"Cannot start - the recipe is already running."};return logger.warn(s),t(s)}var o=function(e){if(r)return;if(e){var i={code:"CONNECT_ERROR",err:e};return r=!0,logger.error("start",i),t(i)}for(var s in n.monitors)if(!n.monitors[s].isConnected())return;n.set({started:!0}),n.connectListeners(!0),t()};for(var u in i)n.monitors[u]=new Monitor(i[u]),n.monitors[u].connect(o)},stop_control:function(e,t){var n=this,r=!1;if(!n.get("started")){var i={code:"NOT_RUNNING",msg:"The recipe is already stopped."};return logger.warn("precondition",i),t(i)}var s=function(e){if(r)return;if(e){var i={code:"DISONNECT_ERROR",err:e};return r=!0,logger.error("onDisconnect",i),t(i)}for(var s in n.monitors)if(n.monitors[s].isConnected())return;n.set({started:!1}),n.compiledScript=null,t()};n.connectListeners(!1),n.context=null;for(var o in n.monitors)n.monitors[o].disconnect(s)},connectListeners:function(e){var t=this,n=t.get("triggeredBy"),r=t.onTrigger.bind(t);if(!n){for(var i in t.monitors)t.monitors[i][e?"on":"off"]("change",t.onTrigger,t);return}for(var s in n){var o=n[s];s==="cron"?e?t.cronJob=new Cron.CronJob(o,r):t.cronJob.initiated?clearInterval(t.CronJob.timer):setTimeout(function(){clearInterval(t.cronJob.timer)},1e3):s==="interval"?e?t.interval=setInterval(r,o):(clearInterval(t.interval),t.interval=null):t.monitors[s][e?"on":"off"](o,r)}},onTrigger:function(){var e=this;e.run_control({},function(e){e&&logger.error("onTrigger",e)})},run_control:function(e,t){var n=this,r=null;if(!n.get("started"))return r={code:"NOT_RUNNING",msg:"Cannot run - recipe not started."},logger.warn(r),t(r);n.name=n.get("probeName")||n.get("id");if(!n.context){n.context=vm?vm.createContext({}):{},n.context.console=console,n.context.logger=Monitor.getLogger("Recipe.run."+n.name);for(var i in n.monitors)n.context[i]=n.monitors[i]}try{n.run(n.context)}catch(s){r="Error running script: "+s.toString(),logger.error("run_control",r)}t(r)},run:function(context){var t=this,script=t.get("script");vm?(t.compiledScript||(t.compiledScript=vm.createScript(script)),t.compiledScript.runInContext(context,t.name)):(eval(t.bringLocal(context)),eval(script))},bringLocal:function(e){var t,n=[];for(t in e)n.push("var "+t+" = context."+t+";");return n.join("\n")}})}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t._,r=t.Cron,i=t.Probe,s=t.Backbone,o=1e3,u="* * * * * *",a=t.PollingProbe=i.extend({defaults:n.extend({},i.prototype.defaults,{pollInterval:null,cronPattern:u}),initialize:function(){var e=this,t=e.get("pollInterval"),n=e.get("cronPattern"),s=function(){e.poll()};i.prototype.initialize.apply(e,arguments),t==null&&n===u&&(t=o),e.poll();if(t!==0)if(t)e.timer=setInterval(s,t);else{if(!r)throw new Error("Cron is not available in this client");e.cronJob=new r.CronJob(n,s)}},release:function(){var e=this,t=e.cronJob?e.cronJob.timer:e.timer;e.cronJob&&!e.cronJob.initiated?setTimeout(function(){clearInterval(e.cronJob.timer)},1e3):e.timer&&clearInterval(t),e.timer=e.cron=null,i.prototype.release.apply(e,arguments)}})}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t.Probe,r=t._,i=1e3,s=t.StreamProbe=n.extend({defaults:r.extend({},n.prototype.defaults,{bundle:[],interval:i,sequence:0}),initialize:function(){var e=this;n.prototype.initialize.apply(e,arguments),e.interval=e.get("interval"),e.queue=[],e.timer=null,e.lastSendTime=0},queueItem:function(e){var t=this,n=Date.now(),r=n-t.lastSendTime;t.queue.push(e),r>t.interval?t._send():t.timer||(t.timer=setTimeout(function(){t._send()},t.interval-r))},_send:function(){var e=this,t=Date.now();e.lastSendTime=t,e.set({bundle:e.queue,sequence:e.get("sequence")+1}),e.queue=[],e.timer&&(clearTimeout(e.timer),e.timer=null)}})}(this),function(root){var Monitor=root.Monitor||require("../Monitor"),_=Monitor._,logger=Monitor.getLogger("InspectProbe"),Backbone=Monitor.Backbone,PollingProbe=Monitor.PollingProbe,DEFAULT_DEPTH=2,InspectProbe=Monitor.InspectProbe=PollingProbe.extend({probeClass:"Inspect",writableAttributes:["value"],initialize:function(e){var t=this;t.key=e.key,typeof e.key=="undefined"&&(t.key=typeof window=="undefined"?"global":"window"),typeof e.depth=="undefined"?!e.key&&t.key==="window"?t.depth=1:t.depth=DEFAULT_DEPTH:t.depth=e.depth,t.value=t._evaluate(t.key),t.isModel=t.value instanceof Backbone.Model,t.set({value:Monitor.deepCopy(t.value,t.depth),isModel:t.isModel}),t.isModel?t.value.on("change",t.poll,t):PollingProbe.prototype.initialize.apply(t,arguments)},set_control:function(e,t){var n=this;if(typeof e.value=="undefined")return t({code:"NO_VALUE"});if(n.isModel)n.value.set(e.value);else{var r=JSON.stringify(e.value);n._evaluate(n.key+" = "+r),n.set("value",e.value)}return t()},release:function(){var e=this;e.isModel?e.value.off("change",e.poll,e):PollingProbe.prototype.release.apply(e,arguments)},eval_control:function(e,t){var n=this;t=typeof t=="undefined"?DEFAULT_DEPTH:t;var r=n._evaluate(e);return Monitor.deepCopy(r,t)},_evaluate:function(expression){var t=this,value=null;try{value=eval(expression)}catch(e){var err='Unable to evaluate expression: "'+expression+'"';throw logger.error("evaluate",err),new Error(err)}return value},poll:function(){var e=this,t=e.eval_control(e.key,e.depth);_.isEqual(t,e.get("value"))||e.set({value:t})}})}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t._,r=t.StreamProbe,i=t.Stat,s="*",o=t.StatProbe=r.extend({probeClass:"Stat",defaults:n.extend({},r.prototype.defaults,{pattern:s}),initialize:function(){var e=this;r.prototype.initialize.apply(e,arguments),e.watcher=function(){var t=n.toArray(arguments);t.splice(0,0,JSON.stringify(new Date).substr(1,24)),e.queueItem.call(e,t)},i.on(e.get("pattern"),e.watcher)},release:function(){var e=this;i.off(e.get("pattern"),e.watcher)}})}(this),function(e){var t=e.Monitor||require("../Monitor"),n=t._,r=t.StreamProbe,i=t.Log,s="*",o=t.LogProbe=r.extend({probeClass:"Log",defaults:n.extend({},r.prototype.defaults,{pattern:s}),initialize:function(){var e=this;r.prototype.initialize.apply(e,arguments),e.watcher=function(){var t=n.toArray(arguments);t.splice(0,0,JSON.stringify(new Date).substr(1,24)),e.queueItem.call(e,t)},i.on(e.get("pattern"),e.watcher)},release:function(){var e=this;i.off(e.get("pattern"),e.watcher)}})}(this);
View
2  package.json
@@ -1,7 +1,7 @@
{
"name": "monitor",
"description": "Runtime monitoring for node.js applications",
- "version": "0.6.9",
+ "version": "0.6.10",
"main": "./lib/index.js",
"author": {
"name": "Loren West",
Please sign in to comment.
Something went wrong with that request. Please try again.