You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@heron.apache.org by hu...@apache.org on 2019/04/09 19:30:04 UTC

[incubator-heron] branch master updated: Data-driven Extra Links in Heron UI (#3233)

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

huijun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-heron.git


The following commit(s) were added to refs/heads/master by this push:
     new 6f4eee9  Data-driven Extra Links in Heron UI (#3233)
6f4eee9 is described below

commit 6f4eee97ba93c80c1de68132b721fc51aa3e4c43
Author: Xiaoyao Qian <qi...@illinois.edu>
AuthorDate: Tue Apr 9 12:29:58 2019 -0700

    Data-driven Extra Links in Heron UI (#3233)
    
    * New viz link
    
    * data driven extra links
---
 .../config/src/yaml/tracker/heron_tracker.yaml     |  6 +++-
 heron/tools/tracker/src/python/config.py           | 42 +++++++++++++---------
 heron/tools/tracker/src/python/tracker.py          | 17 ++++++---
 heron/tools/ui/resources/templates/topology.html   |  9 ++---
 4 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/heron/tools/config/src/yaml/tracker/heron_tracker.yaml b/heron/tools/config/src/yaml/tracker/heron_tracker.yaml
index 8995535..1d8cf5d 100644
--- a/heron/tools/config/src/yaml/tracker/heron_tracker.yaml
+++ b/heron/tools/config/src/yaml/tracker/heron_tracker.yaml
@@ -64,4 +64,8 @@ statemgrs:
 #
 # This is a sample, and should be changed to point to corresponding dashboard.
 #
-# viz.url.format: "http://127.0.0.1/${CLUSTER}/${ENVIRON}/${TOPOLOGY}/${ROLE}/${USER}"
+# extra.links:
+# - name: "Viz"
+#   formatter: "http://127.0.0.1/viz/${ENVIRON}-${CLUSTER}-${TOPOLOGY}"
+# - name: "Alerts"
+#   formatter: "http://127.0.0.1/alerts/${ENVIRON}-${CLUSTER}-${TOPOLOGY}"
diff --git a/heron/tools/tracker/src/python/config.py b/heron/tools/tracker/src/python/config.py
index 9307547..8da884f 100644
--- a/heron/tools/tracker/src/python/config.py
+++ b/heron/tools/tracker/src/python/config.py
@@ -23,7 +23,9 @@
 from heron.statemgrs.src.python.config import Config as StateMgrConfig
 
 STATEMGRS_KEY = "statemgrs"
-VIZ_URL_FORMAT_KEY = "viz.url.format"
+EXTRA_LINKS_KEY = "extra.links"
+EXTRA_LINK_NAME_KEY = "name"
+EXTRA_LINK_FORMATTER_KEY = "formatter"
 
 
 class Config(object):
@@ -35,20 +37,28 @@ class Config(object):
   def __init__(self, configs):
     self.configs = configs
     self.statemgr_config = StateMgrConfig()
-    self.viz_url_format = None
+    self.extra_links = []
 
     self.load_configs()
 
   def load_configs(self):
     """load config files"""
     self.statemgr_config.set_state_locations(self.configs[STATEMGRS_KEY])
-    if VIZ_URL_FORMAT_KEY in self.configs:
-      self.viz_url_format = self.validated_viz_url_format(self.configs[VIZ_URL_FORMAT_KEY])
-    else:
-      self.viz_url_format = ""
+    if EXTRA_LINKS_KEY in self.configs:
+      for extra_link in self.configs[EXTRA_LINKS_KEY]:
+        self.extra_links.append(self.validate_extra_link(extra_link))
+
+  def validate_extra_link(self, extra_link):
+    """validate extra link"""
+    if EXTRA_LINK_NAME_KEY not in extra_link or EXTRA_LINK_FORMATTER_KEY not in extra_link:
+      raise Exception("Invalid extra.links format. " +
+                      "Extra link must include a 'name' and 'formatter' field")
+
+    self.validated_formatter(extra_link[EXTRA_LINK_FORMATTER_KEY])
+    return extra_link
 
   # pylint: disable=no-self-use
-  def validated_viz_url_format(self, viz_url_format):
+  def validated_formatter(self, url_format):
     """validate visualization url format"""
     # We try to create a string by substituting all known
     # parameters. If an unknown parameter is present, an error
@@ -60,18 +70,18 @@ class Config(object):
         "${ROLE}": "role",
         "${USER}": "user",
     }
-    dummy_formatted_viz_url = viz_url_format
+    dummy_formatted_url = url_format
     for key, value in valid_parameters.items():
-      dummy_formatted_viz_url = dummy_formatted_viz_url.replace(key, value)
+      dummy_formatted_url = dummy_formatted_url.replace(key, value)
 
     # All $ signs must have been replaced
-    if '$' in dummy_formatted_viz_url:
-      raise Exception("Invalid viz.url.format: %s" % (viz_url_format))
+    if '$' in dummy_formatted_url:
+      raise Exception("Invalid viz.url.format: %s" % (url_format))
 
     # No error is thrown, so the format is valid.
-    return viz_url_format
+    return url_format
 
-  def get_formatted_viz_url(self, execution_state):
+  def get_formatted_url(self, execution_state, formatter):
     """
     @param execution_state: The python dict representing JSON execution_state
     @return Formatted viz url
@@ -86,12 +96,12 @@ class Config(object):
         "${USER}": execution_state["submission_user"],
     }
 
-    formatted_viz_url = self.viz_url_format
+    formatted_url = formatter
 
     for key, value in valid_parameters.items():
-      formatted_viz_url = formatted_viz_url.replace(key, value)
+      formatted_url = formatted_url.replace(key, value)
 
-    return formatted_viz_url
+    return formatted_url
 
   def __str__(self):
     return "".join((self.config_str(c) for c in self.configs[STATEMGRS_KEY]))
diff --git a/heron/tools/tracker/src/python/tracker.py b/heron/tools/tracker/src/python/tracker.py
index 8c0649a..421bc24 100644
--- a/heron/tools/tracker/src/python/tracker.py
+++ b/heron/tools/tracker/src/python/tracker.py
@@ -29,6 +29,7 @@ from functools import partial
 from heron.common.src.python.utils.log import Log
 from heron.proto import topology_pb2
 from heron.statemgrs.src.python import statemanagerfactory
+from heron.tools.tracker.src.python.config import EXTRA_LINK_FORMATTER_KEY
 from heron.tools.tracker.src.python.topology import Topology
 from heron.tools.tracker.src.python import javaobj
 from heron.tools.tracker.src.python import pyutils
@@ -276,10 +277,13 @@ class Tracker(object):
         "has_physical_plan": None,
         "has_tmaster_location": None,
         "has_scheduler_location": None,
+        "extra_links": [],
     }
 
-    viz_url = self.config.get_formatted_viz_url(executionState)
-    executionState["viz"] = viz_url
+    for extra_link in self.config.extra_links:
+      extra_link["url"] = self.config.get_formatted_url(executionState,
+                                                        extra_link[EXTRA_LINK_FORMATTER_KEY])
+      executionState["extra_links"].append(extra_link)
     return executionState
 
   def extract_metadata(self, topology):
@@ -298,10 +302,13 @@ class Tracker(object):
         "release_username": execution_state.release_state.release_username,
         "release_tag": execution_state.release_state.release_tag,
         "release_version": execution_state.release_state.release_version,
+        "extra_links": [],
     }
-    # refactor get_formatteed_viz_url
-    viz_url = self.config.get_formatted_viz_url(metadata)
-    metadata["viz"] = viz_url
+
+    for extra_link in self.config.extra_links:
+      extra_link["url"] = self.config.get_formatted_url(metadata,
+                                                        extra_link[EXTRA_LINK_FORMATTER_KEY])
+      metadata["extra_links"].append(extra_link)
     return metadata
 
   @staticmethod
diff --git a/heron/tools/ui/resources/templates/topology.html b/heron/tools/ui/resources/templates/topology.html
index 08bac44..707b042 100644
--- a/heron/tools/ui/resources/templates/topology.html
+++ b/heron/tools/ui/resources/templates/topology.html
@@ -149,7 +149,9 @@ under the License.
           <td>
             <a class="btn btn-primary btn-xs" href="./{{topology}}/config" target="_blank">Config</a>
             <a id="jobPageLink" class="btn btn-primary btn-xs" href={{job_page_link}} target="_blank">Job</a>
-            <a id="vizLink" class="btn btn-primary btn-xs" href="{{execution_state['viz']}}" target="_blank">Viz</a>
+            {% for extra_link in execution_state['extra_links'] %}
+              <a id="{{extra_link['name']}}" class="btn btn-primary btn-xs" href="{{extra_link['url']}}" target="_blank">{{extra_link['name']}}</a>
+            {% end %}
           </td>
         </tr>
       </tbody>
@@ -201,11 +203,6 @@ under the License.
       document.getElementById("jobPageLink").style.display = "none";
     }
 
-    // hide viz link if it is not there
-    if ("{{execution_state['viz']}}" === "") {
-      document.getElementById("vizLink").style.display = "none";
-    }
-
     // display the topology name as the title
     d3.select("#page-title")
       .append("p")