You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@heron.apache.org by th...@apache.org on 2022/05/15 07:40:08 UTC

[incubator-heron] 01/01: Added to show the number of instances in the topology list UI.

This is an automated email from the ASF dual-hosted git repository.

thinker0 pushed a commit to branch feature/add-instances-of-ui
in repository https://gitbox.apache.org/repos/asf/incubator-heron.git

commit 272ad2059a0a0e12e3b6cc254500b6feea793816
Author: choi se <th...@gmail.com>
AuthorDate: Fri May 13 15:36:12 2022 +0900

    Added to show the number of instances in the topology list UI.
    
    Add TestCase test_instances of Tracker
    
    Change number type of Instances
    
    Change number type of Instances
    
    Check has attribute of physical_play
---
 heron/tools/tracker/src/python/topology.py         | 10 ++++---
 heron/tools/tracker/tests/python/mock_proto.py     | 31 +++++++++++++++++++++-
 .../tracker/tests/python/topology_unittest.py      | 17 ++++++++++++
 .../tools/ui/resources/static/js/alltopologies.js  | 26 +++++++++++-------
 heron/tools/ui/resources/templates/topology.html   |  2 ++
 5 files changed, 72 insertions(+), 14 deletions(-)

diff --git a/heron/tools/tracker/src/python/topology.py b/heron/tools/tracker/src/python/topology.py
index 89a6ac6409c..817c35073d2 100644
--- a/heron/tools/tracker/src/python/topology.py
+++ b/heron/tools/tracker/src/python/topology.py
@@ -52,6 +52,7 @@ class TopologyInfoMetadata(BaseModel):
   release_username: str
   release_tag: str
   release_version: str
+  instances: int = 0
   extra_links: List[Dict[str, str]]
 
 class TopologyInfoExecutionState(TopologyInfoMetadata):
@@ -274,7 +275,7 @@ class Topology:
     return TopologyInfo(
         id=topology.id,
         logical_plan=self._build_logical_plan(topology, execution_state, physical_plan),
-        metadata=self._build_metadata(topology, execution_state, tracker_config),
+        metadata=self._build_metadata(topology, physical_plan, execution_state, tracker_config),
         name=topology.name, # was self.name
         packing_plan=self._build_packing_plan(packing_plan),
         physical_plan=self._build_physical_plan(physical_plan),
@@ -313,7 +314,7 @@ class Topology:
         topology_pb2.PAUSED: "Paused",
         topology_pb2.KILLED: "Killed",
     }.get(physical_plan.topology.state if physical_plan else None, "Unknown")
-    metadata = Topology._build_metadata(topology, execution_state, tracker_config)
+    metadata = Topology._build_metadata(topology, physical_plan, execution_state, tracker_config)
     return TopologyInfoExecutionState(
         has_physical_plan=bool(physical_plan),
         has_packing_plan=bool(packing_plan),
@@ -378,7 +379,8 @@ class Topology:
     return info
 
   @staticmethod
-  def _build_metadata(topology, execution_state, tracker_config) -> TopologyInfoMetadata:
+  def _build_metadata(topology, physical_plan, execution_state, tracker_config) \
+          -> TopologyInfoMetadata:
     if not execution_state:
       return  TopologyInfoMetadata()
     metadata = {
@@ -392,6 +394,8 @@ class Topology:
         "release_tag": execution_state.release_state.release_tag,
         "release_version": execution_state.release_state.release_version,
     }
+    if physical_plan is not None and hasattr(physical_plan, "instances"):
+      metadata["instances"] = len(physical_plan.instances)
     extra_links = deepcopy(tracker_config.extra_links)
     Topology._render_extra_links(extra_links, topology, execution_state)
     return TopologyInfoMetadata(
diff --git a/heron/tools/tracker/tests/python/mock_proto.py b/heron/tools/tracker/tests/python/mock_proto.py
index f939395d0e9..ebe4491a52f 100644
--- a/heron/tools/tracker/tests/python/mock_proto.py
+++ b/heron/tools/tracker/tests/python/mock_proto.py
@@ -176,14 +176,43 @@ class MockProto:
 
     return topology
 
+  def create_mock_stream_manager(self):
+    stmgr = protoPPlan.StMgr()
+    stmgr.id = "mock_stream1"
+    stmgr.host_name = "local"
+    stmgr.local_endpoint = ":1000"
+    stmgr.local_data_port = 1001
+    stmgr.shell_port = 1002
+    stmgr.data_port = 1003
+    stmgr.cwd = ""
+    stmgr.pid = 1
+    return stmgr
+
+  def create_mock_instance(self, i):
+    instance = protoPPlan.Instance()
+    instance.instance_id = f"mock_instance{i}"
+    instance.stmgr_id = f"mock_stream{i}"
+    instance_info = protoPPlan.InstanceInfo()
+    instance_info.task_id = i
+    instance_info.component_index = i
+    instance_info.component_name = f"mock_spout"
+    instance.info.CopyFrom(instance_info)
+    return instance
+
   def create_mock_simple_physical_plan(
       self,
       spout_parallelism=1,
-      bolt_parallelism=1):
+      bolt_parallelism=1,
+      instances_num=1):
     pplan = protoPPlan.PhysicalPlan()
     pplan.topology.CopyFrom(self.create_mock_simple_topology(
         spout_parallelism,
         bolt_parallelism))
+    pplan.stmgrs.extend([self.create_mock_stream_manager()])
+    instances = []
+    for i in range(instances_num):
+      instances.append(self.create_mock_instance(i+1))
+    pplan.instances.extend(instances)
     return pplan
 
   def create_mock_simple_packing_plan(
diff --git a/heron/tools/tracker/tests/python/topology_unittest.py b/heron/tools/tracker/tests/python/topology_unittest.py
index a03ea4aeb36..f48a17fd8e2 100644
--- a/heron/tools/tracker/tests/python/topology_unittest.py
+++ b/heron/tools/tracker/tests/python/topology_unittest.py
@@ -116,3 +116,20 @@ def test_bolts(topology):
   assert 3 == len(bolts)
   assert ["mock_bolt1", "mock_bolt2", "mock_bolt3"] == \
                    topology.bolt_names()
+
+
+def test_containers(topology):
+  # Set pplan now
+  pplan = MockProto().create_mock_simple_physical_plan()
+  topology.set_physical_plan(pplan)
+
+  assert 1 == len(pplan.instances)
+
+  estate = MockProto().create_mock_execution_state()
+  topology.set_execution_state(estate)
+
+  tracker = MagicMock(Tracker)
+  tracker.config.extra_links = []
+
+  top_info_meta = topology._build_metadata(topology, pplan, estate, tracker.config)
+  assert 1 == top_info_meta.instances
diff --git a/heron/tools/ui/resources/static/js/alltopologies.js b/heron/tools/ui/resources/static/js/alltopologies.js
index a45534a5fe5..e9140c77773 100644
--- a/heron/tools/ui/resources/static/js/alltopologies.js
+++ b/heron/tools/ui/resources/static/js/alltopologies.js
@@ -30,8 +30,9 @@ var TopologyItem = React.createClass({
     };
 
     var topology = this.props.topology;
-    var displaycluster = topology.cluster.toUpperCase();
-    var displayenv = topology.environ.toUpperCase();
+    var display_cluster = topology.cluster.toUpperCase();
+    var display_env = topology.environ.toUpperCase();
+    var display_instances = topology.instances;
     var display_time = "-";
     if (topology.submission_time !== "-") {
       display_time = moment(topology.submission_time * 1000).fromNow();
@@ -53,14 +54,15 @@ var TopologyItem = React.createClass({
     return (
        <tr className={state_class}>
          <td className="col-md-1 index no-break">{index}</td>
-         <td className="col-md-3 break-all"><a className="toponame" href={'./topologies/' + topology.cluster + '/' + topology.environ + '/' + topology.name}>{topology.name}</a></td>
-         <td className="col-md-1 topostatus">{topology.status}</td>
-         <td className="col-md-1 topocluster">{displaycluster}</td>
-         <td className="col-md-1 toporunrole break-all">{topology.role}</td>
-         <td className="col-md-1 topoenviron">{displayenv}</td>
-         <td className="col-md-2 toporeleaseversion break-all">{topology.release_version}</td>
-         <td className="col-md-1 toposubmittedby break-all">{topology.submission_user}</td>
-         <td className="col-md-2 toposubmittedat no-break">{display_time}</td>
+         <td className="col-md-3 break-all"><a className="topo_name" href={'./topologies/' + topology.cluster + '/' + topology.environ + '/' + topology.name}>{topology.name}</a></td>
+         <td className="col-md-1 topo_status">{topology.status}</td>
+         <td className="col-md-1 topo_cluster">{display_cluster}</td>
+         <td className="col-md-1 topo_runrole break-all">{topology.role}</td>
+         <td className="col-md-1 topo_environ">{display_env}</td>
+         <td className="col-md-1 topo_instances">{display_instances}</td>
+         <td className="col-md-2 topo_releaseversion break-all">{topology.release_version}</td>
+         <td className="col-md-1 topo_submittedby break-all">{topology.submission_user}</td>
+         <td className="col-md-2 topo_submittedat no-break">{display_time}</td>
        </tr>
     );
   }
@@ -94,6 +96,7 @@ var TopologyTable = React.createClass({
                 role: estate.role,
                 has_physical_plan: estate.has_physical_plan,
                 has_tmanager_location: estate.has_tmanager_location,
+                instances: estate.instances,
                 release_version: estate.release_version,
                 submission_time: estate.submission_time,
                 submission_user: estate.submission_user,
@@ -193,6 +196,9 @@ var TopologyTable = React.createClass({
               <th onClick={sortBy("environ")} className={sortClass("environ")}>
                 Environ
               </th>
+              <th onClick={sortBy("instances")} className={sortClass("instances")}>
+                Instances
+              </th>
               <th onClick={sortBy("release_version")} className={sortClass("release_version")}>
                 Version
               </th>
diff --git a/heron/tools/ui/resources/templates/topology.html b/heron/tools/ui/resources/templates/topology.html
index 38f55c753c4..692f05fe04f 100644
--- a/heron/tools/ui/resources/templates/topology.html
+++ b/heron/tools/ui/resources/templates/topology.html
@@ -58,6 +58,7 @@ under the License.
       <th>Cluster</th>
       <th>Role</th>
       <th>Environment</th>
+      <th>Instances</th>
       <th>Version</th>
       <th>Launched at</th>
       <th>Submitted by</th>
@@ -71,6 +72,7 @@ under the License.
         <td>{{cluster}}</td>
         <td>{{execution_state['role']}}</td>
         <td>{{environ}}</td>
+        <td>{{instances}}</td>
         <td>{{execution_state['release_version']}}</td>
         <td>{{launched}}</td>
         <td>{{execution_state['submission_user']}}</td>