You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sr...@apache.org on 2014/02/18 18:17:27 UTC

git commit: AMBARI-4683. Tez vertex status should be shown in DAG. (srimanth)

Repository: ambari
Updated Branches:
  refs/heads/trunk 8d9b031e8 -> f2c18bcd7


AMBARI-4683. Tez vertex status should be shown in DAG. (srimanth)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f2c18bcd
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f2c18bcd
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f2c18bcd

Branch: refs/heads/trunk
Commit: f2c18bcd762a99edeb8ba8d38a6a194acd279fa2
Parents: 8d9b031
Author: Srimanth Gunturi <sg...@hortonworks.com>
Authored: Fri Feb 14 09:58:55 2014 -0800
Committer: Srimanth Gunturi <sg...@hortonworks.com>
Committed: Tue Feb 18 09:16:52 2014 -0800

----------------------------------------------------------------------
 ambari-web/app/styles/application.less          | 23 ++++++++++
 .../templates/main/jobs/hive_job_details.hbs    |  5 ++
 .../main/jobs/hive_job_details_tez_dag.hbs      |  5 ++
 ambari-web/app/utils/string_utils.js            | 14 ++++++
 .../main/jobs/hive_job_details_tez_dag_view.js  | 44 +++++++++++++++++-
 .../views/main/jobs/hive_job_details_view.js    | 15 ++++--
 ambari-web/test/utils/string_utils_test.js      | 48 ++++++++++++++------
 7 files changed, 135 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f2c18bcd/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index 9d15410..799901c 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -5674,6 +5674,29 @@ i.icon-asterisks {
           font-size: 80%;
         }
       }
+      .vertex-icon-text {
+        stroke-width: 0;
+        opacity: 0.9;
+      }
+      .vertex-icon-text.running,
+      .vertex-icon-text.initializing,
+      .vertex-icon-text.succeeded,
+      .vertex-icon-text.inited {
+        fill: green;
+        stroke: green;
+      }
+      .vertex-icon-text.new {
+        fill: #fde0dd;
+        stroke: cornflowerblue;
+        stroke-width: 1;
+      }
+      .vertex-icon-text.failed,
+      .vertex-icon-text.killed,
+      .vertex-icon-text.error,
+      .vertex-icon-text.terminating {
+        fill: red;
+        stroke: red;
+      }
     }
     .node text {
       pointer-events: none;

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2c18bcd/ambari-web/app/templates/main/jobs/hive_job_details.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/jobs/hive_job_details.hbs b/ambari-web/app/templates/main/jobs/hive_job_details.hbs
index 3d2d61a..1fe20ab 100644
--- a/ambari-web/app/templates/main/jobs/hive_job_details.hbs
+++ b/ambari-web/app/templates/main/jobs/hive_job_details.hbs
@@ -111,6 +111,11 @@
                 <div id="tez-vertex-details-section-body">
                   <table class="table">
                     <tr>
+                      <td>{{t common.status}}</td>
+                      <td>{{view.selectedVertexIODisplay.status}}</td>
+                      <td></td>
+                    </tr>
+                    <tr>
                       <td>{{t common.time.start}}</td>
                       <td>{{view.selectedVertexIODisplay.started}}</td>
                       <td></td>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2c18bcd/ambari-web/app/templates/main/jobs/hive_job_details_tez_dag.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/jobs/hive_job_details_tez_dag.hbs b/ambari-web/app/templates/main/jobs/hive_job_details_tez_dag.hbs
index c4b71df..e012324 100644
--- a/ambari-web/app/templates/main/jobs/hive_job_details_tez_dag.hbs
+++ b/ambari-web/app/templates/main/jobs/hive_job_details_tez_dag.hbs
@@ -34,6 +34,11 @@
         <rect x="0" y="0" width="44" height="16">
         </rect>
       </clipPath>
+      <font-face xmlns="http://www.w3.org/2000/svg" font-family="FontAwesome" unicode-range="U+0-7F">
+        <font-face-src>
+          <font-face-uri xlink:href="font/fontawesome-webfont.svg" xmlns:xlink="http://www.w3.org/1999/xlink"/>
+        </font-face-src>
+      </font-face>
     </defs>
   </svg>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2c18bcd/ambari-web/app/utils/string_utils.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/string_utils.js b/ambari-web/app/utils/string_utils.js
index c1b6061..0ce8340 100644
--- a/ambari-web/app/utils/string_utils.js
+++ b/ambari-web/app/utils/string_utils.js
@@ -59,6 +59,20 @@ module.exports = {
     }
     return name.replace(/_\w/g,replacer);
   },
+
+  /**
+   * Forces given string into upper camel-case representation. The first
+   * character of each word will be capitalized with the rest in lower case.
+   */
+  getCamelCase : function(name) {
+    if (name != null) {
+      return name.toLowerCase().replace(/(\b\w)/g, function(f) {
+        return f.toUpperCase();
+      })
+    }
+    return name;
+  },
+
   /**
    * Compare two versions by following rules:
    * first higher than second then return 1

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2c18bcd/ambari-web/app/views/main/jobs/hive_job_details_tez_dag_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/jobs/hive_job_details_tez_dag_view.js b/ambari-web/app/views/main/jobs/hive_job_details_tez_dag_view.js
index 0f7940a..408c9a1 100644
--- a/ambari-web/app/views/main/jobs/hive_job_details_tez_dag_view.js
+++ b/ambari-web/app/views/main/jobs/hive_job_details_tez_dag_view.js
@@ -195,6 +195,7 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
           node.metrics['recordsRead'] = vertex.get('recordReadCount');
           node.metrics['recordsWrite'] = vertex.get('recordWriteCount');
           node.metrics['tezTasks'] = vertex.get('tasksCount');
+          node.state = vertex.get('state');
           // Min metrics
           dagVisualModel.minMetrics.input = Math.min(dagVisualModel.minMetrics.input, node.metrics.input);
           dagVisualModel.minMetrics.output = Math.min(dagVisualModel.minMetrics.output, node.metrics.output);
@@ -213,7 +214,8 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
     Ember.run.once(this, 'summaryMetricTypeUpdated');
   }.observes('content.tezDag.vertices.@each.fileReadBytes', 'content.tezDag.vertices.@each.fileWriteBytes', 
       'content.tezDag.vertices.@each.hdfsReadBytes', 'content.tezDag.vertices.@each.hdfsWriteBytes', 
-      'content.tezDag.vertices.@each.recordReadCount', 'content.tezDag.vertices.@each.recordWriteCount'),
+      'content.tezDag.vertices.@each.recordReadCount', 'content.tezDag.vertices.@each.recordWriteCount',
+      'content.tezDag.vertices.@each.state'),
 
   /**
    * Determines layout and creates Tez graph. In the process it populates the
@@ -258,6 +260,7 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
         node = {
           id : vertex.get('id'),
           name : vertex.get('name'),
+          state: vertex.get('state'),
           isMap : vertex.get('isMap'),
           operations : vertex.get('operations'),
           depth : vertexObj.depth,
@@ -420,9 +423,10 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
     metricNodes.append("rect").attr("width", 60).attr("height", 18).attr("rx", "3");
     metricNodes.append("title").attr("class", "metric-title");
     metricNodes.append("text").attr("class", "metric-text").attr("x", "2").attr("dy", "1em");
-    node.append("text").attr("x", "1em").attr("dy", "1.5em").text(function(d) {
+    node.append("text").attr("x", "1.9em").attr("dy", "1.5em").text(function(d) {
       return d.name;
     });
+    node.append('text').attr("x", "0.8em").attr("dy", "1.5em").attr("font-family", "FontAwesome").attr('class', 'vertex-icon-text');
     node.attr("transform", function(d) {
       return "translate(" + d.x + "," + d.y + ")";
     });
@@ -435,10 +439,12 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
   refreshGraphUI: function () {
     var svgLayer = this.get('svgVerticesLayer');
     if (svgLayer!=null) {
+      var self = this;
       var metricNodes = svgLayer.selectAll(".metric");
       var metricNodeTexts = svgLayer.selectAll(".metric-text");
       var metricNodeTitles = svgLayer.selectAll(".metric-title");
       var nodeBackgrounds =svgLayer.selectAll(".background");
+      var vertexIconTexts = svgLayer.selectAll(".vertex-icon-text");
       metricNodes.attr("class", function(node) {
         var classes = "metric ";
         var percent = node.metricPercent;
@@ -479,7 +485,41 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
         }
         return classes;
       });
+      vertexIconTexts.text(function(n) {
+        return self.getVertexIcon(n)
+      }).attr('class', function(n) {
+        var classes = 'vertex-icon-text ';
+        if (n.state != null) {
+          classes += n.state.toLowerCase();
+        }
+        return classes;
+      });
+    }
+  },
+
+  getVertexIcon : function(node){
+    var icon = "";
+    switch (node.state) {
+    case App.TezDagVertexState.NEW:
+      icon = '\uF10C'; //icon-circle-blank
+    case App.TezDagVertexState.RUNNING:
+    case App.TezDagVertexState.FAILED:
+      icon = '\uF111'; //icon-circle
+      break;
+    case App.TezDagVertexState.SUCCEEDED:
+      icon = '\uF00C'; //icon-ok
+      break;
+    case App.TezDagVertexState.KILLED:
+    case App.TezDagVertexState.ERROR:
+      icon = '\uF057'; //icon-remove-sign
+      break;
+    case App.TezDagVertexState.INITED:
+    case App.TezDagVertexState.INITIALIZING:
+    case App.TezDagVertexState.TERMINATING:
+      icon = '\uF141'; //icon-ellipsis-horizontal
+      break;
     }
+    return icon;
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2c18bcd/ambari-web/app/views/main/jobs/hive_job_details_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/jobs/hive_job_details_view.js b/ambari-web/app/views/main/jobs/hive_job_details_view.js
index de1ff14..17ac845 100644
--- a/ambari-web/app/views/main/jobs/hive_job_details_view.js
+++ b/ambari-web/app/views/main/jobs/hive_job_details_view.js
@@ -19,6 +19,7 @@ var App = require('app');
 var date = require('utils/date');
 var numberUtils = require('utils/number_utils');
 var dateUtils = require('utils/date');
+var stringUtils = require('utils/string_utils');
 
 App.MainHiveJobDetailsView = Em.View.extend({
   templateName : require('templates/main/jobs/hive_job_details'),
@@ -136,11 +137,16 @@ App.MainHiveJobDetailsView = Em.View.extend({
    *    'write': '123 records'
    *  },
    *  'started': 'Feb 12, 2014 10:30am',
-   *  'ended': 'Feb 12, 2014 10:35am'
+   *  'ended': 'Feb 12, 2014 10:35am',
+   *  'status': 'Running'
    * }
    */
   selectedVertexIODisplay : function() {
     var v = this.get('selectedVertex');
+    var status = v.get('state');
+    if (status) {
+      status = stringUtils.getCamelCase(status);
+    }
     return {
       file : {
         read : {
@@ -164,12 +170,13 @@ App.MainHiveJobDetailsView = Em.View.extend({
       },
       records : {
         read : Em.I18n.t('jobs.hive.tez.records.count').format(v.get('recordReadCount')),
-        write : Em.I18n.t('jobs.hive.tez.records.count').format(v.get('recordWriteCount')),
+        write : Em.I18n.t('jobs.hive.tez.records.count').format(v.get('recordWriteCount'))
       },
       started: v.get('startTime') ? dateUtils.dateFormat(v.get('startTime')) : '',
-      ended: v.get('endTime') ? dateUtils.dateFormat(v.get('endTime')) : ''
+      ended: v.get('endTime') ? dateUtils.dateFormat(v.get('endTime')) : '',
+      status: status
     };
   }.property('selectedVertex.fileReadOps', 'selectedVertex.fileWriteOps', 'selectedVertex.hdfsReadOps', 'selectedVertex.hdfdWriteOps',
       'selectedVertex.fileReadBytes', 'selectedVertex.fileWriteBytes', 'selectedVertex.hdfsReadBytes', 'selectedVertex.hdfdWriteBytes',
-      'selectedVertex.recordReadCount', 'selectedVertes.recordWriteCount')
+      'selectedVertex.recordReadCount', 'selectedVertex.recordWriteCount', 'selectedVertex.status')
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2c18bcd/ambari-web/test/utils/string_utils_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/string_utils_test.js b/ambari-web/test/utils/string_utils_test.js
index e243346..3079c6d 100644
--- a/ambari-web/test/utils/string_utils_test.js
+++ b/ambari-web/test/utils/string_utils_test.js
@@ -109,19 +109,19 @@ describe('string_utils', function () {
     });
   });
 
-    describe('#getPath', function() {
-        var tests = [
-          {t: undefined, e: ''},
-          {t: {}, e: ''},
-          {t: [], e: ''},
-          {t: '', e: ''},
-          {t: function(){}, e: ''},
-          {t: '/path/to/filename', e: '/path/to'},
-          {t: '/path/to/', e: '/path/to'},
-          {t: '/filename', e: '/'},
-          {t: 'filename', e: ''},
-          {t: '/path/', e: '/path'},
-          {t: 'filename/', e: ''}
+  describe('#getPath', function() {
+      var tests = [
+        {t: undefined, e: ''},
+        {t: {}, e: ''},
+        {t: [], e: ''},
+        {t: '', e: ''},
+        {t: function(){}, e: ''},
+        {t: '/path/to/filename', e: '/path/to'},
+        {t: '/path/to/', e: '/path/to'},
+        {t: '/filename', e: '/'},
+        {t: 'filename', e: ''},
+        {t: '/path/', e: '/path'},
+        {t: 'filename/', e: ''}
       ];
       tests.forEach(function(test) {
           it('Check ' + typeof test.t, function () {
@@ -130,4 +130,26 @@ describe('string_utils', function () {
       });
   });
 
+  describe('#getCamelCase', function () {
+    var tests = [
+      {i:'a',e:'A'},
+      {i:'aB',e:'Ab'},
+      {i:'a b',e:'A B'},
+      {i:'a.b',e:'A.B'},
+      {i:'a,b',e:'A,B'},
+      {i:'a;b',e:'A;B'},
+      {i:'a. b',e:'A. B'},
+      {i:'a   b',e:'A   B'},
+      {i:'aaa. bbb',e:'Aaa. Bbb'},
+      {i:'aAA. bBB',e:'Aaa. Bbb'},
+      {i:'STARTING',e:'Starting'},
+      {i:'starting',e:'Starting'},
+      {i:'starting,ending',e:'Starting,Ending'}
+    ];
+    tests.forEach(function(test) {
+      it(test.i + ' to ' + test.e + ' ', function () {
+        expect(string_utils.getCamelCase(test.i)).to.equal(test.e);
+      });
+    });
+  });
 });