HDFS-13197. Ozone: Fix ConfServlet#getOzoneTags cmd. Contributed by Ajay Kumar.
This commit is contained in:
parent
979bbb4019
commit
908ddab55b
@ -0,0 +1,181 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.hadoop.hdds.conf;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.http.HttpServer2;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A servlet to print out the running configuration data.
|
||||
*/
|
||||
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
|
||||
@InterfaceStability.Unstable
|
||||
public class HddsConfServlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected static final String FORMAT_JSON = "json";
|
||||
protected static final String FORMAT_XML = "xml";
|
||||
private static final String COMMAND = "cmd";
|
||||
private static final OzoneConfiguration OZONE_CONFIG =
|
||||
new OzoneConfiguration();
|
||||
transient Logger LOG = LoggerFactory.getLogger(HddsConfServlet.class);
|
||||
|
||||
|
||||
/**
|
||||
* Return the Configuration of the daemon hosting this servlet.
|
||||
* This is populated when the HttpServer starts.
|
||||
*/
|
||||
private Configuration getConfFromContext() {
|
||||
Configuration conf = (Configuration) getServletContext().getAttribute(
|
||||
HttpServer2.CONF_CONTEXT_ATTRIBUTE);
|
||||
assert conf != null;
|
||||
return conf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
if (!HttpServer2.isInstrumentationAccessAllowed(getServletContext(),
|
||||
request, response)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String format = parseAcceptHeader(request);
|
||||
if (FORMAT_XML.equals(format)) {
|
||||
response.setContentType("text/xml; charset=utf-8");
|
||||
} else if (FORMAT_JSON.equals(format)) {
|
||||
response.setContentType("application/json; charset=utf-8");
|
||||
}
|
||||
|
||||
String name = request.getParameter("name");
|
||||
Writer out = response.getWriter();
|
||||
String cmd = request.getParameter(COMMAND);
|
||||
|
||||
processCommand(cmd, format, request, response, out, name);
|
||||
out.close();
|
||||
}
|
||||
|
||||
private void processCommand(String cmd, String format,
|
||||
HttpServletRequest request, HttpServletResponse response, Writer out,
|
||||
String name)
|
||||
throws IOException {
|
||||
try {
|
||||
if (cmd == null) {
|
||||
if (FORMAT_XML.equals(format)) {
|
||||
response.setContentType("text/xml; charset=utf-8");
|
||||
} else if (FORMAT_JSON.equals(format)) {
|
||||
response.setContentType("application/json; charset=utf-8");
|
||||
}
|
||||
|
||||
writeResponse(getConfFromContext(), out, format, name);
|
||||
} else {
|
||||
processConfigTagRequest(request, out);
|
||||
}
|
||||
} catch (BadFormatException bfe) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, bfe.getMessage());
|
||||
} catch (IllegalArgumentException iae) {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND, iae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static String parseAcceptHeader(HttpServletRequest request) {
|
||||
String format = request.getHeader(HttpHeaders.ACCEPT);
|
||||
return format != null && format.contains(FORMAT_JSON) ?
|
||||
FORMAT_JSON : FORMAT_XML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guts of the servlet - extracted for easy testing.
|
||||
*/
|
||||
static void writeResponse(Configuration conf,
|
||||
Writer out, String format, String propertyName)
|
||||
throws IOException, IllegalArgumentException, BadFormatException {
|
||||
if (FORMAT_JSON.equals(format)) {
|
||||
Configuration.dumpConfiguration(conf, propertyName, out);
|
||||
} else if (FORMAT_XML.equals(format)) {
|
||||
conf.writeXml(propertyName, out);
|
||||
} else {
|
||||
throw new BadFormatException("Bad format: " + format);
|
||||
}
|
||||
}
|
||||
|
||||
public static class BadFormatException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public BadFormatException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private void processConfigTagRequest(HttpServletRequest request,
|
||||
Writer out) throws IOException {
|
||||
String cmd = request.getParameter(COMMAND);
|
||||
Gson gson = new Gson();
|
||||
Configuration config = getOzoneConfig();
|
||||
|
||||
switch (cmd) {
|
||||
case "getOzoneTags":
|
||||
out.write(gson.toJson(config.get("ozone.system.tags").split(",")));
|
||||
break;
|
||||
case "getPropertyByTag":
|
||||
String tags = request.getParameter("tags");
|
||||
Map<String, Properties> propMap = new HashMap<>();
|
||||
|
||||
for (String tag : tags.split(",")) {
|
||||
if (config.isPropertyTag(tag)) {
|
||||
Properties properties = config.getAllPropertiesByTag(tag);
|
||||
propMap.put(tag, properties);
|
||||
} else {
|
||||
LOG.debug("Not a valid tag" + tag);
|
||||
}
|
||||
}
|
||||
out.write(gson.toJsonTree(propMap).toString());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(cmd + " is not a valid command.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Configuration getOzoneConfig() {
|
||||
return OZONE_CONFIG;
|
||||
}
|
||||
}
|
@ -993,6 +993,16 @@
|
||||
</description>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
<name>hadoop.custom.tags</name>
|
||||
<value>OZONE,MANAGEMENT,SECURITY,PERFORMANCE,DEBUG,CLIENT,SERVER,KSM,SCM,CRITICAL,RATIS,CONTAINER,REQUIRED,REST,STORAGE,PIPELINE,STANDALONE</value>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
<name>ozone.system.tags</name>
|
||||
<value>OZONE,MANAGEMENT,SECURITY,PERFORMANCE,DEBUG,CLIENT,SERVER,KSM,SCM,CRITICAL,RATIS,CONTAINER,REQUIRED,REST,STORAGE,PIPELINE,STANDALONE</value>
|
||||
</property>
|
||||
|
||||
|
||||
<property>
|
||||
<name>hdds.rest.rest-csrf.enabled</name>
|
||||
|
@ -21,6 +21,7 @@
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
||||
import org.apache.hadoop.hdfs.DFSUtil;
|
||||
import org.apache.hadoop.hdds.conf.HddsConfServlet;
|
||||
import org.apache.hadoop.http.HttpConfig;
|
||||
import org.apache.hadoop.http.HttpServer2;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
@ -79,6 +80,7 @@ public BaseHttpServer(Configuration conf, String name) throws IOException {
|
||||
builder.configureXFrame(xFrameEnabled).setXFrameOption(xFrameOptionValue);
|
||||
|
||||
httpServer = builder.build();
|
||||
httpServer.addServlet("conf", "/conf", HddsConfServlet.class);
|
||||
|
||||
}
|
||||
|
||||
@ -86,17 +88,19 @@ public BaseHttpServer(Configuration conf, String name) throws IOException {
|
||||
|
||||
/**
|
||||
* Add a servlet to BaseHttpServer.
|
||||
*
|
||||
* @param servletName The name of the servlet
|
||||
* @param pathSpec The path spec for the servlet
|
||||
* @param clazz The servlet class
|
||||
* @param pathSpec The path spec for the servlet
|
||||
* @param clazz The servlet class
|
||||
*/
|
||||
protected void addServlet(String servletName, String pathSpec,
|
||||
Class<? extends HttpServlet> clazz) {
|
||||
Class<? extends HttpServlet> clazz) {
|
||||
httpServer.addServlet(servletName, pathSpec, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the WebAppContext associated with this HttpServer.
|
||||
*
|
||||
* @return WebAppContext
|
||||
*/
|
||||
protected WebAppContext getWebAppContext() {
|
||||
|
@ -15,341 +15,373 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
(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>'
|
||||
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]
|
||||
})
|
||||
.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('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', 'KSM', '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();
|
||||
});
|
||||
|
||||
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;
|
||||
});
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
angular.module('ozone').component('config', {
|
||||
templateUrl: 'static/templates/config.html',
|
||||
controller: function ($scope, $http) {
|
||||
var ctrl = this;
|
||||
ctrl.selectedTags = [];
|
||||
ctrl.loadAll = function() {
|
||||
$http.get("conf?cmd=getPropertyByTag&tags=KSM,SCM," + ctrl.tags)
|
||||
.then(function(response) {
|
||||
|
||||
$http.get("conf?cmd=getOzoneTags&group=ozone")
|
||||
.then(function (response) {
|
||||
ctrl.tags = response.data;
|
||||
|
||||
var excludedTags = ['CBLOCK', 'KSM', '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.loadAll = function () {
|
||||
console.log("Displaying all configs");
|
||||
$http.get("conf?cmd=getPropertyByTag&tags=" + ctrl.tags + "&group=ozone").then(function (response) {
|
||||
ctrl.configs = response.data;
|
||||
console.log(ctrl.configs)
|
||||
for (var idx in ctrl.configs) {
|
||||
var tags = []
|
||||
var parsedTags = ctrl.configs[idx].tag.split(",");
|
||||
for (var t in parsedTags) {
|
||||
tags.push(parsedTags[t].trim())
|
||||
}
|
||||
ctrl.configs[idx].tag = tags;
|
||||
|
||||
};
|
||||
ctrl.sortBy('name');
|
||||
});
|
||||
};
|
||||
|
||||
ctrl.tagFilter = function (value, index, array) {
|
||||
if (!ctrl.selectedTags) {
|
||||
return true;
|
||||
}
|
||||
var selected = true;
|
||||
for (var idx in ctrl.selectedTags) {
|
||||
selected = selected && (value.tag.indexOf(ctrl.selectedTags[idx]) > -1);
|
||||
}
|
||||
return selected;
|
||||
};
|
||||
ctrl.configFilter = function (config) {
|
||||
return false;
|
||||
};
|
||||
ctrl.selected = function (tag) {
|
||||
return ctrl.selectedTags.includes(tag);
|
||||
};
|
||||
|
||||
ctrl.allSelected = function () {
|
||||
return ctrl.selectedTags.indexOf('SCM') == -1
|
||||
&& ctrl.selectedTags.indexOf('KSM') == -1
|
||||
};
|
||||
|
||||
ctrl.switchto = function (tag) {
|
||||
var tags = ctrl.selectedTags.filter(function (item) {
|
||||
return item != 'KSM' && item != 'SCM';
|
||||
});
|
||||
if (tag) {
|
||||
tags.push(tag);
|
||||
}
|
||||
ctrl.selectedTags = tags;
|
||||
};
|
||||
|
||||
ctrl.select = function (tag) {
|
||||
var tagIdx = ctrl.selectedTags.indexOf(tag);
|
||||
if (tagIdx > -1) {
|
||||
ctrl.selectedTags = ctrl.selectedTags.filter(function (item) {
|
||||
return item != tag;
|
||||
});
|
||||
} else {
|
||||
ctrl.selectedTags.push(tag);
|
||||
}
|
||||
console.log("Tags selected:" + ctrl.selectedTags);
|
||||
};
|
||||
|
||||
ctrl.sortBy = function (propertyName) {
|
||||
ctrl.reverse = (ctrl.propertyName === propertyName) ? !ctrl.reverse : false;
|
||||
ctrl.propertyName = propertyName;
|
||||
};
|
||||
ctrl.convertToArray(response.data);
|
||||
ctrl.configs = Object.values(ctrl.keyTagMap);
|
||||
ctrl.component = 'All';
|
||||
console.log("ajay -> " + JSON.stringify(ctrl.configs));
|
||||
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)) {
|
||||
console.log(item['name'] + " false tag " + item['tag']);
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
@ -23,14 +23,14 @@
|
||||
<div class="col-md-10">
|
||||
<div class="btn-group btn-group-justified">
|
||||
<a class="btn"
|
||||
ng-class="$ctrl.allSelected() ? 'btn-primary' :'btn-secondary'"
|
||||
ng-click="$ctrl.switchto('')">All
|
||||
ng-class="$ctrl.allSelected('All') ? 'btn-primary' :'btn-secondary'"
|
||||
ng-click="$ctrl.switchto('All')">All
|
||||
</a>
|
||||
<a class="btn"
|
||||
ng-class="$ctrl.selected('KSM') ? 'btn-primary' :'btn-secondary'"
|
||||
ng-class="$ctrl.allSelected('KSM') ? 'btn-primary' :'btn-secondary'"
|
||||
ng-click="$ctrl.switchto('KSM')">KSM</a>
|
||||
<a class="btn"
|
||||
ng-class="$ctrl.selected('SCM') ? 'btn-primary' :'btn-secondary'"
|
||||
ng-class="$ctrl.allSelected('SCM') ? 'btn-primary' :'btn-secondary'"
|
||||
ng-click="$ctrl.switchto('SCM')">SCM</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -61,26 +61,26 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-3" >
|
||||
<a href="#" ng-click="$ctrl.sortBy('name')">Property</a>
|
||||
<span class="sortorder" ng-show="propertyName === 'name'"
|
||||
ng-class="{reverse: reverse}">
|
||||
|
||||
<a href="javascript:void(0)" ng-click="$ctrl.sortBy('name')">Property</a>
|
||||
<span class="sortorder" ng-show="$ctrl.propertyName === 'name'"
|
||||
ng-class="{reverse: $ctrl.reverse}">
|
||||
</span>
|
||||
</th>
|
||||
<th class="col-md-2" style="word-wrap: break-word;">
|
||||
<a ng-click="$ctrl.sortBy('value')">Value</a>
|
||||
<span class="sortorder" ng-show="propertyName === 'value'"
|
||||
ng-class="{reverse: reverse}"></span>
|
||||
<a href="javascript:void(0)" ng-click="$ctrl.sortBy('value')">Value</a>
|
||||
<span class="sortorder" ng-show="$ctrl.propertyName === 'value'"
|
||||
ng-class="{reverse: $ctrl.reverse}"></span>
|
||||
</th>
|
||||
<th class="col-md-7">
|
||||
<a href="#" ng-click="$ctrl.sortBy('description')">Description</a>
|
||||
<span class="sortorder" ng-show="propertyName === 'description'"
|
||||
<a href="javascript:void(0)" ng-click="$ctrl.sortBy('description')">Description</a>
|
||||
<span class="sortorder" ng-show="$ctrl.propertyName === 'description'"
|
||||
ng-class="{reverse: reverse}"></span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="config in $ctrl.configs | filter:$ctrl.tagFilter | filter:search | orderBy:propertyName:reverse">
|
||||
<tr
|
||||
ng-repeat="config in $ctrl.configs | filter:search | orderBy:$ctrl.propertyName:$ctrl.reverse">
|
||||
<td style="word-wrap: break-word;">{{config.name}}</td>
|
||||
<td style="word-wrap: break-word;">{{config.value}}</td>
|
||||
<td style="word-wrap: break-word;">{{config.description}}</td>
|
||||
|
Loading…
Reference in New Issue
Block a user