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 2014/06/11 18:10:21 UTC
[49/50] [abbrv] Merge branch 'master' into security-upmerge
http://git-wip-us.apache.org/repos/asf/incubator-storm/blob/0a98bee2/storm-core/src/ui/public/templates/topology-page-template.html
----------------------------------------------------------------------
diff --cc storm-core/src/ui/public/templates/topology-page-template.html
index 0000000,da58f9d..fe718dd
mode 000000,100644..100644
--- a/storm-core/src/ui/public/templates/topology-page-template.html
+++ b/storm-core/src/ui/public/templates/topology-page-template.html
@@@ -1,0 -1,128 +1,148 @@@
+ <script id="topology-summary-template" type="text/html">
+ <table id="topology-summary-table">
- <thead><tr><th><span class="tip right" title="The name given to the topology by when it was submitted.">Name</span></th><th><span class="tip right" title="The unique ID given to a Topology each time it is launched.">Id</span></th><th><span class="tip above" title="The status can be one of ACTIVE, INACTIVE, KILLED, or REBALANCING.">Status</span></th><th><span class="tip above" title="The time since the Topology was submitted.">Uptime</span></th><th><span class="tip above" title="The number of Workers (processes).">Num workers</span></th><th><span class="tip above" title="Executors are threads in a Worker process.">Num executors</span></th><th><span class="tip above" 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></tr></thead>
++ <thead><tr>
++ <th><span class="tip right" title="The name given to the topology by when it was submitted.">Name</span></th>
++ <th><span class="tip right" title="The unique ID given to a Topology each time it is launched.">Id</span></th>
++ <th><span class="tip above" title="The user that submitted the Topology, if authentication is enabled.">Owner</span></th>
++ <th><span class="tip above" title="The status can be one of ACTIVE, INACTIVE, KILLED, or REBALANCING.">Status</span></th>
++ <th><span class="tip above" title="The time since the Topology was submitted.">Uptime</span></th>
++ <th><span class="tip above" title="The number of Workers (processes).">Num workers</span></th>
++ <th><span class="tip above" title="Executors are threads in a Worker process.">Num executors</span></th>
++ <th><span class="tip above" 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 class="tip left" title="This shows information from the scheduler about the latest attempt to schedule the Topology on the cluster.">Scheduler Info</span></th>
++ </tr></thead>
+ <tbody>
+ <tr>
+ <td>{{name}}</td>
+ <td>{{id}}</td>
++ <td>{{owner}}</td>
+ <td>{{status}}</td>
+ <td>{{uptime}}</td>
+ <td>{{tasksTotal}}</td>
+ <td>{{workersTotal}}</td>
+ <td>{{executorsTotal}}</td>
++ <td>{{schedulerInfo}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </script>
+ <script id="topology-stats-template" type="text/html">
+ <h2>Topology stats</h2>
+ <table class="zebra-striped" id="topology-stats-table">
+ <thead><tr><th><span class="tip 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 class="tip above" title="The number of Tuples emitted.">Emitted</span></th><th><span class="tip above" title="The number of Tuples emitted that sent to one or more bolts.">Transferred</span></th><th><span class="tip above" 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><span class="tip above" title="The number of Tuple "trees" successfully processed. A value of 0 is expected if no acking is done.">Acked</span></th><th><span class="tip left" 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.">Failed</span></th></tr></thead>
+ <tbody>
+ {{#topologyStats}}
+ <tr>
+ <td><a href="/topology.html?id={{id}}&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-visualization-template" type="text/html">
+ <h2>Topology Visualization</h2>
+ <input type="button" id="show-hide-visualization" value="Show Visualization"/>
+ <p>
+ <div id="visualization-container" style="display:none;">
+ <p>
+ <table class="zebra-striped">
+ <thead>
+ <tr>
+ <th class="header" colspan=4>
+ Streams
+ </th>
+ </tr>
+ </thead>
+ {{#visualizationTable}}
+ <tr>
+ {{#:row}}
+ <td>
+ <input type="checkbox" id={{:sani-stream}} class="stream-box" {{#:checked}}checked{{/:checked}}/>
+ {{:stream}}
+ </td>
+ {{/:row}}
+ </tr>
+ {{/visualizationTable}}
+ </table>
+ </p>
+ <canvas id="topoGraph" width=1024 height=768 style="border:1px solid #000000;">
+ </div>
+ </p>
+ </script>
+
+ <script id="topology-configuration-template" type="text/html">
+ <h2>Topology Configuration</h2>
+ <table class="zebra-striped" 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="zebra-striped" 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." class="tip right">Id</span></th><th class="header"><span data-original-title="Executors are threads in a Worker process." class="tip right">Executors</span></th><th class="header"><span class="tip above" 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><th class="header"><span class="tip above" title="The number of Tuples emitted.">Emitted</span></th><th class="header"><span class="tip above" title="The number of Tuples emitted that sent to one or more bolts.">Transferred</span></th><th class="header"><span class="tip above" 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
class="tip above" 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 class="tip above" 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.">Failed</span></th><th class="header">Last error</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#spouts}}
+ <tr>
+ <td><a href="/component.html?id={{spoutId}}&topology_id={{id}}">{{spoutId}}</a></td>
+ <td>{{executors}}</td>
+ <td>{{tasks}}</td>
+ <td>{{emitted}}</td>
+ <td>{{transferred}}</td>
+ <td>{{completeLatency}}</td>
+ <td>{{acked}}</td>
+ <td>{{failed}}</td>
+ <td>{{lastError}}</td>
+ {{/spouts}}
+ </tbody>
+ </table>
+ </script>
+ <script id="bolt-stats-template" type="text/html">
+ <h2>Bolts ({{windowHint}})</h2>
+ <table class="zebra-striped" id="bolt-stats-table"><thead>
+ <tr><th class="header headerSortDown"><span class="tip 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"><span data-original-title="Executors are threads in a Worker process." class="tip right">Executors</span></th><th class="header"><span class="tip above" 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><th class="header"><span class="tip above" title="The number of Tuples emitted.">Emitted</span></th><th class="header"><span class="tip above" title="The number of Tuples emitted that sent to one or more bolts.">Transferred</span></th><th class="header"><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." class="tip abo
ve">Capacity (last 10m)</span></th><th class="header"><span class="tip above" 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 class="tip above" title="The number of incoming Tuples processed.">Executed</span></th><th class="header"><span class="tip above" 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"><span class="tip above" title="The number of Tuples acknowledged by this Bolt.">Acked</span></th><th class="header"><span class="tip left" title="The number of tuples Failed by this Bolt.">Failed</span></th><th class="header">Last error</th>
+ </tr></thead>
+ <tbody>
+ {{#bolts}}
+ <tr>
+ <td><a href="/component.html?id={{boltId}}&topology_id={{id}}">{{boltId}}</a></td>
+ <td>{{executors}}</td>
+ <td>{{tasks}}</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>
+ <td>{{lastError}}</td>
+ {{/bolts}}
+ </tbody>
+ </script>
+
+ <script id="topology-actions-template" type="text/html">
- <input {{activateStatus}} onclick="confirmAction('{{id}}', '{{name}}', 'activate', false, 0)" type="button" value="Activate"><input {{deactivateStatus}} onclick="confirmAction('{{id}}', '{{name}}', 'deactivate', false, 0)" type="button" value="Deactivate"><input {{rebalanceStatus}} onclick="confirmAction('{{id}}', '{{name}}', 'rebalance', true, {{msgTimeout}})" type="button" value="Rebalance"><input {{killStatus}} onclick="confirmAction('{{id}}', '{{name}}', 'kill', true, 30)" type="button" value="Kill">
++ {{#uiActionsEnabled}}
++ <h2>Topology actions</h2>
++ <p id="topology-actions">
++ <input {{activateStatus}} onclick="confirmAction('{{id}}', '{{name}}', 'activate', false, 0)" type="button" value="Activate">
++ <input {{deactivateStatus}} onclick="confirmAction('{{id}}', '{{name}}', 'deactivate', false, 0)" type="button" value="Deactivate">
++ <input {{rebalanceStatus}} onclick="confirmAction('{{id}}', '{{name}}', 'rebalance', true, {{msgTimeout}})" type="button" value="Rebalance">
++ <input {{killStatus}} onclick="confirmAction('{{id}}', '{{name}}', 'kill', true, 30)" type="button" value="Kill">
++ </p>
++ {{/uiActionsEnabled}}
+ </script>
http://git-wip-us.apache.org/repos/asf/incubator-storm/blob/0a98bee2/storm-core/src/ui/public/topology.html
----------------------------------------------------------------------
diff --cc storm-core/src/ui/public/topology.html
index 0000000,df095ad..b2ac1e5
mode 000000,100644..100644
--- a/storm-core/src/ui/public/topology.html
+++ b/storm-core/src/ui/public/topology.html
@@@ -1,0 -1,90 +1,87 @@@
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+ <html><head>
+ <title>Storm UI</title>
+ <link href="/css/bootstrap-1.4.0.css" rel="stylesheet" type="text/css">
+ <link href="/css/style.css" rel="stylesheet" type="text/css">
+ <script src="/js/jquery-1.6.2.min.js" type="text/javascript"></script>
+ <script src="/js/jquery.tablesorter.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/purl.js" type="text/javascript"></script>
+ <script src="/js/bootstrap-twipsy.js" type="text/javascript"></script>
+ <script src="/js/script.js" type="text/javascript"></script>
+ <script src="/js/visualization.js" type="text/javascript"></script>
+ <script src="/js/arbor.js" type="text/javascript"></script>
+ <script src="/js/arbor-graphics.js" type="text/javascript"></script>
+ </head>
+ <body>
+ <h1><a href="/">Storm UI</a></h1>
+ <h2>Topology summary</h2>
+ <div id="topology-summary">
+ </div>
+ <div id="topology-actions">
-<h2 class="js-only">Topology actions</h2>
-<p id="topology-actions" class="js-only">
-</p>
+ </div>
+ <div id="topology-stats"></div>
+ <div id="spout-stats">
+ </div>
+ <div id="bolt-stats">
+ </div>
+ <div id="topology-visualization">
+ </div>
+ <div id="topology-configuration">
+ </div>
+ <p id="toggle-switch" style="display: block;" class="js-only"></p>
+ <div id="json-response-error">
+ </div>
+ </body>
+ <script>
+ $(document).ready(function() {
+ var topologyId = $.url().param("id");
+ var window = $.url().param("window");
+ var sys = $.cookies.get("sys") || "false";
+ var url = "/api/v1/topology/"+topologyId+"?sys="+sys;
+ if(window) url += "&window="+window;
+ renderToggleSys($("#toggle-switch"));
+ $.ajaxSetup({
+ "error":function(jqXHR,textStatus,response) {
+ var errorJson = jQuery.parseJSON(jqXHR.responseText);
+ $.get("/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 topologySummary = $("#topology-summary");
+ var topologyStats = $("#topology-stats");
+ var spoutStats = $("#spout-stats");
+ var boltStats = $("#bolt-stats");
+ var config = $("#topology-configuration");
+ var topologyActions = $("#topology-actions");
+ var topologyVisualization = $("#topology-visualization")
+ var formattedConfig = formatConfigData(response["configuration"]);
- var buttonJsonData = topologyActionJson(response["id"],response["name"],response["status"],response["msgTimeout"]);
++ var buttonJsonData = topologyActionJson(response["id"],response["name"],response["status"],response["msgTimeout"], response["uiActionsEnabled"]);
+ $.get("/templates/topology-page-template.html", function(template) {
+ topologySummary.append(Mustache.render($(template).filter("#topology-summary-template").html(),response));
+ topologyActions.append(Mustache.render($(template).filter("#topology-actions-template").html(),buttonJsonData));
+ topologyStats.append(Mustache.render($(template).filter("#topology-stats-template").html(),response));
+ $("#topology-stats-table").tablesorter({ sortList: [[0,0]], headers: {0: { sorter: "stormtimestr"}}});
+ spoutStats.append(Mustache.render($(template).filter("#spout-stats-template").html(),response));
+ if(response["spouts"].length > 0) {
+ $("#spout-stats-table").tablesorter({sortList: [[0,0]], headers:{}});
+ }
+ boltStats.append(Mustache.render($(template).filter("#bolt-stats-template").html(),response));
+ if(response["bolts"].length > 0) {
+ $("#bolt-stats-table").tablesorter({sortList: [[0,0]], headers:{}});
+ }
+
+ topologyVisualization.append(Mustache.render($(template).filter("#topology-visualization-template").html(), response));
+ $("#show-hide-visualization").click(function () { show_visualization(null) });
+
+ config.append(Mustache.render($(template).filter("#topology-configuration-template").html(),formattedConfig));
+ $("#topology-configuration-table").tablesorter({ sortList: [[0,0]], headers: {}});
+ });
+ });
+ });
+ </script>
+ </html>
http://git-wip-us.apache.org/repos/asf/incubator-storm/blob/0a98bee2/storm-core/test/clj/backtype/storm/drpc_test.clj
----------------------------------------------------------------------
diff --cc storm-core/test/clj/backtype/storm/drpc_test.clj
index fbc60e6,6d0ba2b..debb332
--- a/storm-core/test/clj/backtype/storm/drpc_test.clj
+++ b/storm-core/test/clj/backtype/storm/drpc_test.clj
@@@ -218,3 -220,24 +220,26 @@@
(.shutdown cluster)
(.shutdown drpc)
))
+
+ (deftest test-dequeue-req-after-timeout
+ (let [queue (ConcurrentLinkedQueue.)
- delay-seconds 2]
++ delay-seconds 2
++ conf {DRPC-REQUEST-TIMEOUT-SECS delay-seconds}]
+ (stubbing [acquire-queue queue
- read-storm-config {DRPC-REQUEST-TIMEOUT-SECS delay-seconds}]
- (let [drpc-handler (service-handler)]
++ read-storm-config conf]
++ (let [drpc-handler (service-handler conf)]
+ (is (thrown? DRPCExecutionException
+ (.execute drpc-handler "ArbitraryDRPCFunctionName" "")))
+ (is (= 0 (.size queue)))))))
+
+ (deftest test-drpc-timeout-cleanup
+ (let [queue (ConcurrentLinkedQueue.)
- delay-seconds 1]
++ delay-seconds 1
++ conf {DRPC-REQUEST-TIMEOUT-SECS delay-seconds}]
+ (stubbing [acquire-queue queue
- read-storm-config {DRPC-REQUEST-TIMEOUT-SECS delay-seconds}
++ read-storm-config conf
+ timeout-check-secs delay-seconds]
- (let [drpc-handler (service-handler)]
++ (let [drpc-handler (service-handler conf)]
+ (is (thrown? DRPCExecutionException
+ (.execute drpc-handler "ArbitraryDRPCFunctionName" "no-args")))))))
+
http://git-wip-us.apache.org/repos/asf/incubator-storm/blob/0a98bee2/storm-core/test/clj/backtype/storm/ui_test.clj
----------------------------------------------------------------------
diff --cc storm-core/test/clj/backtype/storm/ui_test.clj
index 3a837c5,0000000..21ddb33
mode 100644,000000..100644
--- a/storm-core/test/clj/backtype/storm/ui_test.clj
+++ b/storm-core/test/clj/backtype/storm/ui_test.clj
@@@ -1,49 -1,0 +1,49 @@@
+;; 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.
+(ns backtype.storm.ui-test
+ (:use [clojure test])
+ (:use [backtype.storm config])
+ (:use [backtype.storm testing])
+ (:require [backtype.storm.ui [core :as core]])
+ )
+
+(deftest test-authorized-ui-user
+ (testing "allow cluster admin"
- (let [conf {NIMBUS-ADMINS ["alice"]}]
++ (let [conf {UI-FILTER "something" NIMBUS-ADMINS ["alice"]}]
+ (is (core/authorized-ui-user? "alice" conf {}))))
+
+ (testing "ignore any cluster-set topology.users"
- (let [conf {TOPOLOGY-USERS ["alice"]}]
++ (let [conf {UI-FILTER "something" TOPOLOGY-USERS ["alice"]}]
+ (is (not (core/authorized-ui-user? "alice" conf {})))))
+
+ (testing "allow cluster ui user"
- (let [conf {UI-USERS ["alice"]}]
++ (let [conf {UI-FILTER "something" UI-USERS ["alice"]}]
+ (is (core/authorized-ui-user? "alice" conf {}))))
+
+ (testing "allow submitted topology user"
+ (let [topo-conf {TOPOLOGY-USERS ["alice"]}]
- (is (core/authorized-ui-user? "alice" {} topo-conf))))
++ (is (core/authorized-ui-user? "alice" {UI-FILTER "something"} topo-conf))))
+
+ (testing "allow submitted ui user"
+ (let [topo-conf {UI-USERS ["alice"]}]
- (is (core/authorized-ui-user? "alice" {} topo-conf))))
++ (is (core/authorized-ui-user? "alice" {UI-FILTER "something"} topo-conf))))
+
+ (testing "disallow user not in nimbus admin, topo user, or ui user"
- (is (not (core/authorized-ui-user? "alice" {} {}))))
++ (is (not (core/authorized-ui-user? "alice" {UI-FILTER "something"} {}))))
+
+ (testing "user cannot override nimbus admin"
+ (let [topo-conf {NIMBUS-ADMINS ["alice"]}]
- (is (not (core/authorized-ui-user? "alice" {} topo-conf))))))
++ (is (not (core/authorized-ui-user? "alice" {UI-FILTER "something"} topo-conf))))))