blob: a31078cfd7b3a8c8916305c8dbd8a692d542fb2c [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
"use strict";
var isIgnoredJmxKeys = function(key) {
return key == 'name' || key == 'modelerType' || key == "$$hashKey" ||
key.match(/tag.*/);
};
angular.module('ozone', ['nvd3', 'ngRoute']);
angular.module('ozone').config(function($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "main.html"
})
.when("/metrics/rpc", {
template: "<rpc-metrics></rpc-metrics>"
})
.when("/config", {
template: "<config></config>"
})
});
angular.module('ozone').component('overview', {
templateUrl: 'static/templates/overview.html',
transclude: true,
controller: function($http) {
var ctrl = this;
$http.get("jmx?qry=Hadoop:service=*,name=*,component=ServerRuntime")
.then(function(result) {
ctrl.jmx = result.data.beans[0]
})
}
});
angular.module('ozone').component('jvmParameters', {
templateUrl: 'static/templates/jvm.html',
controller: function($http) {
var ctrl = this;
$http.get("jmx?qry=java.lang:type=Runtime")
.then(function(result) {
ctrl.jmx = result.data.beans[0];
//convert array to a map
var systemProperties = {};
for (var idx in ctrl.jmx.SystemProperties) {
var item = ctrl.jmx.SystemProperties[idx];
systemProperties[item.key.replace(/\./g, "_")] = item.value;
}
ctrl.jmx.SystemProperties = systemProperties;
})
}
});
angular.module('ozone').component('rpcMetrics', {
template: '<h1>Rpc metrics</h1><tabs>' +
'<pane ng-repeat="metric in $ctrl.metrics" ' +
'title="{{metric[\'tag.serverName\']}} ({{metric[\'tag.port\']}})">' +
'<rpc-metric jmxdata="metric"></rpc-metric></pane>' +
'</tabs>',
controller: function($http) {
var ctrl = this;
$http.get("jmx?qry=Hadoop:service=*,name=RpcActivityForPort*")
.then(function(result) {
ctrl.metrics = result.data.beans;
})
}
});
angular.module('ozone').component('rpcMetric', {
bindings: {
jmxdata: '<'
},
templateUrl: 'static/templates/rpc-metrics.html',
controller: function() {
var ctrl = this;
ctrl.percentileGraphOptions = {
chart: {
type: 'discreteBarChart',
height: 450,
margin: {
top: 20,
right: 20,
bottom: 50,
left: 55
},
x: function(d) {
return d.label;
},
y: function(d) {
return d.value;
},
showValues: true,
valueFormat: function(d) {
return d3.format(',.1f')(d);
},
duration: 500,
xAxis: {
axisLabel: 'Percentage'
},
yAxis: {
axisLabel: 'Latency (ms)',
axisLabelDistance: -10
}
}
};
ctrl.$onChanges = function(data) {
var groupedMetrics = {}
var createPercentageMetrics = function(metricName, window) {
groupedMetrics.percentiles = groupedMetrics['percentiles'] || {}
groupedMetrics.percentiles[window] = groupedMetrics.percentiles[window] || {};
groupedMetrics.percentiles[window][metricName] = groupedMetrics.percentiles[window][metricName] || {
graphdata: [{
key: window,
values: []
}],
numOps: 0
};
};
var metrics = ctrl.jmxdata;
for (var key in metrics) {
var percentile = key.match(/(.*Time)(\d+s)(\d+th)PercentileLatency/);
var percentileNumOps = key.match(/(.*Time)(\d+s)NumOps/);
var successFailures = key.match(/(.*)(Success|Failures)/);
var numAverages = key.match(/(.*Time)(NumOps|AvgTime)/);
if (percentile) {
var metricName = percentile[1];
var window = percentile[2];
var percentage = percentile[3]
createPercentageMetrics(metricName, window);
groupedMetrics.percentiles[window][metricName].graphdata[0]
.values.push({
label: percentage,
value: metrics[key]
})
} else if (successFailures) {
var metricName = successFailures[1];
groupedMetrics.successfailures = groupedMetrics['successfailures'] || {}
groupedMetrics.successfailures[metricName] = groupedMetrics.successfailures[metricName] || {
success: 0,
failures: 0
};
if (successFailures[2] == 'Success') {
groupedMetrics.successfailures[metricName].success = metrics[key];
} else {
groupedMetrics.successfailures[metricName].failures = metrics[key];
}
} else if (numAverages) {
var metricName = numAverages[1];
groupedMetrics.numavgs = groupedMetrics['numavgs'] || {}
groupedMetrics.numavgs[metricName] = groupedMetrics.numavgs[metricName] || {
numOps: 0,
avgTime: 0
};
if (numAverages[2] == 'NumOps') {
groupedMetrics.numavgs[metricName].numOps = metrics[key];
} else {
groupedMetrics.numavgs[metricName].avgTime = metrics[key];
}
} else if (percentileNumOps) {
var metricName = percentileNumOps[1];
var window = percentileNumOps[2];
createPercentageMetrics(metricName, window);
groupedMetrics.percentiles[window][metricName].numOps = metrics[key];
} else if (isIgnoredJmxKeys(key)) {
//ignore
} else {
groupedMetrics.others = groupedMetrics.others || [];
groupedMetrics.others.push({
'key': key,
'value': metrics[key]
});
}
}
ctrl.metrics = groupedMetrics;
};
}
});
angular.module('ozone')
.component('tabs', {
transclude: true,
controller: function($scope) {
var ctrl = this;
var panes = this.panes = [];
this.select = function(pane) {
angular.forEach(panes, function(pane) {
pane.selected = false;
});
pane.selected = true;
};
this.addPane = function(pane) {
if (panes.length === 0) {
this.select(pane);
}
panes.push(pane);
};
this.click = function(pane) {
ctrl.select(pane);
}
},
template: '<div class="nav navtabs"><div class="row"><ul' +
' class="nav nav-pills">' +
'<li ng-repeat="pane in $ctrl.panes" ng-class="{active:pane.selected}">' +
'<a href="" ng-click="$ctrl.click(pane)">{{pane.title}}</a> ' +
'</li> </ul></div><br/><div class="tab-content" ng-transclude></div> </div>'
})
.component('pane', {
transclude: true,
require: {
tabsCtrl: '^tabs'
},
bindings: {
title: '@'
},
controller: function() {
this.$onInit = function() {
this.tabsCtrl.addPane(this);
};
},
template: '<div class="tab-pane" ng-if="$ctrl.selected" ng-transclude></div>'
});
angular.module('ozone').component('navmenu', {
bindings: {
metrics: '<'
},
templateUrl: 'static/templates/menu.html',
controller: function($http) {
var ctrl = this;
ctrl.docs = false;
$http.head("docs/index.html")
.then(function(result) {
ctrl.docs = true;
}, function() {
ctrl.docs = false;
});
}
});
angular.module('ozone').component('config', {
templateUrl: 'static/templates/config.html',
controller: function($scope, $http) {
var ctrl = this;
ctrl.selectedTags = [];
ctrl.configArray = [];
$http.get("conf?cmd=getOzoneTags")
.then(function(response) {
ctrl.tags = response.data;
var excludedTags = ['CBLOCK', 'OM', 'SCM'];
for (var i = 0; i < excludedTags.length; i++) {
var idx = ctrl.tags.indexOf(excludedTags[i]);
// Remove CBLOCK related properties
if (idx > -1) {
ctrl.tags.splice(idx, 1);
}
}
ctrl.loadAll();
});
ctrl.convertToArray = function(srcObj) {
ctrl.keyTagMap = {};
for (var idx in srcObj) {
//console.log("Adding keys for "+idx)
for (var key in srcObj[idx]) {
if (ctrl.keyTagMap.hasOwnProperty(key)) {
ctrl.keyTagMap[key]['tag'].push(idx);
} else {
var newProp = {};
newProp['name'] = key;
newProp['value'] = srcObj[idx][key];
newProp['tag'] = [];
newProp['tag'].push(idx);
ctrl.keyTagMap[key] = newProp;
}
}
}
}
ctrl.loadAll = function() {
$http.get("conf?cmd=getPropertyByTag&tags=OM,SCM," + ctrl.tags)
.then(function(response) {
ctrl.convertToArray(response.data);
ctrl.configs = Object.values(ctrl.keyTagMap);
ctrl.component = 'All';
ctrl.sortBy('name');
});
};
ctrl.filterTags = function() {
if (!ctrl.selectedTags) {
return true;
}
if (ctrl.selectedTags.length < 1 && ctrl.component == 'All') {
return true;
}
ctrl.configs = ctrl.configs.filter(function(item) {
if (ctrl.component != 'All' && (item['tag'].indexOf(ctrl
.component) < 0)) {
return false;
}
if (ctrl.selectedTags.length < 1) {
return true;
}
for (var tag in item['tag']) {
tag = item['tag'][tag];
if (ctrl.selectedTags.indexOf(tag) > -1) {
return true;
}
}
return false;
});
};
ctrl.configFilter = function(config) {
return false;
};
ctrl.selected = function(tag) {
return ctrl.selectedTags.includes(tag);
};
ctrl.switchto = function(tag) {
ctrl.component = tag;
ctrl.reloadConfig();
};
ctrl.select = function(tag) {
var tagIdx = ctrl.selectedTags.indexOf(tag);
if (tagIdx > -1) {
ctrl.selectedTags.splice(tagIdx, 1);
} else {
ctrl.selectedTags.push(tag);
}
ctrl.reloadConfig();
};
ctrl.reloadConfig = function() {
ctrl.configs = [];
ctrl.configs = Object.values(ctrl.keyTagMap);
ctrl.filterTags();
};
ctrl.sortBy = function(field) {
ctrl.reverse = (ctrl.propertyName === field) ? !ctrl.reverse : false;
ctrl.propertyName = field;
};
ctrl.allSelected = function(comp) {
//console.log("Adding key for compo ->"+comp)
return ctrl.component == comp;
};
}
});
})();