Skip to content

Commit

Permalink
Merge "Related-Bug:#1581650 Initial checkin for monitor infra config …
Browse files Browse the repository at this point in the history
…node summary and dashboard new design implementation. Change-Id: I072860251d3ad7b603d5dd0521713b2a33d429f8"
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed May 17, 2016
2 parents 9df14ee + 46fefdf commit 0a98e63
Show file tree
Hide file tree
Showing 11 changed files with 705 additions and 184 deletions.
3 changes: 2 additions & 1 deletion webroot/common/ui/js/controller.app.js
Expand Up @@ -61,12 +61,13 @@ function getControllerAppPaths (ctBaseDir, ctBuildDir) {
'traceflow-model': ctWebDir + '/monitor/infrastructure/underlay/ui/js/models/TraceFlowTabModel',
'underlay-graph-model' : ctWebDir + '/monitor/infrastructure/underlay/ui/js/models/UnderlayGraphModel',
'monitor-infra-confignode-model' : ctWebDir + '/monitor/infrastructure/common/ui/js/models/ConfigNodeListModel',
'monitor-infra-confignode-charts-model': ctWebDir + '/monitor/infrastructure/common/ui/js/models/ConfigNodeChartsModel',
'monitor-infra-analyticsnode-model' : ctWebDir + '/monitor/infrastructure/common/ui/js/models/AnalyticsNodeListModel',
'monitor-infra-databasenode-model' : ctWebDir + '/monitor/infrastructure/common/ui/js/models/DatabaseNodeListModel',
'monitor-infra-controlnode-model' : ctWebDir + '/monitor/infrastructure/common/ui/js/models/ControlNodeListModel',
'monitor-infra-vrouter-model' : ctWebDir + '/monitor/infrastructure/common/ui/js/models/VRouterListModel',
'monitor-infra-utils' : ctWebDir + '/monitor/infrastructure/common/ui/js/utils/monitor.infra.utils',
'confignode-scatterchart-view': ctWebDir + '/monitor/infrastructure/common/ui/js/views/ConfigNodeScatterChartView',
'confignode-chart-view': ctWebDir + '/monitor/infrastructure/common/ui/js/views/ConfigNodeChartsView',
'controlnode-scatterchart-view': ctWebDir + '/monitor/infrastructure/common/ui/js/views/ControlNodeScatterChartView',
'dbnode-scatterchart-view': ctWebDir + '/monitor/infrastructure/common/ui/js/views/DatabaseNodeScatterChartView',
'analyticsnode-scatterchart-view': ctWebDir + '/monitor/infrastructure/common/ui/js/views/AnalyticsNodeScatterChartView',
Expand Down
6 changes: 6 additions & 0 deletions webroot/common/ui/js/controller.constants.js
Expand Up @@ -229,6 +229,12 @@ define([
this.TRACEFLOW_INTERVAL = 5;
this.UNDERLAY_FLOW_INFO_TEMPLATE = "flow-info-template";

//Config Summary page Constants
this.CONFIGNODESTATS_BUCKET_DURATION = 240000000;
this.CONFIGNODE_COLORS = ['#b0c8c3', '#bf94e0', '#5d6e7e', '#b2a198', '#eccc9b'];
this.CONFIGNODE_FAILEDREQUESTS_TITLE = 'Failed Requests';
this.CONFIGNODE_FAILEDREQUESTS_COLOR = '#d95436';

this.getProjectsURL = function (domainObj, dropdownOptions) {
/* Default: get projects from keystone or API Server as specified in
* config.global.js, getDomainProjectsFromApiServer is true, then
Expand Down
11 changes: 9 additions & 2 deletions webroot/common/ui/js/controller.labels.js
Expand Up @@ -302,6 +302,8 @@ define([
this.TITLE_CPU = "CPU Share (%)";
this.TITLE_CPU_LOAD = "CPU Load";
this.TITLE_MEMORY = "Memory";
this.RESPONSE_SIZE = 'Response size';
this.RESPONSE_TIME = 'Response time';

/** Titles used in node details chart widget **/
this.TITLE_CONTROLNODE_CPU_MEM_UTILIZATION = 'Control Node CPU/Memory Utilization';
Expand Down Expand Up @@ -363,17 +365,22 @@ define([
this.CONFIGNODE_SUMMARY_URL = '/api/admin/monitor/infrastructure/confignodes/summary';
this.CONFIGNODE_SUMMARY_TITLE = 'Config Nodes';
this.CONFIGNODE_SUMMARY_GRID_ID = 'config-nodes-grid';
this.CONFIGNODE_SUMMARY_SCATTERCHART_ID = 'config-nodes-scatterchart';
this.CONFIGNODE_SUMMARY_STACKEDCHART_ID = 'config-nodes-stackedchart';
this.CONFIGNODE_SUMMARY_DONUTCHART_SECTION_ID = 'config-nodes-donutchart-section';
this.CONFIGNODE_SUMMARY_DONUTCHART_ONE_ID = 'config-nodes-donutchart-one';
this.CONFIGNODE_SUMMARY_DONUTCHART_TWO_ID = 'config-nodes-donutchart-two';
this.CONFIGNODE_SUMMARY_LINEBARCHART_ID = 'config-nodes-linebarchart';
this.CONFIGNODE_SUMMARY_GRID_SECTION_ID = "config-nodes-grid-section";
this.CONFIGNODE_SUMMARY_CHART_ID = 'config-nodes-chart';
this.CONFIGNODE_SUMMARY_LIST_SECTION_ID = 'config-nodes-list-section';
this.CONFIGNODE_SUMMARY_SCATTERCHART_SECTION_ID = 'config-nodes-scatterchart-section';
this.CONFIGNODE_SUMMARY_CHART_SECTION_ID = 'config-nodes-chart-section';
this.CONFIGNODE_DETAILS_PAGE_ID = 'config_nodes_details_pages';
this.CONFIGNODE_TAB_SECTION_ID = 'config_node_tab_section';
this.CONFIGNODE_TAB_VIEW_ID = 'config_node_tab';
this.CONFIGNODE_DETAILS_SECTION_ID = 'config_node_details_section';
this.CONFIGNODE_TABS_ID = 'config_node_tab'
this.CACHE_CONFIGNODE = 'cache-config-nodes';
this.CACHE_CONFIGNODE_CHARTS = 'cache-config-nodes-charts';
this.CONFIGNODE_DETAILS_APISERVER_CHART_SECTION_ID = 'config_node_details_apiserver_agent_chart_section';
this.CONFIGNODE_DETAILS_APISERVER_LINE_CHART_ID = 'config_node_details_apiserver_line_chart';
this.CONFIGNODE_DETAILS_SERVICE_MONITOR_CHART_SECTION_ID = 'config_node_details_service_monitor_chart_section';
Expand Down
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
*/

define([
'contrail-list-model'
], function (ContrailListModel) {
var ConfigNodeChartsModel = function () {
var queryPostData = {
"autoSort": true,
"async": false,
"formModelAttrs": {
"table_name": "StatTable.VncApiStatsLog.api_stats",
"table_type": "STAT",
"query_prefix": "stat",
"time_range": "3600",
"from_time": Date.now() - (2 * 60 * 60 * 1000),
"from_time_utc": Date.now() - (2 * 60 * 60 * 1000),
"to_time": Date.now(),
"to_time_utc": Date.now(),
"select": "Source, T, UUID, api_stats.operation_type," +
" api_stats.user, api_stats.useragent, api_stats.remote_ip," +
" api_stats.domain_name, api_stats.project_name, api_stats.object_type," +
" api_stats.response_time_in_usec, api_stats.response_size," +
" api_stats.resp_code, name",
"time_granularity_unit": "secs",
"where": "",
"where_json": null,
"filter_json": null,
"direction": "1",
"filters": "",
"limit": "150000"
},
};
var listModelConfig = {
remote : {
ajaxConfig : {
url : "/api/qe/query",
type: 'POST',
data: JSON.stringify(queryPostData)
},
dataParser : function (response) {
return response['data'];
}
},
cacheConfig : {
ucid: ctwl.CACHE_CONFIGNODE_CHARTS
}
};

return ContrailListModel(listModelConfig);
};
return ConfigNodeChartsModel;
}
);
@@ -1,7 +1,6 @@
/*
* Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
*/

define(
[ 'underscore' ],
function(_) {
Expand Down Expand Up @@ -495,7 +494,6 @@ define(
};

this.parseConfigNodesDashboardData = function (result) {

var retArr = [];
$.each(result,function(idx,d) {
var obj = {};
Expand Down Expand Up @@ -700,8 +698,222 @@ define(
retArr.sort(dashboardUtils.sortNodesByColor);
return retArr;

}
};

this.bucketizeConfigNodeStats = function (apiStats, bucketDuration) {
bucketDuration = ifNull(bucketDuration, ctwc.CONFIGNODESTATS_BUCKET_DURATION);
var minMaxTS = d3.extent(apiStats,function(obj){
return obj['T'];
});
//If only 1 value extend the range by 10 mins on both sides
if(minMaxTS[0] == minMaxTS[1]) {
minMaxTS[0] -= ctwc.CONFIGNODESTATS_BUCKET_DURATION;
minMaxTS[1] += ctwc.CONFIGNODESTATS_BUCKET_DURATION;
}
/* Bucketizes timestamp every 10 minutes */
var xBucketScale = d3.scale.quantize().domain(minMaxTS).range(d3.range(minMaxTS[0],minMaxTS[1], bucketDuration));
var buckets = {};
//Group nodes into buckets
$.each(apiStats,function(idx,obj) {
var xBucket = xBucketScale(obj['T']);
if(buckets[xBucket] == null) {
var timestampExtent = xBucketScale.invertExtent(xBucket);
buckets[xBucket] = {timestampExtent:timestampExtent,
data:[]};
}

buckets[xBucket]['data'].push(obj);
});
return buckets;
};

this.parseConfigNodeRequestsStackChartData = function (apiStats) {
var cf =crossfilter(apiStats);
var parsedData = [];
var timeStampField = 'T';
var groupDim = cf.dimension(function(d) { return d["Source"];});
var tsDim = cf.dimension(function(d) { return d[timeStampField];});
var buckets = this.bucketizeConfigNodeStats(apiStats);
var colorCodes = ctwc.CONFIGNODE_COLORS;
colorCodes = colorCodes.slice(0, groupDim.group().all().length);
//Now parse this data to be usable in the chart
var parsedData = [];
for(var i in buckets) {
var y0 = 0, counts = [], totalFailedReqs = 0;
var timestampExtent = buckets[i]['timestampExtent'];
tsDim.filter(timestampExtent);
var reqCntData = groupDim.group().all();
//Getting nodes group with failed requests as value
var reqFailedData = groupDim.group().reduceSum(
function (d) {
if (parseInt(d['api_stats.resp_code']) != 200) {
return 1;
} else {
return 0;
}
});
//Getting nodes group with response time as value
var totalResTimeData = groupDim.group().reduceSum(
function (d) {
return d['api_stats.response_time_in_usec'];
});
var reqFailedArr = reqFailedData.top(Infinity);
var resTimeArr = totalResTimeData.top(Infinity);
var reqFailedArrLen = reqFailedArr.length;
var resTimeArrLen = resTimeArr.length;
var reqFailedNodeMap = {}, resTimeNodeMap = {};
//Constructing the node - responsetime map
for (var j = 0; j < resTimeArrLen; j++) {
resTimeNodeMap[resTimeArr[j]['key']] =
resTimeArr[j]['value'];
}
//Constructing the node - failedRequestCnt map
for (var j = 0; j < reqFailedArrLen; j++) {
totalFailedReqs += reqFailedArr[j]['value']
reqFailedNodeMap[reqFailedArr[j]['key']] =
reqFailedArr[j]['value'];
}
var totalReqs = 0;
for (var j = 0, len = reqCntData.length; j < len; j++) {
totalReqs += reqCntData[j]['value']
}
counts.push({
name: ctwc.CONFIGNODE_FAILEDREQUESTS_TITLE,
totalReqs: totalReqs,
totalFailedReq: totalFailedReqs,
color: ctwc.CONFIGNODE_FAILEDREQUESTS_COLOR,
y0: y0,
y1: y0 += totalFailedReqs
});
parsedData.push({
colorCodes: colorCodes,
counts: counts,
total: totalFailedReqs,
timestampExtent: timestampExtent,
date: new Date(i / 1000)
});
for(var j=0,len=reqCntData.length;j<len;j++) {
var nodeName = reqCntData[j]['key'];
var nodeReqCnt = reqCntData[j]['value'];
var failedReqPerNode = ifNull(reqFailedNodeMap[nodeName], 0);
var failedReqPerNodePercent = 0;
if (failedReqPerNode != 0 && nodeReqCnt != 0) {
failedReqPerNodePercent = Math.round((failedReqPerNode/nodeReqCnt) * 100);
}
var avgResTime = Math.round((ifNull(resTimeNodeMap[nodeName], 0)/nodeReqCnt)) / 1000; //Converting to millisecs
counts.push({
name: nodeName,
color: colorCodes[j],
avgResTime: contrail.format('{0} {1}', avgResTime, 'ms'),
reqFailPercent: failedReqPerNodePercent,
y0:y0,
y1:y0 += nodeReqCnt
});
parsedData.push({
counts: counts,
total: totalReqs,
timestampExtent: timestampExtent,
date: new Date(i / 1000)
});
}
}
return parsedData;
};
this.parseConfigNodeResponseStackedChartData = function (apiStats) {
var buckets = this.bucketizeConfigNodeStats(apiStats, 600000000);
var colors = ctwc.CONFIGNODE_COLORS;
var cf = crossfilter(apiStats);
var tsDim = cf.dimension(function (d) {return d.T});
var sourceDim = cf.dimension(function (d) {return d.Source});
var sourceGroupedData = sourceDim.group().all();
var nodeMap = {}, chartData = [];
$.each(sourceGroupedData, function (idx, obj) {
nodeMap[obj['key']] = {
key: obj['key'],
values: [],
bar: true,
color: colors[idx] != null ? colors[idx] : cowc.D3_COLOR_CATEGORY5[1]
};
chartData.push(nodeMap[obj['key']]);
});
var lineChartData = {
key: ctwl.RESPONSE_SIZE,
values: [],
color: '#7f9d92'
}
for (var i in buckets) {
var timestampExtent = buckets[i]['timestampExtent'],
aggResSize = 0,
avgResSize = 0,
nodeReqMap = {};
tsDim.filter(timestampExtent);
var bucketRequestsCnt = tsDim.top(Infinity).length;
sourceGroupedData = sourceDim.group().all();
$.each(sourceGroupedData, function(idx, obj) {
nodeReqMap[obj['key']] = obj['value'];
});
var resTimeData = sourceDim.group().reduceSum(function (d) {
return d['api_stats.response_time_in_usec'];
});
var resSizeData = sourceDim.group().reduceSum(function (d) {
return d['api_stats.response_size'];
});
var resTimeArr = resTimeData.top(Infinity);
var resSizeArr = resSizeData.top(Infinity);
var resTimeArrLen = resTimeArr.length;
var resSizeArrLen = resSizeArr.length;
var resTimeNodeMap = {}, resSizeNodeMap = {};
//Averaging the response time on node basis
for (var j = 0; j < resTimeArrLen; j++) {
if (nodeMap[resTimeArr[j]['key']] != null ) {
var avgResTime = 0;
avgResTime = resTimeArr[j]['value']/nodeReqMap[resTimeArr[j]['key']];
avgResTime = avgResTime/1000; // converting to milli secs
nodeMap[resTimeArr[j]['key']]['values'].push({
x: Math.round(i/1000),
y: avgResTime
});
}
}
//Calculating the aggregrate response size of all the nodes
//in particular interval and averaging with overall requests
//in the particular time interval.
for (var j = 0; j < resSizeArrLen; j++) {
aggResSize += resSizeArr[j]['value'];
}
avgResSize = aggResSize/bucketRequestsCnt;
lineChartData['values'].push({
x: Math.round(i/1000),
y: avgResSize
});
}
chartData.push(lineChartData);
return chartData;

};
this.parseConfigNodeRequestForDonutChart = function (apiStats, reqType) {
var cf = crossfilter(apiStats), parsedData = [];
if (!$.isArray(reqType)) {
reqType = [reqType];
}
var reqTypeDim = cf.dimension(function (d) {return d['api_stats.operation_type']});
var sourceDim = cf.dimension(function (d) {return d['Source']});
var sourceGrpDim = sourceDim.group().reduceSum(function(d) {
if (reqType.indexOf(d['api_stats.operation_type']) > -1) {
return 1;
} else {
return 0;
}
});
var sourceGrpData = sourceGrpDim.all();
$.each(sourceGrpData, function (key, value){
parsedData.push({
label: value['key'],
value: value['value']
});
});
return parsedData;
};
this.getNodeVersion = function (buildStr) {
var verStr = '';
if(buildStr != null) {
Expand Down

0 comments on commit 0a98e63

Please sign in to comment.