You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@storm.apache.org by bo...@apache.org on 2018/08/03 20:45:52 UTC
[03/36] storm git commit: STORM-1311: UI Migration from clj to java
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/js/visualization.js
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/js/visualization.js b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/js/visualization.js
new file mode 100644
index 0000000..ced984d
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/js/visualization.js
@@ -0,0 +1,367 @@
+/**
+ * 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.
+ */
+
+var visNS = {
+ // Update / refresh setting
+ shouldUpdate: true,
+ updateFreqMs: 30000,
+
+ // Holds our network
+ network: null,
+
+ // Holds nodes and edge definitions
+ nodes: new vis.DataSet(),
+ edges: new vis.DataSet(),
+
+ // References our visualization container element
+ networkContainer: null,
+
+ // Holds map of Sanitized Stream Id => Stream Id
+ availableStreamsHash: { },
+
+ // vis.js options
+ options: {
+ edges:{
+ arrows: {
+ to: {enabled: true, scaleFactor:1}
+ },
+ hoverWidth: 1.5,
+ shadow:{
+ enabled: true,
+ color: 'rgba(0,0,0,0.5)',
+ size:10,
+ x:5,
+ y:5
+ },
+ smooth: {
+ type: "continuous",
+ forceDirection: "none"
+ }
+ },
+ nodes: {
+ color: {
+ border: '#2B7CE9',
+ background: '#97C2FC',
+ highlight: {
+ border: '#2B7CE9',
+ background: '#D2E5FF'
+ },
+ hover: {
+ border: '#2B7CE9',
+ background: '#D2E5FF'
+ }
+ },
+ shadow:{
+ enabled: true,
+ color: 'rgba(0,0,0,0.5)',
+ size:10,
+ x:5,
+ y:5
+ },
+ },
+ physics:{
+ enabled: false
+ },
+ layout: {
+ randomSeed: 31337,
+ improvedLayout:true,
+ hierarchical: {
+ enabled: true,
+ levelSeparation: 150,
+ nodeSpacing: 300,
+ treeSpacing: 200,
+ blockShifting: true,
+ edgeMinimization: true,
+ parentCentralization: true,
+ direction: 'UD', // UD, DU, LR, RL
+ sortMethod: 'directed' // hubsize, directed
+ }
+ },
+ interaction: {
+ navigationButtons: false
+ }
+ }
+};
+
+function parseResponse(json) {
+ console.log("Updating network");
+ // parse json
+ for (var componentId in json) {
+ parseNode(json[componentId], componentId);
+ }
+
+ // Create network if it does not exist yet
+ if (visNS.network == null) {
+ createNetwork()
+ }
+}
+
+function createNetwork() {
+ var data = {
+ "nodes": visNS.nodes,
+ "edges": visNS.edges
+ };
+ // Create network
+ visNS.network = new vis.Network(visNS.networkContainer, data, visNS.options);
+
+ // Create event handlers
+ visNS.network.on("click", function (params) {
+ handleClickEvent(params);
+ });
+ visNS.network.on("deselectNode", function(params) {
+ handleNodeClickEvent(null);
+ });
+
+ // Then disable layout
+ visNS.network.setOptions({layout: {hierarchical: false } });
+}
+
+function handleClickEvent(params) {
+ if (params["nodes"].length == 1) {
+ handleNodeClickEvent(params["nodes"][0])
+ }
+}
+
+function handleNodeClickEvent(nodeId) {
+ // if nodeId is null, hide
+ if (nodeId == null) {
+ // Ensure slider is hidden
+ $("#bolt_slideout_inner").css("display", "none");
+ return;
+ }
+
+ // add new values
+ var nodeDetails = json[nodeId];
+ //console.log(nodeDetails);
+
+ // Prep the json slightly
+ nodeDetails[":id"] = nodeId;
+ nodeDetails[":inputs_length"] = nodeDetails[":inputs"].length;
+ nodeDetails[":stats_length"] = nodeDetails[":stats"].length;
+
+ // Conditionally link to component
+ for (x=0; x<nodeDetails[":inputs"].length; x++) {
+ var showLink = true;
+ if (nodeDetails[":inputs"][x][":component"].startsWith("__")) {
+ showLink = false;
+ }
+ nodeDetails[":inputs"][x][":show_link"] = showLink;
+ }
+
+ // Calculate uptime in a nice format.
+ for (x=0; x<nodeDetails[":stats"].length; x++) {
+ nodeDetails[":stats"][x][":uptime_str"] = secondsToString(nodeDetails[":stats"][x][":uptime_secs"]);
+ }
+
+ // Render and display template.
+ var template = $('#bolt_info_template').html();
+ var html = Mustache.to_html(template, nodeDetails);
+ $("#bolt-details").html(html);
+
+ // Ensure slider is viewable
+ $("#bolt_slideout_inner").css("display", "inline");
+ return;
+}
+
+function parseNode(nodeJson, nodeId) {
+ // Conditional hack for system components
+ if (isSystemComponent(nodeId)) {
+ nodeJson[":type"] = "system";
+ }
+
+ // Determine node color
+ var col = "#D2E5FF"
+ var selectedCol = "#97C2FC";
+ var shape = "dot"
+
+ if (nodeJson[":type"] === "bolt") {
+ // Determine color based on capacity
+ var cap = Math.min(nodeJson[":capacity"], 1);
+ var red = Math.floor(cap * 225) + 30;
+ var green = Math.floor(255 - red);
+ var blue = Math.floor(green/5);
+ col = "rgba(" + red + "," + green + "," + blue + ",1)"
+ selectedCol = "rgba(" + (red+2) + "," + (green) + "," + (green + 2) + ",1)"
+ }
+ if (nodeJson[":type"] === "spout") {
+ shape = "triangleDown";
+ col = "#D2E5FF";
+ selectedCol = "#97C2FC"
+ }
+ if (nodeJson[":type"] === "system") {
+ shape = "diamond";
+ col = "#ffe6cc";
+ selectedCol = "#ffc180";
+ }
+
+ // Generate title
+ var title = "<b>" + nodeId + "</b><br/>";
+ title += "Capacity: " + nodeJson[":capacity"] + "<br/>";
+ title += "Latency: " + nodeJson[":latency"]
+
+ // Construct the node
+ var node = {
+ "id": nodeId,
+ "label": nodeId,
+ "color": {
+ "background": col,
+ "highlight": {
+ "background": selectedCol
+ }
+ },
+ "shape": shape,
+ "shadow": {
+ "enabled": true
+ },
+ "title": title,
+ "size": 45
+ };
+
+ // Construct edges
+ for (var index in nodeJson[":inputs"]) {
+ var inputComponent = nodeJson[":inputs"][index];
+ parseEdge(inputComponent, nodeId);
+ }
+
+ if (node != null) {
+ visNS.nodes.update(node);
+ }
+}
+
+function isSystemComponent(nodeId) {
+ return nodeId.startsWith("__");
+}
+
+function parseEdge(edgeJson, sourceId) {
+ //console.log(edgeJson);
+
+ // Make this stream available
+ addAvailableStream(edgeJson[":stream"], edgeJson[":sani-stream"])
+
+ // Create a unique Id
+ var id = edgeJson[":component"] + ":" + sourceId + ":" + edgeJson[":sani-stream"];
+
+ // Determine if stream is enabled
+ if (!isStreamEnabled(edgeJson[":sani-stream"])) {
+ // Remove edge
+ visNS.edges.remove({ "id": id });
+ return
+ }
+
+ if (!visNS.edges.get(id)) {
+ visNS.edges.update({
+ "id": id,
+ "from": edgeJson[":component"],
+ "to": sourceId,
+ "label": edgeJson[":stream"],
+ "title": "From: " + edgeJson[":component"] + "<br>To: " + sourceId + "<br>Grouping: " + edgeJson[":grouping"]
+ });
+ }
+}
+
+function addAvailableStream(streamId, streamIdSanitized) {
+ // Create a master list of all streams
+ if (visNS.availableStreamsHash[streamIdSanitized] == null) {
+ visNS.availableStreamsHash[streamIdSanitized] = streamId;
+ updateAvailableStreams();
+ }
+}
+
+function updateAvailableStreams() {
+ var container = jQuery("#available-streams");
+ $.each(visNS.availableStreamsHash, function(streamIdSanitized, streamName) {
+ var entry = jQuery(container).find("#stream-" + streamIdSanitized)
+ if (entry.length == 0) {
+ var checked = "checked"
+ if (streamName.startsWith("__")) {
+ checked = ""
+ }
+ // Render template
+ var template = $('#stream_selector_template').html();
+ var html = Mustache.to_html(template, {"checked": checked, "streamName": streamName, "streamNameSanitized": streamIdSanitized});
+ container.append(html);
+
+ // keep list of streams in sorted order
+ jQuery("#available-streams li").sort(asc_sort).appendTo('#available-streams');
+ }
+ });
+}
+
+// Called when a stream's checkbox is selected/unselected.
+function checkStream(checkBox) {
+ // reload data
+ parseResponse(json);
+}
+
+// Redraws edges
+function redrawStreams() {
+ visNS.edges.forEach(function(edge) { visNS.edges.remove(edge); visNS.edges.add(edge); });
+}
+
+// Returns true if a stream is enabled
+function isStreamEnabled(streamIdSanitized) {
+ return jQuery("input#stream-" + streamIdSanitized).is(':checked')
+}
+
+var update = function() {
+ if(visNS.shouldUpdate) {
+ $.ajax({
+ url: "/api/v1/topology/"+$.url("?id")+"/visualization?sys="+$.url("?sys"),
+ success: function (data, status, jqXHR) {
+ json = data;
+ parseResponse(data);
+ setTimeout(update, visNS.updateFreqMs);
+ }
+ });
+ } else {
+ setTimeout(update, visNS.updateFreqMs);
+ }
+}
+
+function secondsToString(seconds) {
+ var numDays = Math.floor(seconds / 86400);
+ var numHours = Math.floor((seconds % 86400) / 3600);
+ var numMinutes = Math.floor(((seconds % 86400) % 3600) / 60);
+ var numSeconds = ((seconds % 86400) % 3600) % 60;
+
+ var returnStr = "";
+ if (numDays > 0) {
+ returnStr += numDays + " days ";
+ }
+ if (numHours > 0) {
+ returnStr += numHours + " hours ";
+ }
+ if (numMinutes > 0) {
+ returnStr += numMinutes + " mins ";
+ }
+ if (numSeconds > 0) {
+ returnStr += numSeconds + " seconds";
+ }
+ return returnStr;
+}
+
+// ascending sort
+function asc_sort(a, b){
+ return ($(b).text()) < ($(a).text()) ? 1 : -1;
+}
+
+$(document).ready(function() {
+ visNS.networkContainer = document.getElementById("mynetwork");
+ update();
+});
+
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/logviewer.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/logviewer.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/logviewer.html
new file mode 100644
index 0000000..fb60781
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/logviewer.html
@@ -0,0 +1,27 @@
+
+<html><head>
+ <!--
+ 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.
+ -->
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Storm Logviewer</title>
+</head>
+<body>
+<p>You have launched storm logviewer successfully. You can visit logs from Storm UI now.</p>
+
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/logviewer_search.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/logviewer_search.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/logviewer_search.html
new file mode 100644
index 0000000..5fb8870
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/logviewer_search.html
@@ -0,0 +1,72 @@
+<html><head>
+ <!--
+ 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.
+ -->
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Storm UI</title>
+<link href="/css/bootstrap-3.3.1.min.css" rel="stylesheet" type="text/css">
+<link href="/css/jquery.dataTables.1.10.4.min.css" rel="stylesheet" type="text/css">
+<link href="/css/dataTables.bootstrap.css" rel="stylesheet" type="text/css">
+<link href="/css/style.css?_ts=${packageTimestamp}" rel="stylesheet" type="text/css">
+<script src="/js/jquery-1.11.1.min.js" type="text/javascript"></script>
+<script src="/js/jquery.dataTables.1.10.4.min.js" type="text/javascript"></script>
+<script src="/js/jquery.cookies.2.2.0.min.js" type="text/javascript"></script>
+<script src="/js/jquery.mustache.js" type="text/javascript"></script>
+<script src="/js/bootstrap-3.3.1.min.js" type="text/javascript"></script>
+<script src="/js/jquery.blockUI.min.js" type="text/javascript"></script>
+<script src="/js/url.min.js" type="text/javascript"></script>
+<script src="/js/dataTables.bootstrap.min.js" type="text/javascript"></script>
+<script src="/js/script.js?_ts=${packageTimestamp}" type="text/javascript"></script>
+</head>
+<body>
+<div class="container-fluid">
+ <div class="row">
+ <div id="search-form"></div>
+ </div>
+ <div class="row">
+ <div id="result"></div>
+ </div>
+ <div>
+ <p id="page-rendered-at-timestamp"></p>
+ </div>
+</div>
+</body>
+<script>
+$(document).ready(function() {
+ var file = $.url("?file");
+ var search = $.url("?search");
+ var offset = $.url("?offset") || 0;
+ var isDaemon = $.url("?is-daemon") || "no";
+ file = decodeURIComponent(file);
+ search = decodeURIComponent(search);
+
+ getStatic("/templates/logviewer-search-page-template.html", function(template) {
+ $("#search-form").append(Mustache.render($(template).filter("#search-single-file").html(),{file: file, search: search, isDaemon: isDaemon}));
+
+ var result = $("#result");
+ var url = "/api/v1/search?file="+encodeURIComponent(file)+"&search-string="+search+"&start-byte-offset="+offset+"&is-daemon="+isDaemon;
+ $.getJSON(url,function(response,status,jqXHR) {
+ response.file = file;
+ result.append(Mustache.render($(template).filter("#logviewer-search-result-template").html(),response));
+ });
+ });
+ });
+
+getPageRenderedTimestamp("page-rendered-at-timestamp");
+
+</script>
+</html>
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/owner.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/owner.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/owner.html
new file mode 100644
index 0000000..1e8bd5f
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/owner.html
@@ -0,0 +1,211 @@
+<html>
+
+<head>
+ <!--
+ 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.
+ -->
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Storm UI</title>
+ <link href="/css/bootstrap-3.3.1.min.css" rel="stylesheet" type="text/css">
+ <link href="/css/jquery.dataTables.1.10.4.min.css" rel="stylesheet" type="text/css">
+ <link href="/css/dataTables.bootstrap.css" rel="stylesheet" type="text/css">
+ <link href="/css/jsonFormatter.min.css" rel="stylesheet" type="text/css">
+ <link href="/css/style.css?_ts=${packageTimestamp}" rel="stylesheet" type="text/css">
+ <script src="/js/jquery-1.11.1.min.js" type="text/javascript"></script>
+ <script src="/js/jquery.dataTables.1.10.4.min.js" type="text/javascript"></script>
+ <script src="/js/jquery.cookies.2.2.0.min.js" type="text/javascript"></script>
+ <script src="/js/jquery.mustache.js" type="text/javascript"></script>
+ <script src="/js/url.min.js" type="text/javascript"></script>
+ <script src="/js/bootstrap-3.3.1.min.js" type="text/javascript"></script>
+ <script src="/js/jquery.blockUI.min.js" type="text/javascript"></script>
+ <script src="/js/jsonFormatter.min.js" type="text/javascript"></script>
+ <script src="/js/script.js?_ts=${packageTimestamp}" type="text/javascript"></script>
+</head>
+
+<body>
+ <div class="warning" id="ras-warning-fixed-buffer">
+ <H1>This user's topologies are in danger of being unscheduled due to the owner's over-use of cluster resources.</H1>
+ <p>Please keep this user's resource consumption within guaranteed bounds to ensure topologies for this user will continue to run.</p>
+ </div>
+ <div class="warning" id="ras-warning-top-buffer"></div>
+ <div class="container-fluid">
+ <div class="row">
+ <div class="col-md-11">
+ <h1><a href="/">Storm UI</a></h1>
+ </div>
+ <div id="ui-user" class="col-md-1"></div>
+ </div>
+ <div class="row">
+ <div class="col-md-12" id="search-form">
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <h2>Owner Summary</h2>
+ <div id="owner-summary"></div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <h2 id="owner-resource-usage-summary-header">Owner Resource Usage</h2>
+ <div id="owner-resource-usage-summary"></div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <h2 id="owner-resource-guarantee-summary-header">Owner Resource Guarantees (RAS Topologies Only)</h2>
+ <div id="owner-resource-guarantee-summary"></div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <h2>Owner Topologies</h2>
+ <div id="topology-summary"></div>
+ </div>
+ </div>
+ <div class="row">
+ <div id="json-response-error" class="col-md-12"></div>
+ </div>
+ <div>
+ <p id="page-rendered-at-timestamp"></p>
+ </div>
+</div>
+</body>
+<script>
+ $(document).ajaxStop($.unblockUI);
+ $(document).ajaxStart(function() {
+ $.blockUI({
+ message: '<img src="images/spinner.gif" /> <h3>Loading summary...</h3>'
+ });
+ });
+ $(document).ready(function() {
+
+ var owner = $.url("?id");
+ if (!owner) {
+ // this page is designed to be per owner, handle the case where the URL is malformed
+ getStatic("/templates/json-error-template.html", function(template) {
+ $("#json-response-error").append(Mustache.render($(template).filter("#json-error-template").html(), {
+ "error": "Invalid owner",
+ "errorMessage": "Please pass an owner id with the id URL parameter"
+ }));
+ });
+ return;
+ }
+ var url = "/api/v1/owner-resources/" + owner;
+
+ $.extend($.fn.dataTable.defaults, {
+ stateSave: true,
+ lengthMenu: [
+ [20, 40, 60, 100, -1],
+ [20, 40, 60, 100, "All"]
+ ],
+ pageLength: 20
+ });
+
+ $.ajaxSetup({
+ "error": function(jqXHR, textStatus, response) {
+ var errorJson = jQuery.parseJSON(jqXHR.responseText);
+ getStatic("/templates/json-error-template.html", function(template) {
+ $("#json-response-error").append(Mustache.render($(template).filter("#json-error-template").html(), errorJson));
+ });
+ }
+ });
+
+ function jsError(other) {
+ try {
+ other();
+ } catch (err) {
+ getStatic("/templates/json-error-template.html", function(template) {
+ $("#json-response-error").append(Mustache.render($(template).filter("#json-error-template").html(), {
+ error: "JS Error",
+ errorMessage: err
+ }));
+ });
+ }
+ }
+
+ var topologySummary = $("#topology-summary");
+ var ownerResourceUsage = $("#owner-resource-usage-summary");
+ var ownerSummary = $("#owner-summary");
+ var ownerResourceGuarantee = $("#owner-resource-guarantee-summary");
+ $.getJSON(url, function(response, status, jqXHR) {
+ getStatic("/templates/owner-page-template.html", function(template) {
+ jsError(function() {
+ //owner,totalTopologies,totalTasks,totalExecutors,totalWorkers
+ ownerSummary.append(
+ Mustache.render($(template).filter("#owner-summary-template").html(), response));
+
+ //totalReqOnHeapMem,totalReqOffHeapMem,totalReqMem,totalReqCpu,totalAssignedOnHeapMem,totalAssignedOffHeapMem,totalAssignedMem,totalAssignedCpu
+ ownerResourceUsage.append(
+ Mustache.render($(template).filter("#owner-resource-usage-template").html(), response));
+ $('#owner-resource-usage-summary [data-toggle="tooltip"]').tooltip();
+
+ if (response["cpuGuarantee"] != "N/A" || response["memoryGuarantee"] != "N/A") {
+ ownerResourceGuarantee.append(
+ Mustache.render($(template).filter("#owner-resource-guarantee-template").html(), response));
+ $('#owner-resource-guarantee-summary [data-toggle="tooltip"]').tooltip();
+
+ $('#mem-guarantee-util').html(getResourceGuaranteeRemainingFormat("display", response["memoryGuaranteeRemaining"]));
+
+ $('#cpu-guarantee-util').html(getResourceGuaranteeRemainingFormat("display", response["cpuGuaranteeRemaining"]));
+
+ } else {
+ $('#owner-resource-guarantee-summary-header').hide();
+ $('#owner-resource-guarantee-summary').hide();
+ }
+
+ var displayResource = response["schedulerDisplayResource"];
+ if (!displayResource) {
+ $('#owner-resource-usage-summary-header').hide();
+ $('#owner-resource-usage-summary').hide();
+ $('#owner-resource-guarantee-summary-header').hide();
+ $('#owner-resource-guarantee-summary').hide();
+ }
+
+ if(response && (response["memoryGuaranteeRemaining"] < 0 || response["cpuGuaranteeRemaining"] < 0
+ || response["memoryGuaranteeRemaining"] == "N/A" || response["cpuGuaranteeRemaining"] == "N/A")) {
+ $(".warning").show();
+ } else {
+ $(".warning").hide();
+ }
+
+ $('#owner-resource-usage-summary [data-toggle="tooltip"]').tooltip();
+
+ topologySummary.append(
+ Mustache.render($(template).filter("#owner-topology-summary-template").html(), response));
+ //name, owner, status, uptime, num workers, num executors, num tasks, assigned total mem, assigned total cpu, scheduler info
+ dtAutoPage("#owner-topology-summary-table", {
+ columnDefs: [{
+ type: "num",
+ targets: [4, 5, 6, 7, 8]
+ }, {
+ type: "time-str",
+ targets: [3]
+ }]
+ });
+ $('#topology-summary [data-toggle="tooltip"]').tooltip();
+
+ });
+ });
+ });
+ });
+
+ getPageRenderedTimestamp("page-rendered-at-timestamp");
+
+</script>
+
+</html>
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/search_result.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/search_result.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/search_result.html
new file mode 100644
index 0000000..30f09e4
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/search_result.html
@@ -0,0 +1,108 @@
+<html><head>
+ <!--
+ 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.
+ -->
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Storm UI</title>
+<link href="/css/bootstrap-3.3.1.min.css" rel="stylesheet" type="text/css">
+<link href="/css/jquery.dataTables.1.10.4.min.css" rel="stylesheet" type="text/css">
+<link href="/css/dataTables.bootstrap.css" rel="stylesheet" type="text/css">
+<link href="/css/style.css?_ts=${packageTimestamp}" rel="stylesheet" type="text/css">
+<script src="/js/jquery-1.11.1.min.js" type="text/javascript"></script>
+<script src="/js/jquery.dataTables.1.10.4.min.js" type="text/javascript"></script>
+<script src="/js/jquery.cookies.2.2.0.min.js" type="text/javascript"></script>
+<script src="/js/jquery.mustache.js" type="text/javascript"></script>
+<script src="/js/bootstrap-3.3.1.min.js" type="text/javascript"></script>
+<script src="/js/jquery.blockUI.min.js" type="text/javascript"></script>
+<script src="/js/url.min.js" type="text/javascript"></script>
+<script src="/js/dataTables.bootstrap.min.js" type="text/javascript"></script>
+<script src="/js/script.js?_ts=${packageTimestamp}" type="text/javascript"></script>
+</head>
+<body>
+<div class="container-fluid">
+ <div class="row">
+ <div id="search-form"></div>
+ </div>
+ <div class="row">
+ <div id="result"></div>
+ </div>
+ <div>
+ <p id="page-rendered-at-timestamp"></p>
+ </div>
+</div>
+</body>
+<script>
+$(document).ready(function() {
+ var id = $.url("?id");
+ var search = $.url("?search");
+ var count = $.url("?count") || 2;
+ var searchArchived = $.url("?searchArchived") || "";
+
+ getStatic("/templates/search-result-page-template.html", function(template) {
+ $("#search-form").append(Mustache.render($(template).filter("#search-form-template").html(),{id: id, search: search, count: count, searchArchived: searchArchived}));
+
+ var result = $("#result");
+ $.getJSON("/api/v1/topology-workers/"+id, function(response,status,jqXHR) {
+ for (var index in response.hostPortList) {
+ var host = response.hostPortList[index].host;
+ var port = response.hostPortList[index].port;
+ var elemId = "search-results-"+host.replace(/\./g,"-")+"-"+port;
+ response.hostPortList[index].elemId = elemId;
+ }
+ result.append(Mustache.render($(template).filter("#search-result-files-template").html(),response));
+
+ var logviewerPort = response.logviewerPort;
+ var logviewerScheme = response.logviewerScheme;
+ for (var index in response.hostPortList) {
+ var host = response.hostPortList[index].host;
+ var port = response.hostPortList[index].port;
+ var elemId = response.hostPortList[index].elemId;
+ var file = id+"/"+port+"/worker.log";
+ var searchURL = logviewerScheme + "://"+host+":"+logviewerPort+"/api/v1/search?file="+encodeURIComponent(file)+"&search-string="+search+"&num-matches="+count;
+ if (searchArchived != "") {
+ searchURL = logviewerScheme + "://"+host+":"+logviewerPort+"/api/v1/deepSearch/"+id+"?search-string="+search+"&num-matches="+count+"&search-archived=true&port="+port;
+ }
+
+ $.ajax({dataType: "json",
+ url: searchURL,
+ xhrFields: {
+ withCredentials: true
+ },
+ success: $.proxy(function(data,status,jqXHR) {
+ data.file = this.file;
+ data.host = this.host;
+ data.port = this.port;
+ data.id = id;
+ data.logviewerPort = logviewerPort;
+ data.logviewerScheme = logviewerScheme;
+ var searchTemp = $(template).filter("#search-result-identified-template").html();
+ if (searchArchived != "") {
+ searchTemp = $(template).filter("#deepsearch-result-identified-template").html();
+ }
+ var rendered = Mustache.render(searchTemp, data);
+ $("#"+this.elemId).replaceWith(rendered);
+ }, {host: host, port: port, file: file, elemId: elemId})
+ });
+ }
+ });
+ });
+ });
+
+ getPageRenderedTimestamp("page-rendered-at-timestamp");
+
+</script>
+</html>
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/supervisor.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/supervisor.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/supervisor.html
new file mode 100644
index 0000000..5489d5a
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/supervisor.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+ 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.
+-->
+
+<html><head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Storm UI</title>
+<link href="/css/bootstrap-3.3.1.min.css" rel="stylesheet" type="text/css">
+<link href="/css/jquery.dataTables.1.10.4.min.css" rel="stylesheet" type="text/css">
+<link href="/css/dataTables.bootstrap.css" rel="stylesheet" type="text/css">
+<link href="/css/jsonFormatter.min.css" rel="stylesheet" type="text/css">
+<link href="/css/style.css?_ts=${packageTimestamp}" rel="stylesheet" type="text/css">
+<script src="/js/jquery-1.11.1.min.js" type="text/javascript"></script>
+<script src="/js/jquery.dataTables.1.10.4.min.js" type="text/javascript"></script>
+<script src="/js/jquery.cookies.2.2.0.min.js" type="text/javascript"></script>
+<script src="/js/jquery.mustache.js" type="text/javascript"></script>
+<script src="/js/url.min.js" type="text/javascript"></script>
+<script src="/js/bootstrap-3.3.1.min.js" type="text/javascript"></script>
+<script src="/js/jquery.blockUI.min.js" type="text/javascript"></script>
+<script src="/js/jsonFormatter.min.js" type="text/javascript"></script>
+<script src="/js/script.js?_ts=${packageTimestamp}" type="text/javascript"></script>
+<script src="/js/dataTables.bootstrap.min.js" type="text/javascript"></script>
+</head>
+<body>
+<div class="supervisor-page container-fluid">
+ <div class="row">
+ <div class="col-md-11">
+ <h1><a href="/">Storm UI</a></h1>
+ </div>
+ <div id="ui-user" class="col-md-1"></div>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <h2>Supervisor summary</h2>
+ <div id="supervisor-summary"></div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <h2 id="worker-resources-header">Worker resources</h2>
+ <div id="worker-resources"></div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <span id="toggle-sys" style="display: block;" class="js-only"></span>
+ </div>
+ </div>
+ <div>
+ <p id="page-rendered-at-timestamp"></p>
+ </div>
+</div>
+</body>
+
+<script>
+
+$(document).ajaxStop($.unblockUI);
+$(document).ajaxStart(function(){
+ $.blockUI({ message: '<img src="images/spinner.gif" /> <h3>Loading summary...</h3>'});
+});
+$(document).ready(function() {
+ var supervisorId = $.url("?id");
+ var host = $.url("?host");
+ var windowParam = $.url("?window");
+ var sys = $.cookies.get("sys") || "false";
+ var url = "/api/v1/supervisor?" +
+ (supervisorId ? "id="+supervisorId : "host="+host)
+ + "&sys="+sys;
+ if(windowParam) url += "&window=" + windowParam;
+ $.extend( $.fn.dataTable.defaults, {
+ stateSave: true,
+ lengthMenu: [[20,40,60,100,-1], [20, 40, 60, 100, "All"]],
+ pageLength: 20
+ });
+
+ renderToggleSys($("#toggle-sys"));
+
+ var supervisorSummary = $("#supervisor-summary");
+ var workerStats = $("#worker-resources");
+
+ $.ajaxSetup({
+ "error":function(jqXHR,textStatus,response) {
+ var errorJson = jQuery.parseJSON(jqXHR.responseText);
+ getStatic("/templates/json-error-template.html", function(template) {
+ $("#json-response-error").append(Mustache.render($(template).filter("#json-error-template").html(),errorJson));
+ });
+ }
+ });
+ function jsError(other) {
+ try {
+ other();
+ } catch (err) {
+ getStatic("/templates/json-error-template.html", function(template) {
+ $("#json-response-error").append(Mustache.render($(template).filter("#json-error-template").html(),{error: "JS Error", errorMessage: err}));
+ });
+ }
+ }
+
+ $.getJSON(url,function(response,status,jqXHR) {
+ getStatic("/templates/supervisor-page-template.html", function(template) {
+ jsError(function() {
+ supervisorSummary.append(
+ Mustache.render($(template).filter("#supervisor-summary-template").html(),response));
+
+ //id, host, uptime, slots, used slots
+ dtAutoPage("#supervisor-summary-table", {
+ columnDefs: [
+ {type: "num", targets: [3, 4]},
+ {type: "time-str", targets: [2]}
+ ]
+ });
+
+ $('#supervisor-summary-table [data-toggle="tooltip"]').tooltip();
+ workerStats.append(Mustache.render($(template).filter("#worker-stats-template").html(),response));
+ makeSupervisorWorkerStatsTable(response, '#worker-stats-table', '#worker-resources');
+ });
+ });
+ });
+});
+
+getPageRenderedTimestamp("page-rendered-at-timestamp");
+
+</script>
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/component-page-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/component-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/component-page-template.html
new file mode 100644
index 0000000..c1f3a19
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/component-page-template.html
@@ -0,0 +1,591 @@
+<!--
+ 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.
+-->
+<script id="component-summary-template" type="text/html">
+ <h2>Component summary</h2>
+ <table class="table compact">
+ <thead>
+ <tr>
+ <th>
+ <span data-toggle="tooltip" data-placement="right" title="The ID assigned to a the Component by the Topology.">
+ Id
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The name given to the topology by when it was submitted. Click the name to view the Topology's information.">
+ Topology
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Executors are threads in a Worker process.">
+ Executors
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="A Task is an instance of a Bolt or Spout. The number of Tasks is almost always equal to the number of Executors.">
+ Tasks
+ </span>
+ </th>
+ {{#schedulerDisplayResource}}
+ <th>
+ <span data-toggle="tooltip" data-placement="above" title="The amount on heap memory in megabytes requested to run a single executor of this component.">
+ Requested On-heap Memory
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="above" title="The amount off heap memory in megabytes requested to run a single executor of this component.">
+ Requested Off-heap Memory
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="above" title="The amount of CPU resources requested to run a single executor of this component. Every 100 means 1 core.">
+ Requested CPU
+ </span>
+ </th>
+ {{/schedulerDisplayResource}}
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Click on the link below to open the logviewer and view the events emitted by this component.">
+ Debug
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{id}}</td>
+ <td><a href="/topology.html?id={{encodedTopologyId}}">{{name}}</a></td>
+ <td>{{executors}}</td>
+ <td>{{tasks}}</td>
+ {{#schedulerDisplayResource}}
+ <td>{{requestedMemOnHeap}}</td>
+ <td>{{requestedMemOffHeap}}</td>
+ <td>{{requestedCpu}}</td>
+ {{/schedulerDisplayResource}}
+ <td><a href="{{eventLogLink}}">events</a></td>
+ </tbody>
+ </table>
+</script>
+<script id="spout-stats-detail-template" type="text/html">
+ <h2>Spout stats</h2>
+ <table class="table table-striped compact" id="spout-stats-table">
+ <thead>
+ <tr>
+ <th class="header headerSortDown">
+ <span data-toggle="tooltip" data-placement="right" title="The past period of time for which the statistics apply. Click on a value to set the window for this page.">
+ Window
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted.">
+ Emitted
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of Tuples emitted that sent to one or more bolts." data-toggle="tooltip" data-placement="top">
+ Transferred
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The average time a Tuple "tree" takes to be completely processed by the Topology. A value of 0 is expected if no acking is done.">
+ Complete latency (ms)
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuple "trees" successfully processed. A value of 0 is expected if no acking is done.">
+ Acked
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of Tuple "trees" that were explicitly failed or timed out before acking was completed. A value of 0 is expected if no acking is done." data-toggle="tooltip" data-placement="left">
+ Failed
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#spoutSummary}}
+ <tr>
+ <td><a href="/component.html?id={{encodedId}}&topology_id={{encodedTopologyId}}&window={{window}}">{{windowPretty}}</a></td>
+ <td>{{emitted}}</td>
+ <td>{{transferred}}</td>
+ <td>{{completeLatency}}</td>
+ <td>{{acked}}</td>
+ <td>{{failed}}</td>
+ </tr>
+ {{/spoutSummary}}
+ </tbody>
+ </table>
+</script>
+<script id="output-stats-template" type="text/html">
+ <h2>Output stats ({{windowHint}})</h2>
+ <table class="table table-striped compact" id="output-stats-table">
+ <thead>
+ <tr>
+ <th class="header headerSortDown">
+ <span data-original-title="The name of the Tuple stream given in the Topolgy, or "default" if none was given." data-toggle="tooltip" data-placement="right">
+ Stream
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted.">
+ Emitted
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of Tuples emitted that sent to one or more bolts." data-toggle="tooltip" data-placement="top">
+ Transferred
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The average time a Tuple "tree" takes to be completely processed by the Topology. A value of 0 is expected if no acking is done." data-toggle="tooltip" data-placement="top">
+ Complete latency (ms)
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of Tuple "trees" successfully processed. A value of 0 is expected if no acking is done." data-toggle="tooltip" data-placement="top">
+ Acked
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of Tuple "trees" that were explicitly failed or timed out before acking was completed. A value of 0 is expected if no acking is done." data-toggle="tooltip" data-placement="left">
+ Failed
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#outputStats}}
+ <tr>
+ <td>{{stream}}</td>
+ <td>{{emitted}}</td>
+ <td>{{transferred}}</td>
+ <td>{{completeLatency}}</td>
+ <td>{{acked}}</td>
+ <td>{{failed}}</td>
+ </tr>
+ {{/outputStats}}
+ </tbody>
+ </table>
+</script>
+<script id="executor-stats-template" type="text/html">
+ <h2>Executors ({{windowHint}})</h2>
+ <table class="table table-striped compact" id="executor-stats-table">
+ <thead>
+ <tr>
+ <th class="header headerSortDown">
+ <span data-toggle="tooltip" data-placement="right" title="The unique executor ID.">
+ Id
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="right" title="The length of time an Executor (thread) has been alive.">
+ Uptime
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The hostname reported by the remote host. (Note that this hostname is not the result of a reverse lookup at the Nimbus node.)">
+ Host
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The port number used by the Worker to which an Executor is assigned. Click on the port number to open the logviewer page for this Worker." data-toggle="tooltip" data-placement="top">
+ Port
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="Select workers on which to perform actions. Selecting any row will automatically select all executors belonging to the same worker." data-toggle="tooltip" data-placement="top">
+ Actions
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of Tuples emitted." data-toggle="tooltip" data-placement="top">
+ Emitted
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted that sent to one or more bolts.">
+ Transferred
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The average time a Tuple "tree" takes to be completely processed by the Topology. A value of 0 is expected if no acking is done.">
+ Complete latency (ms)
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuple "trees" successfully processed. A value of 0 is expected if no acking is done.">
+ Acked
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of Tuple "trees" that were explicitly failed or timed out before acking was completed. A value of 0 is expected if no acking is done." data-toggle="tooltip" data-placement="left">
+ Failed
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#executorStats}}
+ <tr>
+ <td>{{id}}</td>
+ <td>{{uptime}}</td>
+ <td>{{host}}</td>
+ <td><a href="{{workerLogLink}}">{{port}}</a></td>
+ <td></td>
+ <td>{{emitted}}</td>
+ <td>{{transferred}}</td>
+ <td>{{completeLatency}}</td>
+ <td>{{acked}}</td>
+ <td>{{failed}}</td>
+ </tr>
+ {{/executorStats}}
+ </tbody>
+ </table>
+</script>
+<script id="profiling-template" type="text/html">
+ <h2>Profiling and Debugging</h2>
+ Use the following controls to profile and debug the components on this page.
+ <table class="table table-striped compact">
+ <thead>
+ <tr>
+ <th class="header">
+ <span data-original-title="The status of a running profiler or the timeout for one you're starting (in minutes)" data-toggle="tooltip">
+ Status / Timeout (Minutes)
+ </span>
+ </th>
+ <th class="header">Actions</th>
+ </tr>
+ </thead>
+ <tbody id="profiler-table-body">
+ <tr>
+ <td>
+ <input id="timeout" class="timeout_input" type="text" value="" placeholder="10"/>
+ </td>
+ <td>
+ <span id="workerActionButtons">
+ {{#profileActionEnabled}}
+ <input type="button" value="Start" name="start" onClick="start_profiling()" class="btn btn-secondary" disabled/>
+ {{/profileActionEnabled}}
+ <input type="button" value="JStack" name="jstack" onClick="dump_jstacks()" class="btn btn-secondary" disabled/>
+ <input type="button" value="Restart Worker" name="jvmrestart" onClick="restart_worker_jvms()" class="btn btn-secondary" disabled/>
+ <input type="button" value="Heap" name="heap" onClick="dump_heaps()" class="btn btn-secondary" disabled/>
+ </span>
+ </td>
+ </tr>
+ {{> profilerActive}}
+ </tbody>
+ </table>
+</script>
+<script id="profiler-active-partial" type="text/html">
+ {{#profilerActive}}
+ <tr>
+ <td>{{host}}:{{port}}<br/>Active until {{timestamp}}</td>
+ <td>
+ <input id="stop_{{host}}:{{port}}" type="button" value="Stop" name="stop" onClick="stop_profiling('{{host}}:{{port}}')" class="btn btn-secondary"/>
+ <input id="dump_profile_{{host}}:{{port}}" type="button" value="Dump Profile" name="dumpjprofile" onClick="dump_profile('{{host}}:{{port}}')" class="btn btn-secondary"/>
+ <input id="dump_jstack_{{host}}:{{port}}" type="button" value="JStack" name="jstack" onClick="dump_jstack('{{host}}:{{port}}')" class="btn btn-secondary"/>
+ <input id="restart_worker_jvm_{{host}}:{{port}}" type="button" value="Restart Worker" name="jvmrestart" onClick="restart_worker_jvms(['{{host}}:{{port}}'])" class="btn btn-secondary"/>
+ <input id="dump_heap_{{host}}:{{port}}" type="button" value="Heap" name="heap" onClick="dump_heap('{{host}}:{{port}}')" class="btn btn-secondary"/> <a href="{{dumplink}}">My Dump Files</a>
+ </td>
+ </tr>
+ {{/profilerActive}}
+</script>
+<script id="bolt-stats-template" type="text/html">
+ <h2>Bolt stats</h2>
+ <table class="table table-striped compact" id="bolt-stats-table">
+ <thead>
+ <tr>
+ <th class="header headerSortDown">
+ <span data-toggle="tooltip" data-placement="right" title="The past period of time for which the statistics apply. Click on a value to set the window for this page.">
+ Window
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted.">
+ Emitted
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted that sent to one or more bolts.">
+ Transferred
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The average time a Tuple spends in the execute method. The execute method may complete without sending an Ack for the tuple." data-toggle="tooltip" data-placement="top">
+ Execute latency (ms)
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of incoming Tuples processed.">
+ Executed
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The average time it takes to Ack a Tuple after it is first received. Bolts that join, aggregate or batch may not Ack a tuple until a number of other Tuples have been received." data-toggle="tooltip" data-placement="top">
+ Process latency (ms)
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of Tuples acknowledged by this Bolt." data-toggle="tooltip" data-placement="top">
+ Acked
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of tuples Failed by this Bolt." data-toggle="tooltip" data-placement="left">
+ Failed
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#boltStats}}
+ <tr>
+ <td><a href="/component.html?id={{encodedId}}&topology_id={{encodedTopologyId}}&window={{window}}">{{windowPretty}}</a></td>
+ <td>{{emitted}}</td>
+ <td>{{transferred}}</td>
+ <td>{{executeLatency}}</td>
+ <td>{{executed}}</td>
+ <td>{{processLatency}}</td>
+ <td>{{acked}}</td>
+ <td>{{failed}}</td>
+ </tr>
+ {{/boltStats}}
+ </tbody>
+ </table>
+</script>
+<script id="bolt-input-stats-template" type="text/html">
+ <h2>Input stats ({{windowHint}})</h2>
+ <table class="table table-striped compact" id="bolt-input-stats-table">
+ <thead>
+ <tr>
+ <th class="header headerSortDown">
+ <span data-toggle="tooltip" data-placement="right" title="The ID assigned to a the Component by the Topology.">
+ Component
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="right" title="The name of the Tuple stream given in the Topolgy, or "default" if none was given.">
+ Stream
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The average time a Tuple spends in the execute method. The execute method may complete without sending an Ack for the tuple.">
+ Execute latency (ms)
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of incoming Tuples processed.">
+ Executed
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The average time it takes to Ack a Tuple after it is first received. Bolts that join, aggregate or batch may not Ack a tuple until a number of other Tuples have been received." data-toggle="tooltip" data-placement="top">
+ Process latency (ms)
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples acknowledged by this Bolt.">
+ Acked
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of tuples Failed by this Bolt." data-toggle="tooltip" data-placement="left">
+ Failed
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#inputStats}}
+ <tr>
+ <td>{{component}}</td>
+ <td>{{stream}}</td>
+ <td>{{executeLatency}}</td>
+ <td>{{executed}}</td>
+ <td>{{processLatency}}</td>
+ <td>{{acked}}</td>
+ <td>{{failed}}</td>
+ </tr>
+ {{/inputStats}}
+ </tbody>
+ </table>
+</script>
+<script id="bolt-output-stats-template" type="text/html">
+ <h2>Output stats ({{windowHint}})</h2>
+ <table class="table table-striped compact" id="bolt-output-stats-table">
+ <thead>
+ <tr>
+ <th class="header headerSortDown">
+ <span data-toggle="tooltip" data-placement="right" title="The name of the Tuple stream given in the Topolgy, or "default" if none was given.">
+ Stream
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted.">
+ Emitted
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted that sent to one or more bolts.">
+ Transferred
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#outputStats}}
+ <tr>
+ <td>{{stream}}</td>
+ <td>{{emitted}}</td>
+ <td>{{transferred}}</td>
+ </tr>
+ {{/outputStats}}
+ </tbody>
+ </table>
+</script>
+<script id="bolt-executor-template" type="text/html">
+ <h2>Executors ({{windowHint}})</h2>
+ <table class="table table-striped compact" id="executor-stats-table">
+ <thead>
+ <tr>
+ <th class="header headerSortDown">
+ <span data-toggle="tooltip" data-placement="right" title="The unique executor ID.">
+ Id
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The length of time an Executor (thread) has been alive." data-toggle="tooltip" data-placement="right">
+ Uptime
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The hostname reported by the remote host. (Note that this hostname is not the result of a reverse lookup at the Nimbus node.)">
+ Host
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The port number used by the Worker to which an Executor is assigned. Click on the port number to open the logviewer page for this Worker.">
+ Port
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="Select workers on which to perform actions. Selecting any row will automatically select all executors belonging to the same worker." data-toggle="tooltip" data-placement="top">
+ Debug
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted.">
+ Emitted
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted that sent to one or more bolts.">
+ Transferred
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="If this is around 1.0, the corresponding Bolt is running as fast as it can, so you may want to increase the Bolt's parallelism. This is (number executed * average execute latency) / measurement time.">
+ Capacity (last 10m)
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The average time a Tuple spends in the execute method. The execute method may complete without sending an Ack for the tuple." data-toggle="tooltip" data-placement="top">
+ Execute latency (ms)
+ </span>
+ </th>
+ <th class="header">
+ <span data-toggle="tooltip" data-placement="top" title="The number of incoming Tuples processed.">
+ Executed
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The average time it takes to Ack a Tuple after it is first received. Bolts that join, aggregate or batch may not Ack a tuple until a number of other Tuples have been received." data-toggle="tooltip" data-placement="top">
+ Process latency (ms)
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of Tuples acknowledged by this Bolt." data-toggle="tooltip" data-placement="top">
+ Acked
+ </span>
+ </th>
+ <th class="header">
+ <span data-original-title="The number of tuples Failed by this Bolt." data-toggle="tooltip" data-placement="left">
+ Failed
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#executorStats}}
+ <tr>
+ <td>{{id}}</td>
+ <td>{{uptime}}</td>
+ <td>{{host}}</td>
+ <td><a href="{{workerLogLink}}">{{port}}</a></td>
+ <td></td>
+ <td>{{emitted}}</td>
+ <td>{{transferred}}</td>
+ <td>{{capacity}}</td>
+ <td>{{executeLatency}}</td>
+ <td>{{executed}}</td>
+ <td>{{processLatency}}</td>
+ <td>{{acked}}</td>
+ <td>{{failed}}</td>
+ </tr>
+ {{/executorStats}}
+ </tbody>
+ </table>
+</script>
+<script id="component-errors-template" type="text/html">
+ <h2>Errors</h2>
+ <table class="table table-striped compact" id="component-errors-table">
+ <thead>
+ <tr>
+ <th>Time</th>
+ <th>Error Host</th>
+ <th>Error Port</th>
+ <th>Error</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#componentErrors}}
+ <tr>
+ <td>
+ <span id="{{errorTime}}" class="errorTimeSpan">{{errorTime}}</span>
+ </td>
+ <td>{{errorHost}}</td>
+ <td><a href="{{errorWorkerLogLink}}">{{errorPort}}</a></td>
+ <td>
+ <span id="{{errorLapsedSecs}}" class="errorSpan">{{error}}</span>
+ </td>
+ </tr>
+ {{/componentErrors}}
+ </tbody>
+ </table>
+</script>
+<script id="component-actions-template" type="text/html">
+ <h2>Component actions</h2>
+ <p id="component-actions">
+ {{#loggersDisabled}}
+ <span style="display:inline-block;" data-toggle="tooltip" title="" data-original-title="To debug, set topology.eventlogger.executors to a value > 0">
+ {{/loggersDisabled}}
+ <input {{startDebugStatus}} onclick="confirmComponentAction('{{encodedTopologyId}}', '{{encodedId}}', '{{componentName}}', 'debug/enable', true, {{currentSamplingPct}}, 'sampling percentage', 'debug')" type="button" value="Debug" class="btn btn-default">
+ {{#loggersDisabled}}
+ </span>
+ {{/loggersDisabled}}
+ <input {{stopDebugStatus}} onclick="confirmComponentAction('{{encodedTopologyId}}', '{{encodedId}}', '{{componentName}}', 'debug/disable', false, 0, 'sampling percentage', 'stop debugging')" type="button" value="Stop Debug" class="btn btn-default">
+ </p>
+</script>
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/deep-search-result-page-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/deep-search-result-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/deep-search-result-page-template.html
new file mode 100644
index 0000000..e5146d8
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/deep-search-result-page-template.html
@@ -0,0 +1,72 @@
+<!--
+ 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.
+-->
+<script id="search-result-files-template" type="text/html">
+<table id="search-result-table" class="table table-striped compact">
+ <thead><tr><th>host:port</th><th>Match</th></tr></thead>
+ <tbody>
+ {{#supervisors}}
+ <tr id="{{elemId}}">
+ <td>{{host}}</td>
+ <td>LOADING ...</td>
+ </tr>
+ {{/supervisors}}
+ </tbody>
+</table>
+</script>
+<script id="search-result-identified-template" type="text/html">
+ {{#matches}}
+ <tr id="aResult">
+ <td><a href="{{logviewerScheme}}://{{host}}:{{logviewerPort}}/logviewer_search.html?file={{fileName}}&search={{searchString}}">{{host}}:{{port}}</a></td>
+ <td><pre>{{beforeString}}<b><a href="{{logviewerURL}}">{{matchString}}</a></b>{{afterString}}</pre></td>
+ </tr>
+ {{/matches}}
+ {{#resultNotFound}}
+ <tr id="noResult">
+ <td>Result Not Found</td>
+ <td></td>
+ </tr>
+ {{/resultNotFound}}
+</script>
+<script id="search-form-template" type="text/html">
+ <div id="search-form-container" class="search-box">
+ <form action="deep_search_result.html" id="search-box">
+ <div class="row" data-toggle="tooltip" data-placement="bottom" title="The ID of the topology, can be a regex for search, i.e. '.' lists everything">
+ <div class="col-md-2">Topology Id:</div>
+ <div class="col-md-10">
+ <input class="expand-box" id="search-id" name="id" class="typeahead" type="text" placeholder="Topology-ID" value="{{id}}" number="50">
+ </div>
+ </div>
+ <div class="row" data-toggle="tooltip" data-placement="bottom" title="Exact search string to look for (NOT A REGEX)">
+ <div class="col-md-2">Search:</div>
+ <div class="col-md-10">
+ <input class="expand-box" type="text" name="search" value="{{search}}" placeholder="Search" number="50">
+ </div>
+ </div>
+ <div class="row" data-toggle="tooltip" data-placement="bottom" title="Search older logs that have rotated and may have been compressed. This could take much longer.">
+ <div class="col-md-2">Search archived logs:</div>
+ <div class="col-md-10"><input type="checkbox" name="search-archived" {{search_archived}}></div>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <input type="submit" value="Search">
+ </td>
+ </div>
+ <input type="hidden" name="count" value="{{count}}">
+ </form>
+ </div>
+</script>
+
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/index-page-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/index-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/index-page-template.html
new file mode 100644
index 0000000..48658a9
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/index-page-template.html
@@ -0,0 +1,446 @@
+<!--
+ 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.
+-->
+<script id="cluster-summary-template" type="text/html">
+<table id="cluster-summary-table" class="table compact">
+ <thead>
+ <tr>
+ <th>
+ <span data-toggle="tooltip" data-placement="right" title="The version of storm installed on the UI node. (Hopefully, this is the same on all storm nodes!)">
+ Version
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The number of nodes in the cluster currently.">
+ Supervisors
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total number of Slots. Slots are Workers (processes).">
+ Used slots
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total number of Slots. Slots are Workers (processes).">
+ Free slots
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total number of Slots. Slots are Workers (processes).">
+ Total slots
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Executors are threads in a Worker process.">
+ Executors
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="A Task is an instance of a Bolt or Spout. The number of Tasks is almost always equal to the number of Executors.">
+ Tasks
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{stormVersion}}</td>
+ <td>{{supervisors}}</td>
+ <td>{{slotsUsed}}</td>
+ <td>{{slotsFree}}</td>
+ <td>{{slotsTotal}}</td>
+ <td>{{executorsTotal}}</td>
+ <td>{{tasksTotal}}</td>
+ </tr>
+ </tbody>
+</table>
+</script>
+
+<script id="nimbus-summary-template" type="text/html">
+ <table class="zebra-striped" id="nimbus-summary-table">
+ <thead>
+ <tr>
+ <th>
+ <span data-toggle="tooltip" data-placement="right" title="nimbus host name.">Host</span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Nimbus Thrift port number.">Port</span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Leader if this host is leader, Not a Leader for all other live hosts,
+ note that these hosts may or may not be in leader lock queue, and Dead for hosts that are part of nimbus.seeds list but are not alive.">Status</span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Storm version this nimbus host is running.">Version</span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="Time since this nimbus host has been running.">Uptime</span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#nimbuses}}
+ <tr>
+ <td>{{host}}</td>
+ <td><a href="{{nimbusLogLink}}">{{port}}</a></td>
+ <td>{{status}}</td>
+ <td>{{version}}</td>
+ <td>{{nimbusUpTime}}</td>
+ </tr>
+ {{/nimbuses}}
+ </tbody>
+ </table>
+</script>
+<script id="cluster-resources-template" type="text/html">
+ <table id="cluster-resources-table" class="table compact">
+ <thead>
+ <tr>
+ <th>
+ <span data-toggle="tooltip" data-placement="right" title="Total Available Memory in Cluster in MB.">
+ Total Memory (MB)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="right" title="Total Available Memory in Cluster in MB.">
+ Total Available Memory (MB)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="right" title="Total Fragmented Memory in Cluster in MB.">
+ Total Fragmented Memory (MB)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Percent Utilization of Memory Resources in Cluster.">
+ Memory Utilization (%)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total CPU Resources in Cluster. Every 100 means 1 core.">
+ Total CPU (%)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total Available CPU Resources in Cluster. Every 100 means 1 core.">
+ Available CPU (%)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total Fragmented CPU Resources in Cluster. Every 100 means 1 core.">
+ Fragmented CPU (%)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Percent Utilization of CPU Resources in Cluster.">
+ CPU Utilization (%)
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{totalMem}}</td>
+ <td>{{availMem}}</td>
+ <td>{{fragmentedMem}}</td>
+ <td>{{memAssignedPercentUtil}}</td>
+ <td>{{totalCpu}}</td>
+ <td>{{availCpu}}</td>
+ <td>{{fragmentedCpu}}</td>
+ <td>{{cpuAssignedPercentUtil}}</td>
+ </tr>
+ </tbody>
+ </table>
+</script>
+<script id="owner-summary-template" type="text/html">
+ <table class="table table-striped compact" id="owner-summary-table">
+ <thead>
+ <tr>
+ <th>
+ Owner
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total number of topologies owned by user.">
+ Total Topologies
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total number of executors used by user.">
+ Total Executors
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total number of workers used by user.">
+ Total Workers
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The amount of memory resource (in MB) used by user.">
+ Memory Usage (MB)
+ </span>
+ </th>
+ {{#schedulerDisplayResource}}
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The amount of memory resource (in MB) guaranteed to user.">
+ Memory Guarantee (MB)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The amount of guaranteed memory resources (in MB) remaining.">
+ Memory Guarantee Remaining (MB)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total CPU Resource Assigned on behalf of Owner. Every 100 means 1 core.">
+ CPU Usage (%)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The amount of CPU resource (every 100 means 1 core) guaranteed to user.">
+ CPU Guarantee (%)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The amount of guaranteed CPU resource (every 100 means 1 core) remaining.">
+ CPU Guarantee Remaining (%)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The amount of isolated nodes user may use">
+ Isolated Nodes Guarantee
+ </span>
+ </th>
+ {{/schedulerDisplayResource}}
+ </tr>
+ </thead>
+ <tbody>
+ </tbody>
+ </table>
+</script>
+<script id="topology-summary-template" type="text/html">
+ <table class="table table-striped compact" id="topology-summary-table">
+ <thead>
+ <tr>
+ <th>
+ <span data-toggle="tooltip" data-placement="right" title="The name given to the topology by when it was submitted. Click the name to view the Topology's information.">
+ Name
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The user that submitted the Topology, if authentication is enabled.">
+ Owner
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The status can be one of ACTIVE, INACTIVE, KILLED, or REBALANCING.">
+ Status
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The time since the Topology was submitted.">
+ Uptime
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The number of Workers (processes).">
+ Num workers
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Executors are threads in a Worker process.">
+ Num executors
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="A Task is an instance of a Bolt or Spout. The number of Tasks is almost always equal to the number of Executors.">
+ Num tasks
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Number of nimbus hosts on which this topology's code is replicated. ">
+ Replication count
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Assigned Total Memory by Scheduler.">
+ Assigned Mem (MB)
+ </span>
+ </th>
+ {{#schedulerDisplayResource}}
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Assigned Total CPU by Scheduler. Every 100 means 1 core.">
+ Assigned CPU (%)
+ </span>
+ </th>
+ {{/schedulerDisplayResource}}
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="This shows information from the scheduler about the latest attempt to schedule the Topology on the cluster.">
+ Scheduler Info
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="The version of this topology">
+ Topology Version
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="The version of the storm client that this topology request (was launched with)">
+ Storm Version
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#topologies}}
+ <tr>
+ <td><a href="/topology.html?id={{encodedId}}">{{name}}</a></td>
+ <td><a href="/owner.html?id={{owner}}">{{owner}}</a></td>
+ <td>{{status}}</td>
+ <td>{{uptime}}</td>
+ <td>{{workersTotal}}</td>
+ <td>{{executorsTotal}}</td>
+ <td>{{tasksTotal}}</td>
+ <td>{{replicationCount}}</td>
+ <td>{{assignedTotalMem}}</td>
+ {{#schedulerDisplayResource}}
+ <td>{{assignedCpu}}</td>
+ {{/schedulerDisplayResource}}
+ <td>{{schedulerInfo}}</td>
+ <td>{{topologyVersion}}</td>
+ <td>{{stormVersion}}</td>
+ </tr>
+ {{/topologies}}
+ </tbody>
+ </table>
+</script>
+<script id="supervisor-summary-template" type="text/html">
+<table class="table table-striped compact" id="supervisor-summary-table">
+ <thead>
+ <tr>
+ <th>
+ <span data-toggle="tooltip" data-placement="right" title="The hostname reported by the remote host. (Note that this hostname is not the result of a reverse lookup at the Nimbus node.)">
+ Host
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="A unique identifier given to a Supervisor when it joins the cluster.">
+ Id
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The length of time a Supervisor has been registered to the cluster.">
+ Uptime
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="Total number of Slots. Slots are Workers (processes).">
+ Slots
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="Total number of Slots. Slots are Workers (processes).">
+ Used slots
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="The number of Slots available. Slots are Workers (processes).">
+ Avail slots
+ </span>
+ </th>
+ {{#schedulerDisplayResource}}
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The total memory capacity of a supervisor in megabytes.">
+ Total Mem (MB)
+ </span>
+ </th>
+ {{/schedulerDisplayResource}}
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="The amount of memory that has been allocated in megabytes.">
+ Used Mem (MB)
+ </span>
+ </th>
+ {{#schedulerDisplayResource}}
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="The amount of Memory available in megabytes.">
+ Avail Mem (MB)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="top" title="The total CPU capacity of a supervisor. Every 100 means one core.">
+ Total CPU (%)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="The amount of CPU that has been allocated. Every 100 means one core.">
+ Used CPU (%)
+ </span>
+ </th>
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="The amount of CPU that is available. Every 100 means one core.">
+ Avail CPU (%)
+ </span>
+ </th>
+ {{/schedulerDisplayResource}}
+ <th>
+ <span data-toggle="tooltip" data-placement="left" title="Version">
+ Version
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#supervisors}}
+ <tr>
+ <td><a href="/supervisor.html?host={{host}}">{{host}}</a> (<a href="{{logLink}}" title="View log">log</a>)</td>
+ <td><a href="/supervisor.html?id={{id}}">{{id}}</a></td>
+ <td>{{uptime}}</td>
+ <td>{{slotsTotal}}</td>
+ <td>{{slotsUsed}}</td>
+ <td>{{slotsFree}}</td>
+ {{#schedulerDisplayResource}}
+ <td>{{totalMem}}</td>
+ {{/schedulerDisplayResource}}
+ <td>{{usedMem}}</td>
+ {{#schedulerDisplayResource}}
+ <td>{{availMem}}</td>
+ <td>{{totalCpu}}</td>
+ <td>{{usedCpu}}</td>
+ <td>{{availCpu}}</td>
+ {{/schedulerDisplayResource}}
+ <td>{{version}}</td>
+ </tr>
+ {{/supervisors}}
+ </tbody>
+</table>
+</script>
+
+<script id="configuration-template" type="text/html">
+ <table class="table table-striped compact" id="nimbus-configuration-table">
+ <thead>
+ <tr>
+ <th>Key</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#config}}
+ <tr>
+ <td>{{key}}</td>
+ <td>{{value}}</td>
+ </tr>
+ {{/config}}
+ </tbody>
+ </table>
+</script>
http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/json-error-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/json-error-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/json-error-template.html
new file mode 100644
index 0000000..f496cf8
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/json-error-template.html
@@ -0,0 +1,20 @@
+<!--
+ 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.
+-->
+<script id="json-error-template" type="text/html">
+<h2>{{error}}</h2>
+<pre>{{errorMessage}}</pre>
+</script>