var MONTHS = { 1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec' } var monitor = {} monitor.utils = {} monitor.utils.get = {} monitor.utils.get.time = function (item) { // date = ([item.day + '-' + MONTHS[item.month] + '-' + item.year, hour + ':' + item.minute]).join(' ') var hour = item.hour > 9 ? item.hour : ('0' + item.hour) if (hour > 12) { var units = 'PM' } else { var units = 'AM' } return ([hour+':'+item.minute,units]).join(' ') } monitor.utils.get.dateTime = function (item) { var time = monitor.utils.get.time(item) return ([item.day+'-'+MONTHS[item.month]+'-'+item.year,time]).join(' ') } monitor.processes = {} monitor.processes.fetch = function(){ var httpclient = HttpClient.instance() httpclient.get(HTTP_CONTEXT+'/get/processes',monitor.processes.init); } monitor.processes.init = function (x) { var r = JSON.parse(x.responseText) monitor.processes.summary.init(r) var keys = jx.utils.keys(r) jx.dom.set.value('menu','') jx.utils.patterns.visitor(keys,function(label){ var div = jx.dom.get.instance('DIV') var frame= jx.dom.get.instance('DIV') var i = jx.dom.get.instance('I') i.className = 'fa fa-chevron-right left' div.innerHTML = label frame.data = r[label] frame.label = label frame.appendChild(i) frame.appendChild(div) frame.className = 'menu-item' frame.onclick = function () { monitor.processes.render(this.label, this.data); jx.dom.set.value('trends_chart','') //monitor.processes.trend.init(this.label) } jx.dom.append('menu',frame) }) // // Auto start the first item in the menu // This is designed not to let the user wander or wonder what is going on // var nodes = jx.dom.get.children('menu') if (nodes.length > 0) { nodes[0].click() } else { // // We should hide the panes for this // jx.dom.hide('apps') } monitor.sandbox.init() // setTimeout(monitor.sandbox.init,1000) } /** * This function renders the grid of processes being monitored, * @param label label the list of processes belongs to * @param data dataset of a selected set of processes (works a bit like top) */ monitor.processes.render = function(label,data) { data = jx.utils.patterns.visitor(data,function(row){ var status = {"idle":'',"running":'',"crash":''} if (!row.status.match(/class/)) { row.status_id = row.status row.status = status[row.status] } return row }) jx.dom.set.value('latest_processes','') ; jx.dom.set.value('latest_processes_label', label) var options = { width: $('#latest_processes').width(), height:'auto' } options.paging = true options.pageSize = 4 options.pageIndex = 1 options.pageButtonCount = 4 options.pagerContainer = '#latest_process_pager' options.pagerFormat= "{prev} Page {pageIndex} of {pageCount} {next}" options.pagePrevText= '' options.pageNextText= " " options.data = data options.rowClass = function (item, index,evt) { return 'small' } options.rowClick = function(args){ var item = args.item var id = jx.dom.get.value('latest_processes_label') var app = item.label monitor.processes.trend.init(id, app) if (item.anomaly == true) { jx.dom.show('has_anomaly') } else { jx.dom.hide('has_anomaly') } // var hour = item.hour < 10? ('0'+item.hour): item.hour // date = ([item.day + '-' + MONTHS[item.month] + '-' + item.year, hour + ':' + item.minute]).join(' ') jx.dom.set.value('node_last_lookup',monitor.utils.get.dateTime(item)) } options.autoload = true options.fields = [ { name: 'label', type: 'text', title: "Process", headercss: "small bold", css: "small"}, { name: "cpu_usage", type: "number", title: "CPU", headercss: "small bold" , width:'64px'}, { name: "memory_usage", type: "text", title: "Mem. Used", type: "number", headercss: "small bold" }, { name: "proc_count", type: "number", title: "Proc Count", headercss: "small bold" }, {name:"status",type:"text",title:"Status",headercss:"small bold",align:"center", width:'64px'} ] var grid = $('#latest_processes').jsGrid(options) ; // // We need to auto click the first row $('#latest_processes').find('.jsgrid-row')[0].click() } monitor.processes.trend = {} monitor.processes.trend.init = function (label,app) { var httpclient = HttpClient.instance() var uri = HTTP_CONTEXT+'/trends?id='+label+'&app='+encodeURIComponent(app) httpclient.get(uri, function (x) { var logs = JSON.parse(x.responseText) var dom = jx.dom.get.instance('trend_info'); dom.logs = logs jx.dom.set.value('trend_info',app.trim()) // jx.dom.set.attribute(label,'logs',logs) monitor.processes.trend.render(logs,null,app) }) } monitor.processes.trend.render = function (logs, key,label) { // if (key == null) { // key = 'memory_usage' // } // if (logs == null || label == null){ // logs = jx.dom.get.instance('trend_info').logs // label= jx.dom.get.value('trend_info') ; // } var frame = $('#trends_chart') jx.dom.set.value('trends_chart','') var context = jx.dom.get.instance('CANVAS') context.width = $(frame).width() context.height= $(frame).height() var conf = { type: 'line',responsive:true } conf.data = {} conf.options = { legend: { position: 'bottom' } } conf.options.scales = {} conf.options.scales.yAxes = [ {id:'0',scaleLabel:{display:true,labelString:'CPU & MEMORY %'},ticks:{min:0,max:100,beginAtZero:true},gridLines: {display:false}} // {id:'1',position:'right',scaleLabel:{display:true,labelString:'PROCESS COUNT'},ticks:{min:0,stepSize:1,beginAtZero:true},gridLines: {display:false}} ] conf.options.scales.xAxes = [ { gridLines: {display:false}, time: { format:'HH:mm' } } ] conf.data.datasets = [ ] var x_axis = [] var _x = {} // var _y = {} var cpu = {label: 'CPU Usage (%)', data: [] ,backgroundColor:'transparent',borderColor:COLORS[187],fill:false,borderWidth:1} var mem = {label : 'Memory Usage(%)',data:[],backgroundColor:'transparent',borderColor:COLORS[32],fill:false,borderWidth:1} // var proc= {yAxisID:'1',label : 'Proc Count',data:[],backgroundColor:'transparent',borderColor:COLORS[542],fill:false,borderWidth:1} // var months={1:"Jan",2:"Feb",3:"Mar",4:"Apr",5:"May",6:"Jun",7:"Jul",8:"Aug",9:"Sep",10:"Oct",11:"Nov",12:"Dec"} jx.utils.patterns.visitor(logs,function(item){ //x = new Date(item.year,item.month-1,item.day,item.hour,item.minute) // day = item.day.length > 1? (['0',item.day]).join(''): item.day // month = months[item.month] // x = ([month, day, item.hour + ':' + item.minute]).join(' ') x = monitor.utils.get.time(item).replace(/AM|PM/g,'') y = item[key] if (_x[x] == null ){//||(_x[x] == null && _y[y] == null)) { _x[x] = 1 // _y[y] = 1 x_axis.push(x) cpu.data.push({ x: x, y: item.cpu_usage }) mem.data.push({x:x,y:item.memory_usage}) // proc.data.push({x:x,y:item.proc_count}) // return {x:x,y:y} } }) var item = logs[logs.length - 1] jx.dom.set.value('trend_last_lookup',monitor.utils.get.dateTime(item)) conf.data.datasets = [cpu,mem] x_axis = jx.utils.unique(x_axis) conf.data.labels = x_axis // console.log(conf) jx.dom.append('trends_chart',context) var chart = new Chart(context,conf) } monitor.processes.summary = {} monitor.processes.summary.init = function(logs){ var xr = 0, xc = 0, xi = 0 var series = {} //var colors = [COLORS[11], COLORS[1], COLORS[2]] colors = [COLORS[11], COLORS[2], COLORS[100]] RUNNING_COLOR = COLORS[26] IDLE_COLOR = COLORS[100] CRASH_COLOR=COLORS[2] var i = 0; var date = null; for( label in logs ){ var rows = logs[label] series[label] = {data:[0,0,0],label:label} jx.utils.patterns.visitor(rows,function(item){ if (date == null) { // date = new Date(item.year,item.month-1,item.day,item.hour,item.minute) // date = ([item.day + '-' + MONTHS[item.month] + '-' + item.year, item.hour + ':' + item.minute]).join(' ') date = monitor.utils.get.dateTime(item) } if (item.status == 'running'){ xr += 1 }else if(item.status == 'idle'){ xi += 1 }else{ xc += 1 } }) } var data = {labels:['Running','Crash','Idle'],datasets:[{data:[xr,xc,xi],backgroundColor:[RUNNING_COLOR,CRASH_COLOR,IDLE_COLOR/**COLORS[11],COLORS[2],COLORS[100]*/]}]} var context = jx.dom.get.instance('CANVAS') context.id = 'doughnut' jx.dom.set.value('total-running', xr) jx.dom.set.value('total-crash', xc) jx.dom.set.value('total-idle', xi) // jx.dom.set.value('total-apps', xr + xi + xc) jx.dom.set.value('app-summary-date', date) jx.dom.set.value('summary_chart','') jx.dom.append('summary_chart', context) $("#doughnut").attr('width', 50) $("#doughnut").attr('height', 50) var conf = {}//width:100,height:100}//width:'auto',height:$('#process_summary').height} conf.type = 'doughnut' conf.responsive = true conf.data = data conf.options = { legend: { position: 'right' }, repsonsive: true } var _chart = new Chart(context,conf) $('#summary_chart').click(function (evt) { console.log(_chart) console.log($(_chart)) var activePoints = $(_chart).getSegmentsAtEvent(evt); console.log(activePoints) }) jx.dom.set.value('summary_ranking','') context = jx.dom.get.instance('CANVAS') jx.dom.append('summary_ranking',context) conf = { type: 'bar', responsive: true } conf.options={scales:{xAxes:[{gridLines: {display:false}}],yAxes:[{gridLines: {display:false},scaleLabel:{display:true,labelString:'PROCESS COUNTS'} }] }} conf.options.legend ={position:'right'} /* conf.data = {labels:['Running','Idle','Crash']} var labels = jx.utils.keys(series) var i = 0 conf.data.datasets = jx.utils.patterns.visitor(labels,function(id){ series[id].backgroundColor = COLORS[i++] return series[id]}) chart = new Chart(context,conf); */ var labels = jx.utils.keys(logs) conf.data = { labels: labels, backgroundColor:colors } var xr = [], xi = [], xc = [],xr_bg = [],xc_bg = [],xi_bg = [] jx.utils.patterns.visitor(labels, function (id) { var rows = logs[id] var index = xr.length xr_bg[index] = RUNNING_COLOR xi_bg[index] = IDLE_COLOR xc_bg[index] = CRASH_COLOR if (xr[index] == null) { xr[index] = 0 xc[index] = 0 xi[index] = 0 } jx.utils.patterns.visitor(logs[id], function (row) { if (row.status.match(/running/i)) { xr[index] += 1 } else if (row.status.match(/idle/i)) { xi[index] += 1 } else { xc[index] += 1 } }) }) conf.data.datasets = [{ label: 'Running', data:xr,backgroundColor:xr_bg},{label:'Crash',data:xc,backgroundColor:xc_bg},{label:'Idle',data:xi,backgroundColor:xi_bg} ] chart = new Chart(context, conf) } monitor.sandbox = {} monitor.sandbox.init = function () { jx.dom.hide('inspect_sandbox') var httpclient = HttpClient.instance() httpclient.get(HTTP_CONTEXT+'/sandbox', function (x) { var r = JSON.parse(x.responseText) if (r.length > 0) { jx.dom.show('sandbox') monitor.sandbox.render(r); } else { jx.dom.hide('sandbox') } }) } monitor.sandbox.render = function (logs) { // months = { 1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec' } // var d = ([logs[0].day, '-', MONTHS[logs[0].month], '-', logs[0].year, ' ', logs[0].hour, ':', logs[0].minute]).join('') var item = logs[logs.length -1] jx.dom.set.value('sandbox_date', monitor.utils.get.datetime(item)) var options = { width: $('#sandbox_status').width()-8, height: 'auto' } options.data = jx.utils.patterns.visitor(logs, function (item) { if (item.value == 100) { item.status = '' } else { item.status = '' } return item }) options.paging = true options.pageSize = 4 options.pageIndex = 1 options.pageButtonCount = 4 options.pagerContainer = '#folders_pager' options.pagerFormat = "{prev} Page {pageIndex} of {pageCount} {next}" options.pagePrevText = '' options.pageNextText = " "; options.rowClass = function (item) { if (item.value < 70) { return 'bad' } else if (item.value < 100) { return 'warning' } else { return 'good' } } options.rowClick = function (args) { var item = args.item; if (item.missing.length > 0) { var form = jx.dom.get.instance('FORM') var dom = jx.dom.get.instance('INPUT') dom.type = 'hidden' dom.name = 'missing' dom.value = JSON.stringify(item.missing) form.action = HTTP_CONTEXT+'/download' form.method = 'POST' form.appendChild(dom) form.submit() } } options.fields = [ {name:"status",title:"",width:20}, { name: 'label',title:'Virtual Environment Label',type:'text',css:'small',headercss:'small bold' }, { name: 'value', title:'Completeness %',type: 'number', css: 'small', headercss: 'small bold' } ] var grid = $('#sandbox_status').jsGrid(options) jx.dom.show('inspect_sandbox') } monitor.folders = {} monitor.folders.init = function () { var httpclient = HttpClient.instance() httpclient.get(HTTP_CONTEXT+'/folders', function (x) { var r = JSON.parse(x.responseText) var data = [] for (var id in r) { var item = r[id] // item.id = id data = data.concat(item) } monitor.folders.render.init(data) }) } monitor.folders.search = {} monitor.folders.search.reset = function () { jx.dom.set.value('folder_search', '') var data = jx.dom.get.attribute('folder_search', 'data') monitor.folders.render.summary(data) } monitor.folders.search.init = function(){ var term = jx.dom.get.value('folder_search') var data = jx.dom.get.attribute('folder_search', 'data') term = term.replace(/ /g,'') if (term.length == 0) { monitor.folders.render.summary(data) } else if (term.length > 0) { data = jx.utils.patterns.visitor(data, function (row) { pattern = "(.*" + term + ".*)" if (row.id.match(pattern)) { return row } }) monitor.folders.render.summary(data) } } monitor.folders.render = {} monitor.folders.render.init = function (data) { jx.dom.set.attribute('folder_search','data',data) monitor.folders.render.summary(data) } monitor.folders.show = {} monitor.folders.show.plan = function () { $('#folder_summary').slideUp(function () { $('#folder_plan').slideDown() }) } monitor.folders.show.grid = function () { $('#folder_plan').slideUp(function () { $('#folder_summary').slideDown() }) } /*** * This function is designed to establish a folder clean up strategy i.e : * - We will look for anomalies given age,file size * - We will also look for where most of the data is distributed (mode) */ monitor.folders.render.details = function (folder,data) { // // We need to normalize the data at this point so as to be able to show it all in the same chart // jx.math.scale x: counts, y: measure ment // var r = [data.age, data.size] var plans = [] for (var i in r) { var xy = r[i] var mode = jx.math.mode(jx.utils.vector('x', xy)) var yvalues = jx.utils.patterns.visitor(xy, function (row) { if (row.x == mode) { return row.y } }) var sd = jx.math.sd(yvalues) if (i == 0) { prefix = 'age' var mean = jx.math.mean(yvalues) var max = (mean + (1.5 * sd)) if (mean > 30 && mean < 365) { divide_by = 30 units = 'MONTHS' } else if (mean > 365) { divide_by=365 units = 'YEARS' } else { divide_by = 1 units = 'DAYS' } } else { prefix = 'size' var mean = jx.math.sum(yvalues) var max = 0// (mean + (1.5 * sd)) if (mean > 1000) { divide_by = 1000 units = 'GB' } else { divide_by = 1 units = 'MB' } } if (isNaN(mean)) { mean = 0 } // // We need to assess the outliars i.e too old, too large // y = jx.utils.vector('y', xy) var _mean = jx.math.mean(y) var _sd = jx.math.sd(y) var outlier = _mean < mean || max > (_mean + (1.5 * _sd)) plans.push({ 'label': prefix, 'max': max, 'sd': sd, 'mean': mean, 'count': yvalues.length, 'outlier': outlier }) jx.dom.set.value(prefix + '_count', yvalues.length) jx.dom.set.value(prefix + '_value', (mean/divide_by).toFixed(2)) jx.dom.set.value(prefix+'_units',units) monitor.folders.show.plan() } jx.dom.set.value('folder_name', folder) } monitor.folders.render.summary = function (data) { jx.dom.set.value('gridfolders', '') var options = { width: $('#gfolderframe').width()-8, height:'auto' } options.paging = true options.pageSize = 4 options.pageIndex = 1 options.pageButtonCount = 4 options.pagerContainer = '#folderspager' options.pagerFormat= "{prev} Page {pageIndex} of {pageCount} {next}" options.pagePrevText= '' options.pageNextText= " " options.data = data options.rowClass = function (item, index,evt) { return 'small' } options.rowClick = function(args){ // var item = args.item // age = jx.utils.patterns.visitor(item.details.age, function (row) { // return {y:row[0],x:row[1]} // }) // size = jx.utils.patterns.visitor(item.details.size, function (row) { // return {y:row[0],x:row[1]} // }) // monitor.folders.render.details(item.name,{age:age,size:size}) } // // @TODO Add the units in days just in case options.autoload = true options.fields = [ { name: 'id', type: 'text', title: "Host", headercss: "small bold", css: "small"}, { name: 'name', type: 'text', title: "Folder Name", headercss: "small bold", css: "small"}, { name: "size", type: "number", title: "Folder Size", type: "number", headercss: "small bold" }, { name: "count", type: "number", title: "File Count", type: "number", headercss: "small bold" } ] var grid = $('#gridfolders').jsGrid(options) ; } monitor.menu = {} monitor.menu.event = {} monitor.menu.event.toggle = function () { var dom = jx.dom.get.instance('menuframe') var value = dom.style.marginLeft.trim() if (value==0 || value == "0px" || value == "") { var width = -$(dom).width() - 10 $('#menuframe').animate({marginLeft:"-12%"}) } else { $('#menuframe').animate({marginLeft:"0"}) } } /** * Socket handler, check for learning status */