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:51 UTC

[02/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/templates/logviewer-search-page-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/logviewer-search-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/logviewer-search-page-template.html
new file mode 100644
index 0000000..e132936
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/logviewer-search-page-template.html
@@ -0,0 +1,45 @@
+<!--
+ 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="logviewer-search-result-template" type="text/html">
+{{#nextByteOffset}}
+<a href="/logviewer_search.html?file={{file}}&search={{searchString}}&offset={{nextByteOffset}}&is-daemon={{isDaemon}}" class="btn btn-default enabled">Next</a>
+{{/nextByteOffset}}
+<table id="search-result-table" class="table table-striped compact">
+  <thead><tr><th>File offset</th><th>Match</th></tr></thead>
+  <tbody>
+    {{#matches}}
+    <tr>
+      <td>{{byteOffset}}</td>
+      <td><pre>{{beforeString}}<b><a href="{{logviewerURL}}">{{matchString}}</a></b>{{afterString}}</pre></td>
+    </tr>
+    {{/matches}}
+  </tbody>
+</table>
+{{#nextByteOffset}}
+<a href="/logviewer_search.html?file={{file}}&search={{searchString}}&offset={{nextByteOffset}}&is-daemon={{isDaemon}}" class="btn btn-default enabled">Next</a>
+{{/nextByteOffset}}
+</script>
+<script id="search-single-file" type="text/html">
+<form action="logviewer_search.html" id="search-box">
+  Search {{file}}:
+  <input type="text" name="search" value="{{search}}">
+  <input type="hidden" name="file" value="{{file}}">
+  <input type="hidden" name="is-daemon" value="{{isDaemon}}">
+  <input type="submit" value="Search">
+</form>
+</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/owner-page-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/owner-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/owner-page-template.html
new file mode 100644
index 0000000..f1320b6
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/owner-page-template.html
@@ -0,0 +1,239 @@
+<!--
+ 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="owner-summary-template" type="text/html">
+    <table id="owner-summary-table" class="table compact">
+        <thead>
+        <tr>
+            <th>
+                Owner
+            </th>
+            <th>
+                <span data-toggle="tooltip" data-placement="above" title="Total number of topologies owned by owner.">
+                    Total Topologies
+                </span>
+            </th>
+            <th>
+                <span data-toggle="tooltip" data-placement="above" title="Total number of tasks used by owner.">
+                    Total Tasks
+                </span>
+            </th>
+            <th>
+                <span data-toggle="tooltip" data-placement="above" title="Total number of executors used by owner.">
+                    Total Executors
+                </span>
+            </th>
+            <th>
+                <span data-toggle="tooltip" data-placement="above" title="Total number of workers used by owner.">
+                    Total Workers
+                </span>
+            </th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr>
+            <td>{{owner}}</td>
+            <td>{{totalTopologies}}</td>
+            <td>{{totalTasks}}</td>
+            <td>{{totalExecutors}}</td>
+            <td>{{totalWorkers}}</td>
+        </tr>
+        </tbody>
+    </table>
+</script>
+
+<script id="owner-resource-usage-template" type="text/html">
+    <table id="owner-resource-usage-table" class="table compact">
+        <thead>
+        <tr>
+            <th>
+            </th>
+            <th>
+                On-Heap Mem (MB)
+            </th>
+            <th>
+                Off-Heap Mem (MB)
+            </th>
+            <th>
+                Total Mem (MB)
+            </th>
+            <th>
+                <span data-toggle="tooltip" data-placement="top" title="Total CPU Resource. Every 100 means 1 core.">
+                    Total CPU (%)
+                </span>
+            </th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr>
+            <td>Requested</td>
+            <td>{{totalReqOnHeapMem}}</td>
+            <td>{{totalReqOffHeapMem}}</td>
+            <td>{{totalReqMem}}</td>
+            <td>{{totalReqCpu}}</td>
+        </tr>
+        <tr>
+            <td>Assigned</td>
+            <td>{{totalAssignedOnHeapMem}}</td>
+            <td>{{totalAssignedOffHeapMem}}</td>
+            <td>{{totalMemoryUsage}}</td>
+            <td>{{totalCpuUsage}}</td>
+        </tr>
+        </tbody>
+    </table>
+</script>
+
+<script id="owner-resource-guarantee-template" type="text/html">
+    <table id="owner-resource-guarantee-table" class="table compact">
+        <thead>
+        <tr>
+            <th>
+                <span data-toggle="tooltip" data-placement="top" title="The amount of CPU resource (every 100 means 1 core) guaranteed to owner.">
+                    CPU Guarantee (%)
+                </span>
+            </th>
+            <th>
+                <span data-toggle="tooltip" data-placement="top" title="The amount of CPU resource (every 100 means 1 core) used by owner.">
+                    CPU Usage (%)
+                </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>
+        </tr>
+        </thead>
+        <tbody>
+        <tr>
+            <td>{{cpuGuarantee}}</td>
+            <td>{{totalCpuUsage}}</td>
+            <td id="cpu-guarantee-util">{{cpuGuaranteeRemaining}}</td>
+        </tr>
+        </tbody>
+        <thead>
+        <tr>
+            <th>
+                <span data-toggle="tooltip" data-placement="top" title="The amount of memory resource (in MB) guaranteed to owner.">
+                    Memory Guarantee (MB)
+                </span>
+            </th>
+            <th>
+                <span data-toggle="tooltip" data-placement="top" title="The amount of memory resource (in MB) used by owner.">
+                    Memory Usage (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>
+        </tr>
+        </thead>
+        <tbody>
+        <tr>
+            <td>{{memoryGuarantee}}</td>
+            <td>{{totalMemoryUsage}}</td>
+            <td id="mem-guarantee-util">{{memoryGuaranteeRemaining}}</td>
+        </tr>
+        </tbody>
+    </table>
+</script>
+
+<script id="owner-topology-summary-template" type="text/html">
+    <table id="owner-topology-summary-table" class="table table-striped compact">
+        <thead>
+        <tr>
+            <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.">
+                    Name
+                </span>
+            </th>
+            <th>
+                <span data-toggle="tooltip" data-placement="top" title="The owner 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="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>
+        </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>{{assignedTotalMem}}</td>
+            {{#schedulerDisplayResource}}
+            <td>{{assignedCpu}}</td>
+            {{/schedulerDisplayResource}}
+            <td>{{schedulerInfo}}</td>
+            <td>{{topologyVersion}}</td>
+        </tr>
+        {{/topologies}}
+        </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/search-result-page-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/search-result-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/search-result-page-template.html
new file mode 100644
index 0000000..4376408
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/search-result-page-template.html
@@ -0,0 +1,60 @@
+<!--
+ 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>
+    {{#hostPortList}}
+      <tr id="{{elemId}}">
+        <td>{{host}}:{{port}}</td>
+        <td>LOADING ...</td>
+      </tr>
+    {{/hostPortList}}
+  </tbody>
+</table>
+</script>
+<script id="search-result-identified-template" type="text/html">
+    {{#matches}}
+    <tr>
+      <td><a href="{{logviewerScheme}}://{{host}}:{{logviewerPort}}/logviewer_search.html?file={{file}}&search={{searchString}}">{{host}}:{{port}}</a></td>
+      <td><pre>{{beforeString}}<b><a href="{{logviewerURL}}">{{matchString}}</a></b>{{afterString}}</pre></td>
+    </tr>
+    {{/matches}}
+</script>
+<script id="deepsearch-result-identified-template" type="text/html">
+    {{#matches}}
+    {{#matches}}
+    <tr>
+      <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}}
+    {{/matches}}
+</script>
+<script id="search-form-template" type="text/html">
+  <div class="search-box">
+    <form action="search_result.html" id="search-box">
+      Search {{id}}:
+      <input type="text" name="search" value="{{search}}">
+      <input type="hidden" name="id" value="{{id}}">
+      <input type="hidden" name="count" value="{{count}}">
+      <input type="submit" value="Search">
+      Search Archived Logs: <input type="checkbox" name="searchArchived" value="checked" {{searchArchived}}>
+    </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/supervisor-page-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/supervisor-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/supervisor-page-template.html
new file mode 100644
index 0000000..6fa79c6
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/supervisor-page-template.html
@@ -0,0 +1,161 @@
+<!--
+ 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="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="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>
+            <span data-toggle="tooltip" data-placement="top" title="A unique identifier given to a Supervisor when it joins the cluster.">
+              Supervisor 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="Slots are Workers (processes).">
+              Slots
+            </span>
+          </th>
+          <th>
+            <span data-toggle="tooltip" data-placement="top" title="Slots are Workers (processes).">
+              Used slots
+            </span>
+          </th>
+          {{#schedulerDisplayResource}}
+          <th>
+            <span data-toggle="tooltip" data-placement="top" title="Memory capacity of a supervisor.">
+              Total Mem (MB)
+            </span>
+          </th>
+          {{/schedulerDisplayResource}}
+          <th>
+            <span data-toggle="tooltip" data-placement="top" title="Memory that has been allocated.">
+              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="CPU capacity of a supervisor. Every 100 means one core.">
+              Total CPU (%)
+            </span>
+          </th>
+          <th>
+            <span data-toggle="tooltip" data-placement="top" title="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="top" title="Version">
+              Version
+            </span>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+      {{#supervisors}}
+          <tr>
+            <td><a href="/supervisor.html?host={{host}}">{{host}} (<a href="{{logLink}}" title="View log">log</a>)</a></td>
+            <td><a href="/supervisor.html?id={{id}}">{{id}}</td>
+            <td>{{uptime}}</td>
+            <td>{{slotsTotal}}</td>
+            <td>{{slotsUsed}}</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="worker-stats-template" type="text/html">
+  <table class="table table-striped compact" id="worker-stats-table">
+    <thead>
+      <tr>
+        <th class="header headerSortDown">
+          <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 Name
+          </span>
+        </th>
+        <th class="header">
+          <span data-original-title="The hostname reported by the remote host. (Note that this hostname is not the result of a reverse lookup at the Nimbus node.)" data-toggle="tooltip" data-placement="top">
+            Host
+          </span>
+        </th>
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="The port number used by the Worker. Click on the port number to open the logviewer page for this Worker.">
+            Port 
+          </span>
+        </th>
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="The length of time a Worker has been alive.">
+            Uptime
+          </span>
+        </th>
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="The number of executors.">
+            Num executors
+          </span>
+        </th>
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="Assigned Total Memory by Scheduler.">
+            Assigned Mem (MB)
+          </span>
+        </th>
+        {{#schedulerDisplayResource}}
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="Assigned Total CPU by Scheduler. Every 100 means 1 core.">
+            Assigned CPU (%)
+          </span>
+        </th>
+        {{/schedulerDisplayResource}}
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="The components running in this worker and the number of tasks per component.">
+            Components
+          </span>
+        </th>
+    </tr></thead>
+    <tbody>
+    </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/topology-page-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/topology-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/topology-page-template.html
new file mode 100644
index 0000000..49cb314
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/topology-page-template.html
@@ -0,0 +1,700 @@
+<!--
+ 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="topology-summary-template" type="text/html">
+  <table id="topology-summary-table" class="table compact">
+    <thead>
+      <tr>
+        <th>
+          <span data-toggle="tooltip" data-placement="right" title="The name given to the topology by when it was submitted.">
+            Name
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="right" title="The unique ID given to a Topology each time it is launched.">
+            Id
+          </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>
+      <tr>
+        <td>{{name}}</td>
+        <td>{{id}}</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>
+    </tbody>
+  </table>
+</script>
+<script id="topology-resources-template" type="text/html">
+  <table id="topology-resources-table" class="table compact">
+    <thead>
+      <tr>
+        <th>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="On-Heap memory that is not shared between executors">
+            Not Shared On-Heap Mem (MB)
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="On-Heap memory that is shared between executors">
+            Shared On-Heap Mem (MB)
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="Off-Heap memory that is not shared between executors">
+            Not Shared Off-Heap Mem (MB)
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="Off-Heap memory that is shared between executors, either within a worker or between workers on a node">
+            Shared Off-Heap Mem (MB)
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="Total memory MB.  For requested only one copy of each shared region is included so assigned may be more than requested.">
+            Total Mem (MB)
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="Total CPU Resource. Every 100 means 1 core.">
+            Total CPU (%)
+          </span>
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td>Requested</td>
+        <td>{{requestedRegularOnHeapMem}}</td>
+        <td>{{requestedSharedOnHeapMem}}</td>
+        <td>{{requestedRegularOffHeapMem}}</td>
+        <td>{{requestedSharedOffHeapMem}}</td>
+        <td>{{requestedTotalMem}}</td>
+        <td>{{requestedCpu}}</td>
+      </tr>
+      <tr>
+        <td>Assigned</td>
+        <td>{{assignedRegularOnHeapMem}}</td>
+        <td>{{assignedSharedOnHeapMem}}</td>
+        <td>{{assignedRegularOffHeapMem}}</td>
+        <td>{{assignedSharedOffHeapMem}}</td>
+        <td>{{assignedTotalMem}}</td>
+        <td>{{assignedCpu}}</td>
+      </tr>
+    </tbody>
+  </table>
+</script>
+<script id="topology-stats-template" type="text/html">
+  <h2>Topology stats</h2>
+  <table class="table table-striped compact" id="topology-stats-table">
+    <thead>
+      <tr>
+        <th>
+          <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>
+          <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted.">
+            Emitted
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted that sent to one or more bolts.">
+            Transferred
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="The average time a Tuple &quot;tree&quot; 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>
+          <span data-toggle="tooltip" data-placement="top" title="The number of Tuple &quot;trees&quot; successfully processed. A value of 0 is expected if no acking is done.">
+            Acked
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="left" title="The number of Tuple &quot;trees&quot; that were explicitly failed or timed out before acking was completed. A value of 0 is expected if no acking is done.">
+            Failed
+          </span>
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      {{#topologyStats}}
+      <tr>
+        <td><a href="/topology.html?id={{encodedId}}&window={{window}}">{{windowPretty}}</td>
+        <td>{{emitted}}</td>
+        <td>{{transferred}}</td>
+        <td>{{completeLatency}}</td>
+        <td>{{acked}}</td>
+        <td>{{failed}}</td>
+      </tr>
+      {{/topologyStats}}
+    </tbody>
+  </table>
+</script>
+
+<script id="topology-kafka-spouts-lag-template" type="text/html">
+  <h2>Kafka Spouts Lag</h2>
+  <table class="table table-striped compact" id="topology-kafka-spouts-lag-table">
+    <thead>
+      <tr>
+        <th>
+          <span data-toggle="tooltip" data-placement="right" title="Kafka spout id">
+            Id
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="Topic">
+            Topic
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="Partition">
+            Partition
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="Latest Offset">
+            Latest Offset
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="Offset of last spout message successfully acked">
+            Spout Committed Offset
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="left" title="Lag">
+            Lag
+          </span>
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      {{#kafkaSpoutsLagResults}}
+      <tr>
+        <td>{{id}}</td>
+        <td>{{topic}}</td>
+        <td>{{partition}}</td>
+        <td>{{logHeadOffset}}</td>
+        <td>{{consumerCommittedOffset}}</td>
+        <td>{{lag}}</td>
+      </tr>
+      {{/kafkaSpoutsLagResults}}
+    </tbody>
+  </table>
+</script>
+
+<script id="topology-spouts-lag-error-template" type="text/html">
+  <h2>Topology spouts lag error</h2>
+  <table class="table table-striped compact" id="topology-spouts-lag-error-table">
+    <thead>
+      <tr>
+        <th>
+          <span data-toggle="tooltip" data-placement="right" title="Spout id">
+            Id
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="top" title="Type of spout">
+            Type
+          </span>
+        </th>
+        <th>
+          <span data-toggle="tooltip" data-placement="left" title="Message to denote the reason for failure to get the lag">
+            Message
+          </span>
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      {{#spoutsLagErrorResults}}
+      <tr>
+        <td>{{spoutId}}</td>
+        <td>{{spoutType}}</td>
+        <td>{{errorInfo}}</td>
+      </tr>
+      {{/spoutsLagErrorResults}}
+    </tbody>
+  </table>
+</script>
+
+<script id="topology-visualization-container-template" type="text/html">
+<iframe src="/visualize.html?id={{id}}&sys={{sys}}" width="100%" height="500px"></iframe>
+</script>
+
+<script id="topology-visualization-template" type="text/html">
+  <h2>Topology Visualization</h2>
+  <input type="button" id="show-hide-visualization" value="Show Visualization" class="btn btn-default"/>
+  <input type="button" id="open-visualization" value="Open Visualization" class="btn btn-default"/>
+  <p>
+    <div id="visualization-container" style="display:none;">
+    </div>
+  </p>
+</script>
+
+<script id="topology-configuration-template" type="text/html">
+  <h2>Topology Configuration</h2>
+  <table class="table table-striped compact" id="topology-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>
+<script id="spout-stats-template" type="text/html">
+  <h2>Spouts ({{windowHint}})</h2>
+  <table class="table table-striped compact" id="spout-stats-table">
+    <thead>
+      <tr>
+        <th class="header headerSortDown">
+          <span data-original-title="The ID assigned to a the Component by the Topology. Click on the name to view the Component's page." data-toggle="tooltip" data-placement="right">
+            Id
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-original-title="Executors are threads in a Worker process." data-toggle="tooltip" data-placement="right">
+            Executors
+          </span>
+        </th>
+        <th class="header table-num">
+          <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 class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The amount of on-heap memory in megabytes requested to run a single executor of this component.">
+            Req On-heap Mem (MB)
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The amount of off-heap memory in megabytes requested to run a single executor of this component.">
+            Req Off-heap Mem (MB)
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The amount of CPU resources requested to run a single executor of this component. Every 100 means 1 core.">
+            Req CPU
+          </span>
+        </th>
+        {{/schedulerDisplayResource}}
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted.">
+            Emitted
+          </span>
+        </th>
+        <th class="header table-num">
+          <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 table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The average time a Tuple &quot;tree&quot; 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 table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The number of Tuple &quot;trees&quot; successfully processed. A value of 0 is expected if no acking is done.">
+            Acked
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The number of Tuple &quot;trees&quot; that were explicitly failed or timed out before acking was completed. A value of 0 is expected if no acking is done.">
+            Failed
+          </span>
+        </th>
+        <th class="header">Error Host</th>
+        <th class="header">Error Port</th>
+        <th class="header">Last error</th>
+        <th class="header">Error Time</th>
+      </tr>
+    </thead>
+    <tbody>
+      {{#spouts}}
+      <tr>
+        <td><a href="/component.html?id={{encodedSpoutId}}&topology_id={{encodedId}}">{{spoutId}}</a></td>
+        <td>{{executors}}</td>
+        <td>{{tasks}}</td>
+        {{#schedulerDisplayResource}}
+        <td>{{requestedMemOnHeap}}</td>
+        <td>{{requestedMemOffHeap}}</td>
+        <td>{{requestedCpu}}</td>
+        {{/schedulerDisplayResource}}
+        <td>{{emitted}}</td>
+        <td>{{transferred}}</td>
+        <td>{{completeLatency}}</td>
+        <td>{{acked}}</td>
+        <td>{{failed}}</td>
+        <td>{{errorHost}}</td>
+        <td><a href="{{errorWorkerLogLink}}">{{errorPort}}</a></td>
+        <td>
+          <span id="{{errorLapsedSecs}}" class="errorSpan">{{lastError}}</span>
+        </td>
+        <td>
+          {{#errorTime}}
+          <span id="{{errorTime}}" class="errorTime" data-toggle="tooltip" title="{{errorLapsedSecs}}">{{errorTime}}</span>
+          {{/errorTime}}
+        </td>
+        {{/spouts}}
+    </tbody>
+  </table>
+</script>
+<script id="bolt-stats-template" type="text/html">
+  <h2>Bolts ({{windowHint}})</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 ID assigned to a the Component by the Topology. Click on the name to view the Component's page.">
+            Id
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-original-title="Executors are threads in a Worker process." data-toggle="tooltip" data-placement="right">
+            Executors
+          </span>
+        </th>
+        <th class="header table-num">
+          <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 class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The amount of on-heap memory in megabytes requested to run a single executor of this component.">
+            Req On-heap Mem (MB)
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The amount of off-heap memory in megabytes requested to run a single executor of this component.">
+            Req Off-heap Mem (MB)
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The amount of CPU resources requested to run a single executor of this component. Every 100 means 1 core.">
+            Req CPU
+          </span>
+        </th>
+        {{/schedulerDisplayResource}}
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The number of Tuples emitted.">
+            Emitted
+          </span>
+        </th>
+        <th class="header table-num">
+          <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 table-num">
+          <span data-original-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." data-toggle="tooltip" data-placement="top">
+            Capacity (last 10m)
+          </span>
+        </th>
+        <th class="header table-num">
+          <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 table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The number of incoming Tuples processed.">
+            Executed
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" 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.">
+            Process latency (ms)
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="top" title="The number of Tuples acknowledged by this Bolt.">
+            Acked
+          </span>
+        </th>
+        <th class="header table-num">
+          <span data-toggle="tooltip" data-placement="left" title="The number of tuples Failed by this Bolt.">
+            Failed
+          </span>
+        </th>
+        <th class="header">Error Host</th>
+        <th class="header">Error Port</th>
+        <th class="header">Last error</th>
+        <th class="header">Error Time</th>
+    </tr></thead>
+    <tbody>
+      {{#bolts}}
+      <tr>
+        <td><a href="/component.html?id={{encodedBoltId}}&topology_id={{encodedId}}">{{boltId}}</a></td>
+        <td>{{executors}}</td>
+        <td>{{tasks}}</td>
+        {{#schedulerDisplayResource}}
+        <td>{{requestedMemOnHeap}}</td>
+        <td>{{requestedMemOffHeap}}</td>
+        <td>{{requestedCpu}}</td>
+        {{/schedulerDisplayResource}}
+        <td>{{emitted}}</td>
+        <td>{{transferred}}</td>
+        <td>{{capacity}}</td>
+        <td>{{executeLatency}}</td>
+        <td>{{executed}}</td>
+        <td>{{processLatency}}</td>
+        <td>{{acked}}</td>
+        <td>{{failed}}</td>
+        <td>{{errorHost}}</td>
+        <td><a href="{{errorWorkerLogLink}}">{{errorPort}}</a></td>
+        <td>
+          <span id="{{errorLapsedSecs}}" class="errorSpan">{{lastError}}</span>
+        </td>
+        <td>
+          {{#errorTime}}
+          <span id="{{errorTime}}" class="errorTime" data-toggle="tooltip" title="{{errorLapsedSecs}}">{{errorTime}}</span>
+          {{/errorTime}}
+        </td>
+        {{/bolts}}
+    </tbody>
+</script>
+<script id="worker-stats-template" type="text/html">
+  <h2>Worker Resources</h2>
+  <table class="table table-striped compact" id="worker-stats-table">
+    <thead>
+      <tr>
+        <th class="header headerSortDown">
+          <span data-original-title="The hostname reported by the remote host. (Note that this hostname is not the result of a reverse lookup at the Nimbus node.)" data-toggle="tooltip" data-placement="top">
+            Host
+          </span>
+        </th>
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="A unique identifier given to a Supervisor when it joins the cluster.">
+            Supervisor Id
+          </span>
+        </th>
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="The port number used by the Worker. Click on the port number to open the logviewer page for this Worker.">
+            Port 
+          </span>
+        </th>
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="The length of time a Worker has been alive.">
+            Uptime
+          </span>
+        </th>
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="The number of executors">
+            Num executors
+          </span>
+        </th>
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="Assigned Total Memory by Scheduler.">
+            Assigned Mem (MB)
+          </span>
+        </th>
+        {{#schedulerDisplayResource}}
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="Assigned Total CPU by Scheduler. Every 100 means 1 core.">
+            Assigned CPU (%)
+          </span>
+        </th>
+        {{/schedulerDisplayResource}}
+        <th class="header">
+          <span data-toggle="tooltip" data-placement="top" title="The components running in this worker and the number of tasks per component.">
+            Components
+          </span>
+        </th>
+    </tr></thead>
+    <tbody>
+    </tbody>
+</script>
+<script id="topology-actions-template" type="text/html">
+  <h2>Topology actions</h2>
+  <p id="topology-actions">
+    <input {{activateStatus}} onclick="confirmAction('{{encodedId}}', '{{name}}', 'activate', false)" type="button" value="Activate" class="btn btn-default">
+    <input {{deactivateStatus}} onclick="confirmAction('{{encodedId}}', '{{name}}', 'deactivate', false)" type="button" value="Deactivate" class="btn btn-default">
+    <input {{rebalanceStatus}} onclick="confirmAction('{{encodedId}}', '{{name}}', 'rebalance', true, {{msgTimeout}}, 'wait time in seconds')" type="button" value="Rebalance" class="btn btn-default">
+    <input {{killStatus}} onclick="confirmAction('{{encodedId}}', '{{name}}', 'kill', true, 30, 'wait time in seconds')" type="button" value="Kill" class="btn btn-default">
+    {{#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="confirmAction('{{encodedId}}', '{{name}}', 'debug/enable', true, {{currentSamplingPct}}, 'sampling percentage', 'debug')" type="button" value="Debug" class="btn btn-default" >
+    {{#loggersDisabled}}
+    </span>
+    {{/loggersDisabled}}
+    <input {{stopDebugStatus}} onclick="confirmAction('{{encodedId}}', '{{name}}', 'debug/disable', false, 0, 'sampling percentage', 'stop debugging')" type="button" value="Stop Debug" class="btn btn-default">
+    <input type="button" {{logLevel}} value="Change Log Level" onclick="toggleChangeLogLevel()" class="btn btn-default">
+  </p>
+  <!-- 
+    Contents of topology-change-log-level-template will be added to the div below
+    once user clicks on "Change Log Level"
+  -->
+  <div id="change-log-level" style="display:none"></div>
+</script>
+
+<script id="search-form-template" type="text/html">
+  <form action="search_result.html" id="search-box">
+    Search {{id}}:
+    <input type="text" name="search">
+    <input type="hidden" name="id" value="{{id}}">
+    <input type="hidden" name="count" value="1">
+    <input type="submit" value="Search">
+    Search Archived Logs: <input type="checkbox" name="searchArchived" value="checked">
+  </form>
+</script>
+
+<script id="log-level-and-timeout" type="text/html" class="partials">
+    <tr id="logger-{{loggerId}}" class="{{cls}}">
+        {{#loggerName}}
+          <td>{{loggerName}}</td>
+          <input type="hidden" id="loggerName-{{loggerId}}" value="{{loggerName}}"/>
+          <input type="hidden" id="loggerRemove-{{loggerId}}" value="false"/>
+        {{/loggerName}}
+
+        {{#isNew}}
+          <td>
+            <input type="text" id="loggerName-{{loggerId}}" placeholder="com.your.organization.LoggerName"/>
+          </td>
+        {{/isNew}}
+
+        <td>
+            <select id="loggerLevel-{{loggerId}}">
+                {{#levels}} 
+                    <option value="{{name}}" {{levelSelected}}>{{name}}</option>
+                {{/levels}}
+            </select>
+        </td>
+        <td>
+            <input type="text" class="timeout_input" id="loggerTimeout-{{loggerId}}" placeholder="30" value="{{timeout}}"/> 
+        </td>
+        <td>
+            {{absoluteTimeout}}
+        </td>
+        <td>
+            {{#isNew}}
+                <input type="button" value="Add" name="clear" onClick='sendLoggerLevel({{loggerId}})' class="btn btn-secondary"/>
+            {{/isNew}}
+            {{#loggerName}}
+                <input type="button" value="Apply" name="clear" onClick='sendLoggerLevel({{loggerId}})' class="btn btn-secondary"/>
+                {{#canClear}}
+                    <input type="button" value="Clear" name="clear" onClick='clearLoggerLevel({{loggerId}})' class="btn btn-secondary"/>
+                {{/canClear}}
+            {{/loggerName}}
+        </td>
+    </tr>
+</script>
+
+<script id="topology-change-log-level-template" type="text/html">
+  <div id="change-log-level">
+      <h3>Change Log Level</h3>
+      Modify the logger levels for topology. Note that applying a setting restarts the timer in the workers. To configure the root logger, use the name ROOT. 
+      <table class="table table-striped compact">
+          <thead>
+              <tr>
+                  <th class="header">Logger</th>
+                  <th class="header">Level</th>
+                  <th class="header">Timeout (sec)</th>
+                  <th class="header">Expires at</th>
+                  <th class="header">Actions</th>
+              </tr>
+          </thead>
+      {{#loggers}}
+          {{ > log-level-and-timeout }}
+      {{/loggers}}
+      </table>
+  </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/user-template.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/user-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/user-template.html
new file mode 100644
index 0000000..853f0c9
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/user-template.html
@@ -0,0 +1,38 @@
+<!--
+ 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="user-template" type="text/html">
+ <div class="ui-user">
+     {{#central-log-url}}
+        <span data-toggle="tooltip" data-placement="bottom" data-original-title="Link to Central Logging">
+                <a href="{{central-log-url}}" target="_blank"><image src="/images/statistic.png" class="image_pre_format"/></a>
+        </span>
+      {{/central-log-url}}
+     {{#bugtracker-url}}
+        <span data-toggle="tooltip" data-placement="bottom" data-original-title="Submit BUG for Help and tracking the issue.">
+                <a href="{{bugtracker-url}}" target="_blank"><image src="/images/bug.png" class="image_pre_format"/></a>
+        </span>
+     {{/bugtracker-url}}
+     <span data-toggle="tooltip" data-placement="bottom" data-original-title="Search through all logs for any topology.">
+             <a href="/deep_search_result.html" target="_blank"><image src="/images/search.png" class="image_pre_format"/></a>
+     </span>
+     {{#user}}
+        <span data-toggle="tooltip" data-placement="bottom" data-original-title="This should be you.">
+                User: {{user}}
+        </span>
+     {{/user}}
+ </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/topology.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/topology.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/topology.html
new file mode 100644
index 0000000..0250242
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/topology.html
@@ -0,0 +1,463 @@
+<!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="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>Topology summary</h2>
+      <div id="topology-summary"></div>
+    </div>
+  </div>
+  <div class="row">
+      <div class="col-md-12">
+          <h2 id="topology-resources-header">Topology resources</h2>
+          <div id="topology-resources"></div>
+      </div>
+  </div>
+  <div class="row">
+    <div id="topology-actions" class="col-md-12"></div>
+  </div>
+  <div class="row">
+    <div id="topology-stats" class="col-md-12"></div>
+  </div>
+  <div class="row">
+    <div id="topology-spouts-lag" class="col-md-12"></div>
+  </div>
+  <div class="row">
+    <div id="spout-stats" class="col-md-12"></div>
+  </div>
+  <div class="row">
+    <div id="bolt-stats" class="col-md-12"></div>
+  </div>
+  <div class="row">
+    <div id="worker-stats" class="col-md-12"></div>
+  </div>
+  <div class="row">
+    <div id="topology-visualization" class="col-md-12"></div>
+  </div>
+  <div class="row">
+    <div id="topology-configuration" class="col-md-12"></div>
+  </div>
+  <div class="row">
+    <div class="col-md-12">
+      <p id="toggle-switch" style="display: block;" class="js-only"></p>
+    </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>
+
+var toggleChangeLogLevel;
+
+function closeChangeLogLevel (){
+    var container = $("#change-log-level");
+    container.hide();
+}
+
+function clearLoggerLevel(id){
+    $("#loggerRemove-" + id).val("true");
+    sendLoggerLevel(id);
+    $("#logger-" + id).remove();
+}
+
+function sendLoggerLevel(id){
+    var topologyId = $.url("?id");
+    var shouldRemove = $("#loggerRemove-" + id).val() === "true";
+    var level = $("#loggerLevel-" + id).val();
+    var timeout = parseInt($("#loggerTimeout-" + id).val());
+        timeout = isNaN(timeout) ? 0 : timeout;
+    var loggerName = $("#loggerName-" + id).val();
+    if (level === 'Pick Level'){
+        alert ('Please pick a valid log level');
+        return;
+    }
+    var levelBelowInfo = level === 'DEBUG';
+
+    if (!shouldRemove && levelBelowInfo && timeout <= 0){
+        timeout = parseInt (
+            prompt ("You must provide a timeout > 0 for DEBUG log level. What timeout would you like (secs)?", 30));
+        if (!timeout){
+            return;
+        }
+    }
+    var data = {};
+    var loggerSetting;
+
+    if (id === 0) {
+        data["namedLoggerLevels"] = {};
+        data["namedLoggerLevels"]["ROOT"] = {};
+        loggerSetting = data["namedLoggerLevels"]["ROOT"];
+    } else {
+        data["namedLoggerLevels"] = {};
+        data["namedLoggerLevels"][loggerName] = {};
+        loggerSetting = data["namedLoggerLevels"][loggerName];
+    }
+
+    loggerSetting.target_level = shouldRemove ? null : level;
+    loggerSetting.reset_level  = "INFO";
+    loggerSetting.timeout = timeout;
+
+    sendRequest (topologyId, "logconfig", null, data, toggleChangeLogLevel);
+};
+
+function renderLogLevelForm (template, responseData){
+    var topologyId = $.url("?id");
+    var container = $("#change-log-level");
+
+    var levels = [
+        {name: "Pick Level"},
+        {name: "ALL"},
+        {name: "TRACE"},
+        {name: "DEBUG"},
+        {name: "INFO" },
+        {name: "WARN" },
+        {name: "ERROR"},
+        {name: "FATAL"},
+        {name: "OFF"}
+    ];
+    var partialTemplates = $(template).filter('.partials');
+    var partials = {};
+
+    $.each(partialTemplates, function (ix, partial){
+        var obj = $(partial);
+        partials [obj.attr('id')] = obj.html(); 
+    });
+
+    var logLevelTemplate = $(template).filter("#topology-change-log-level-template").html();
+
+    var calcAbsoluteTimeout = function (timeout_epoch) {
+        var absoluteTimeout = "";
+        if (timeout_epoch) {
+            var d = new Date(0); 
+            d.setUTCSeconds(timeout_epoch / 1000);
+            absoluteTimeout = d.toLocaleDateString() + " " + d.toLocaleTimeString();
+        }
+        return absoluteTimeout;
+    };
+    var renderImpl = function (data){
+        var loggers = [];
+        var loggerCount = 1;
+        var obj = data.namedLoggerLevels;
+        if (!obj) {
+            obj = {};
+            data.namedLoggerLevels = obj;
+        }
+
+        var sortedLoggers = Object.keys(obj).sort(function (l1, l2){
+            if (l1 === "ROOT") return -1;
+            if (l2 === "ROOT") return 1;
+            return l1 > l2;
+        });
+
+        sortedLoggers.forEach (function (l){
+            var obj = data.namedLoggerLevels[l];
+            obj.loggerId = loggerCount++;
+            obj.loggerName = l;
+            obj.named = l != "ROOT";
+            obj.cls = "namedLoggers";
+            obj.levelSelected = function (obj){
+                return function (){
+                    return this.name === obj.target_level ? "selected" : "";
+                }
+            }(obj);
+            obj.absoluteTimeout = calcAbsoluteTimeout (obj.timeout_epoch);
+            obj.canClear = true;
+            loggers.push(obj);
+        });
+
+        loggers.push({
+            loggerId: loggerCount,
+            isNew: true,
+            cls: 'newLogger'
+        });
+
+        var tmplData = {
+            loggers: loggers,
+            levels: levels
+        };
+
+        container.html(Mustache.render(logLevelTemplate, tmplData, partials));
+        container.show('fast');
+    };
+    if (!responseData) {
+        var topologyId = $.url("?id");
+        $.get('/api/v1/topology/' + topologyId + '/logconfig', renderImpl);
+    } else {
+        renderImpl (responseData);
+    }
+} 
+$(document).ajaxStop($.unblockUI);
+$(document).ajaxStart(function(){
+    if ($("#topology-visualization").children().size() == 0) {
+        $.blockUI({ message: '<img src="images/spinner.gif" /> <h3>Loading topology summary...</h3>'});
+    }
+});
+$(document).ready(function() {
+    var topologyId = $.url("?id");
+    var tableStateKey = ":".concat(topologyId);
+    var window = $.url("?window");
+    var sys = $.cookies.get("sys") || "false";
+    var url = "/api/v1/topology/"+topologyId+"?sys="+sys;
+    if(window) url += "&window="+window;
+    $.getJSON("/api/v1/cluster/configuration",function(response,status,jqXHR) {
+        $.extend( $.fn.dataTable.defaults, {
+          stateSave: true,
+          stateSaveCallback: function (oSettings, oData) {
+            sessionStorage.setItem( oSettings.sTableId.concat(tableStateKey), JSON.stringify(oData) );
+          },
+          stateLoadCallback: function (oSettings) {
+            return JSON.parse( sessionStorage.getItem(oSettings.sTableId.concat(tableStateKey)) );
+          },
+          lengthMenu: [[20,40,60,100,-1], [20, 40, 60, 100, "All"]],
+          pageLength: response["ui.pagination"]
+        });
+    });
+
+    renderToggleSys($("#toggle-switch"));
+    $.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));
+            });
+        }
+    });
+
+    $.getJSON(url,function(response,status,jqXHR) {
+        var uiUser = $("#ui-user");
+        getStatic("/templates/user-template.html", function(template) {
+            uiUser.append(Mustache.render($(template).filter("#user-template").html(),response));
+            $('#ui-user [data-toggle="tooltip"]').tooltip();
+        });
+
+        var topologySummary = $("#topology-summary");
+        var topologyResources = $("#topology-resources");
+        var topologyStats = $("#topology-stats");
+        var topologySpoutsLag = $("#topology-spouts-lag");
+        var spoutStats = $("#spout-stats");
+        var boltStats = $("#bolt-stats");
+        var workerStats = $("#worker-stats");
+        var config = $("#topology-configuration");
+        var topologyActions = $("#topology-actions");
+        var topologyVisualization = $("#topology-visualization")
+        var searchForm = $("#search-form")
+        var formattedConfig = formatConfigData(response["configuration"]);
+        var buttonJsonData = topologyActionJson(response["id"],response["encodedId"],response["name"],response["status"]
+                                                ,response["msgTimeout"],response["configuration"]["topology.eventlogger.executors"],response["debug"],response["samplingPct"]);
+        $.ajax ({url: "/templates/topology-page-template.html", success: function(template) {
+            toggleChangeLogLevel = function (data) {
+              renderLogLevelForm (template, data);
+            }
+            searchForm.append(Mustache.render($(template).filter("#search-form-template").html(),{id: topologyId}));
+            topologySummary.append(Mustache.render($(template).filter("#topology-summary-template").html(),response));
+            topologyResources.append(Mustache.render($(template).filter("#topology-resources-template").html(),response));
+            var displayResource = response["schedulerDisplayResource"];
+            if (!displayResource){
+                $('#topology-resources-header').hide();
+                $('#topology-resources').hide();
+            }
+            topologyActions.append(Mustache.render($(template).filter("#topology-actions-template").html(),buttonJsonData));
+            topologyStats.append(Mustache.render($(template).filter("#topology-stats-template").html(),response));
+            //window, emitted, transferred, complete latency, acked, failed
+            $("#topology-stats-table").DataTable({
+              paging: false,
+              info: false,
+              searching: false,
+              columnDefs: [
+                {type: "num", targets: [1, 2, 3, 4, 5]},
+                {type: "time-str", targets: [0]}
+              ]
+            });
+
+            spoutStats.append(Mustache.render($(template).filter("#spout-stats-template").html(),response));
+            dtAutoPage("#spout-stats-table", {
+              columnDefs: [
+                {type: "num", targets: 'table-num'}
+              ]
+            });
+
+            boltStats.append(Mustache.render($(template).filter("#bolt-stats-template").html(),response));
+            dtAutoPage("#bolt-stats-table", {
+              columnDefs: [
+                {type: "num", targets: 'table-num'}
+              ]
+            });
+
+          jsError(function() {
+            workerStats.append(Mustache.render($(template).filter("#worker-stats-template").html(),response));
+            makeTopologyWorkerStatsTable (response, '#worker-stats-table', '#worker-stats');
+          });
+
+          jsError(function() {
+            topologyVisualization.append(Mustache.render($(template).filter("#topology-visualization-template").html(), response));
+            var sys = $.cookies.get("sys") || "false";
+            $("#show-hide-visualization").click(function () { show_visualization(sys) });
+            $("#open-visualization").click(function() { open_visualization(sys); });
+
+            config.append(Mustache.render($(template).filter("#topology-configuration-template").html(),formattedConfig));
+            $('#topology-configuration td').jsonFormatter()
+            //key, value
+            dtAutoPage("#topology-configuration-table", {});
+
+            var errorCells = document.getElementsByClassName("errorSpan");
+            for (i =0; i < errorCells.length; i++)
+            {
+              var timeLapsedInSecs = errorCells[i].id;
+              if (parseInt(timeLapsedInSecs) < 1800) {
+                errorCells[i].style.color = "#9d261d";
+                errorCells[i].style.borderBottomColor = "#9d261d";
+              }
+              errorCells[i].style.whiteSpace = "pre";
+            }
+            
+            var errorTime = document.getElementsByClassName("errorTime");
+            for (i=0; i < errorTime.length; i++)
+            {
+              if((errorTime[i].id))
+              {
+                var a = new Date(parseInt(errorTime[i].id) * 1000);
+                var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
+                var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
+                var year = a.getFullYear();
+                var month = months[a.getMonth()];
+                var date = a.getDate();
+                var hour = a.getHours();
+                var min = a.getMinutes();
+                var sec = a.getSeconds();
+                var day = days[a.getDay()];
+                if (hour < 10) {hour = "0"+hour;}
+                if (min  < 10) {min  = "0"+min;}
+                if (sec  < 10) {sec  = "0"+sec;}
+                var time = day + ', '+date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec;
+                
+                errorTime[i].innerHTML = time;
+                var sec_num = parseInt(errorTime[i].title, 10);
+                var hours   = Math.floor(sec_num / 3600);
+                var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
+                var seconds = sec_num - (hours * 3600) - (minutes * 60);
+                if (hours   < 10) {hours   = "0"+hours;}
+                if (minutes < 10) {minutes = "0"+minutes;}
+                if (seconds < 10) {seconds = "0"+seconds;}
+                var time    = hours+':'+minutes+':'+seconds;
+                errorTime[i].title = "Elapsed Time Since Error: " + time;
+              }
+            }
+            $('#topology-summary [data-toggle="tooltip"]').tooltip();
+            $('#topology-stats [data-toggle="tooltip"]').tooltip();
+            $('#spout-stats [data-toggle="tooltip"]').tooltip();
+            $('#bolt-stats [data-toggle="tooltip"]').tooltip();
+            $('#topology-configuration [data-toggle="tooltip"]').tooltip();
+            $('#topology-actions [data-toggle="tooltip"]').tooltip();
+            $('#topology-visualization [data-toggle="tooltip"]').tooltip();
+
+            var lagUrl = "/api/v1/topology/"+topologyId+"/lag";
+            $.getJSON(lagUrl,function(lagResponse,status,jqXHR) {
+                if (lagResponse !== null && lagResponse !== undefined) {
+                    var kafkaSpoutsLagTemplate = $(template).filter("#topology-kafka-spouts-lag-template").html();
+                    var spoutsErrorTemplate = $(template).filter("#topology-spouts-lag-error-template").html();
+
+                    var data = {};
+                    data.kafkaSpoutsLagResults = [];
+                    data.spoutsLagErrorResults = [];
+                    for (var spoutId in lagResponse) {
+                        var spout = lagResponse[spoutId];
+                        var spoutType = spout.spoutType;
+                        if (spoutType !== "KAFKA") {
+                            continue;
+                        }
+                        var spoutLagResult = spout.spoutLagResult;
+                        var errorInfo = spout.errorInfo;
+                        if (spoutLagResult !== undefined) {
+                            for (var topicName in spoutLagResult) {
+                                var topicLagResult = spoutLagResult[topicName];
+                                for (var partitionId in topicLagResult) {
+                                    var partitionLagResult = topicLagResult[partitionId];
+                                    data.kafkaSpoutsLagResults.push({
+                                        id: spoutId,
+                                        topic: topicName,
+                                        partition: partitionId,
+                                        logHeadOffset: partitionLagResult.logHeadOffset,
+                                        consumerCommittedOffset: partitionLagResult.consumerCommittedOffset,
+                                        lag: partitionLagResult.lag
+                                    });
+                                }
+                            }
+                        } else if (errorInfo !== undefined) {
+                            data.spoutsLagErrorResults.push({
+                                spoutId: spoutId,
+                                spoutType: spout.spoutType,
+                                errorInfo: errorInfo
+                            });
+                        }
+                    }
+
+                    if (data.kafkaSpoutsLagResults.length > 0) {
+                        topologySpoutsLag.append(Mustache.render(kafkaSpoutsLagTemplate, data));
+                    }
+                    if (data.spoutsLagErrorResults.length > 0) {
+                        topologySpoutsLag.append(Mustache.render(spoutsErrorTemplate, data));
+                    }
+                }
+            });
+          });
+      }});
+    });
+ });
+
+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/visualize.html
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/visualize.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/visualize.html
new file mode 100644
index 0000000..ec16544
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/visualize.html
@@ -0,0 +1,124 @@
+<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>Topology Visualization</title>
+    <link href="/css/bootstrap-3.3.1.min.css" rel="stylesheet" type="text/css">
+    <link href="/css/vis.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.mustache.js" type="text/javascript"></script>
+    <script src="/js/url.min.js" type="text/javascript"></script>
+    <script src="/js/vis.min.js" type="text/javascript"></script>
+    <script src="/js/visualization.js" type="text/javascript"></script>
+</head>
+<body>
+<div id="visualization">
+    <!-- Slide out for stream selection -->
+    <div id="streams_slideout">
+        <div id="streams_slideout_inner">
+            <img src="/images/streams.png" alt="Streams" style="float: right;"/>
+            <ul id="available-streams">
+            </ul>
+        </div>
+    </div>
+
+    <!-- Slide out for bolt stats -->
+    <div id="bolt_slideout">
+        <div id="bolt_slideout_inner">
+            <img src="/images/component.png" alt="Component Info" class="header" style="float: left;"/>
+            <ul id="bolt-details"></ul>
+        </div>
+    </div>
+
+    <div id="mynetwork"></div>
+
+    <!-- template for stream selector checkbox -->
+    <script id="stream_selector_template" type="text/template">
+        <li>
+            <label>
+                <input type="checkbox" id="stream-{{streamNameSanitized}}" class="stream_checkbox" onclick="checkStream(this);" {{checked}}>{{streamName}}
+            </label>
+        </li>
+    </script>
+
+    <!-- template for bolt info -->
+    <script id="bolt_info_template" type="text/template">
+        <!-- top level component details -->
+        <li>Id: <a href="{{:link}}" target="_blank">{{:id}}</a> &#x25F3;</li>
+        <li>Type: {{:type}}</li>
+        <li>Latency: {{:latency}} ms</li>
+        <li>Capacity: {{:capacity}}</li>
+        <li>Transferred: {{:transferred}}</li>
+
+        <!-- Inputs to Component -->
+        <li>
+            <details>
+                <summary>{{:inputs_length}} Inputs</summary>
+                <ul id="bolt-inputs">
+                    <!-- Start loop over inputs -->
+                    {{#:inputs}}
+                    <li>
+                        <details>
+                            <summary>
+                                {{#:show_link}}
+                                    <a href="#" onclick="network.selectNodes(['{{:component}}']); handleNodeClickEvent('{{:component}}'); return false;">{{:component}}</a>
+                                {{/:show_link}}
+                                {{^:show_link}}
+                                    {{:component}}
+                                {{/:show_link}}
+                            </summary>
+                            <ul>
+                                <li>Stream: {{:stream}}</li>
+                                <li>Grouping: {{:grouping}}</li>
+                            </ul>
+                        </details>
+                    </li>
+                    {{/:inputs}}
+                </ul>
+            </details>
+        </li>
+
+        <!-- Instance Details -->
+        <li>
+            <details>
+                <summary>
+                    {{:stats_length}} Instance(s)
+                </summary>
+                <ul id="bolt-instances">
+                    <!-- Start loop over instances -->
+                    {{#:stats}}
+                    <li>
+                        <details>
+                            <summary>
+                                {{:host}}:{{:port}}
+                            </summary>
+                            <ul>
+                                <li>Uptime: {{:uptime_str}}</li>
+                            </ul>
+                        </details>
+                    </li>
+                    {{/:stats}}
+                </ul>
+            </details>
+        </li>
+    </script>
+</div>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/AuthorizationExceptionMapper.java
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/AuthorizationExceptionMapper.java b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/AuthorizationExceptionMapper.java
new file mode 100644
index 0000000..5ee8ccb
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/AuthorizationExceptionMapper.java
@@ -0,0 +1,40 @@
+/*
+ * 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.storm.daemon.ui.exceptionmappers;
+
+import static org.apache.storm.daemon.ui.exceptionmappers.ExceptionMapperUtils.getResponse;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import org.apache.storm.generated.AuthorizationException;
+
+@Provider
+public class AuthorizationExceptionMapper implements ExceptionMapper<AuthorizationException> {
+
+    @Inject
+    public javax.inject.Provider<HttpServletRequest> request;
+
+    @Override
+    public Response toResponse(AuthorizationException e) {
+        return getResponse(e, request);
+    }
+}

http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/DefaultExceptionMapper.java
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/DefaultExceptionMapper.java b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/DefaultExceptionMapper.java
new file mode 100644
index 0000000..73aeb05
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/DefaultExceptionMapper.java
@@ -0,0 +1,48 @@
+/*
+ * 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.storm.daemon.ui.exceptionmappers;
+
+import static org.apache.storm.daemon.ui.exceptionmappers.ExceptionMapperUtils.getResponse;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+public class DefaultExceptionMapper implements ExceptionMapper<Throwable> {
+
+    @Inject
+    public javax.inject.Provider<HttpServletRequest> request;
+
+    /**
+     * toResponse.
+     * @param throwable
+     * @return response
+     */
+    @Override
+    public Response toResponse(Throwable throwable) {
+        if (throwable instanceof Exception) {
+            return getResponse((Exception) throwable, request);
+        } else {
+            return getResponse(new Exception(throwable.getMessage(), throwable), request);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/storm/blob/034ac677/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/ExceptionMapperUtils.java
----------------------------------------------------------------------
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/ExceptionMapperUtils.java b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/ExceptionMapperUtils.java
new file mode 100644
index 0000000..7d3627e
--- /dev/null
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/exceptionmappers/ExceptionMapperUtils.java
@@ -0,0 +1,70 @@
+/*
+ * 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.storm.daemon.ui.exceptionmappers;
+
+import javax.inject.Provider;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
+
+import org.apache.storm.daemon.common.JsonResponseBuilder;
+import org.apache.storm.daemon.ui.UIHelpers;
+import org.apache.storm.daemon.ui.resources.StormApiResource;
+import org.apache.storm.generated.AuthorizationException;
+
+
+public class ExceptionMapperUtils {
+
+    /**
+     * getResponse.
+     * @param ex ex
+     * @param responseStatus responseStatus
+     * @return getResponse
+     */
+    public static Response getResponse(Exception ex, Response.Status responseStatus,
+                                       Provider<HttpServletRequest> request) {
+        String callback = null;
+        if (request.get().getParameterMap().containsKey(StormApiResource.callbackParameterName)) {
+            callback = String.valueOf(request.get().getParameterMap().get(StormApiResource.callbackParameterName));
+        }
+        return new JsonResponseBuilder().setData(
+                UIHelpers.exceptionToJson(ex, responseStatus.getStatusCode())).setCallback(callback)
+                .setStatus(responseStatus.getStatusCode()).build();
+    }
+
+    /**
+     * getResponse.
+     * @param ex ex
+     * @param request request
+     * @return getResponse
+     */
+    public static Response getResponse(AuthorizationException ex, Provider<HttpServletRequest> request) {
+        return getResponse(ex, Response.Status.UNAUTHORIZED, request);
+    }
+
+    /**
+     * getResponse.
+     * @param ex ex
+     * @return getResponse
+     */
+    public static Response getResponse(Exception ex, Provider<HttpServletRequest> request) {
+        return getResponse(ex, Response.Status.INTERNAL_SERVER_ERROR, request);
+    }
+
+
+}