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>