You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
smart-top/old/dashboard.js

619 lines
18 KiB
JavaScript

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":'<i class="fa fa-ellipsis-h" title="IDLE"></i>',"running":'<i class="fa fa-check" title="RUNNING"></i>',"crash":'<i class="fa fa-times" title="CRASHED"></i>'}
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: "90%", height:'auto', autoload:true
}
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= '<i class="fa fa-chevron-left"></i>'
options.pageNextText= "<i class='fa fa-chevron-right small' title='Next'> </i>"
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})
console.log(item.cpu_usage)
console.log(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 = ["#00BFFF", "#b2beb5", "#ffa812"]
colors = [COLORS[0], COLORS[2], COLORS[1]]
RUNNING_COLOR = COLORS[0]
// RUNNING_COLOR = #0072BB
IDLE_COLOR = COLORS[1]
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 = '<i class="fa fa-check" style="color:green"></i>'
} else {
item.status = '<i class="fa fa-download" style="color:black"></i>'
}
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 = '<i class="fa fa-chevron-left"></i>'
options.pageNextText = "<i class='fa fa-chevron-right small' title='Next'> </i>";
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= '<i class="fa fa-chevron-left"></i>'
options.pageNextText= "<i class='fa fa-chevron-right small' title='Next'> </i>"
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() - 20
$('#menuframe').animate({marginLeft:"-20%"})
} else {
$('#menuframe').animate({marginLeft:"0"})
}
}
/**
* Socket handler, check for learning status
*/