You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by ss...@apache.org on 2015/02/10 22:52:18 UTC

[06/17] tez git commit: TEZ-2043. Tez UI: add progress info from am webservice to dag and vertex views. (Prakash Ramachandran via hitesh)

TEZ-2043. Tez UI: add progress info from am webservice to dag and vertex views. (Prakash Ramachandran via hitesh)


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

Branch: refs/heads/TEZ-2003
Commit: d51103db3ae383b0e6e43577dd1c97f49f5f3bfc
Parents: 5f3a9a3
Author: Hitesh Shah <hi...@apache.org>
Authored: Fri Feb 6 09:28:18 2015 -0800
Committer: Hitesh Shah <hi...@apache.org>
Committed: Fri Feb 6 09:28:18 2015 -0800

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 tez-ui/src/main/webapp/app/index.html           |  1 +
 tez-ui/src/main/webapp/app/scripts/app.js       | 44 ++++++++++++++
 .../app/scripts/controllers/dag_controller.js   | 18 +++++-
 .../scripts/controllers/dag_index_controller.js |  8 +++
 .../app/scripts/controllers/dag_vertices.js     | 46 +++++++++++++-
 .../app/scripts/controllers/dags_controller.js  | 23 ++++++-
 .../controllers/tez-app-dags-controller.js      | 48 ++++++++++++++-
 .../scripts/controllers/vertex_controller.js    | 21 ++++++-
 .../controllers/vertex_index_controller.js      |  8 +++
 .../main/webapp/app/scripts/default-configs.js  |  5 +-
 .../main/webapp/app/scripts/helpers/number.js   | 10 ++++
 .../app/scripts/mixins/paginated_content.js     | 15 ++++-
 .../app/scripts/models/TimelineRestAdapter.js   |  4 ++
 .../src/main/webapp/app/scripts/models/dag.js   | 23 +++++++
 .../src/main/webapp/app/templates/dag/index.hbs | 63 ++++++++++----------
 .../main/webapp/app/templates/vertex/index.hbs  |  1 +
 17 files changed, 295 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 2ab6c0a..0732004 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -57,6 +57,7 @@ Release 0.6.1: Unreleased
 INCOMPATIBLE CHANGES
 
 ALL CHANGES:
+  TEZ-2043. Tez UI: add progress info from am webservice to dag and vertex views.
   TEZ-2032. Update CHANGES.txt to show 0.6.0 is released
   TEZ-2018. App Tracking and History URL should point to the Tez UI.
   TEZ-2035. Make timeline server putDomain exceptions non-fatal - work-around

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/index.html b/tez-ui/src/main/webapp/app/index.html
index 73e991b..4fe7e3d 100644
--- a/tez-ui/src/main/webapp/app/index.html
+++ b/tez-ui/src/main/webapp/app/index.html
@@ -53,6 +53,7 @@
     <script src="bower_components/ember-addons.bs_for_ember/dist/js/bs-modal.min.js"></script>
     <script src="bower_components/ember-addons.bs_for_ember/dist/js/bs-nav.min.js"></script>
     <script src="bower_components/ember-addons.bs_for_ember/dist/js/bs-items-action-bar.min.js"></script>
+    <script src="bower_components/ember-addons.bs_for_ember/dist/js/bs-badge.min.js"></script>
     <script src="bower_components/antiscroll/antiscroll.js"></script>
     <script src="bower_components/jquery-mousewheel/jquery.mousewheel.js"></script>
     <script src="bower_components/ember-table/dist/ember-table.js"></script>

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/app.js b/tez-ui/src/main/webapp/app/scripts/app.js
index 5beb815..4fc461a 100644
--- a/tez-ui/src/main/webapp/app/scripts/app.js
+++ b/tez-ui/src/main/webapp/app/scripts/app.js
@@ -107,6 +107,50 @@ App.ready = function () {
       });
     }
   });
+
+  App.AMInfoAdapter = DS.RESTAdapter.extend({
+    ajax: function(url, method, hash) {
+      hash = hash || {}; // hash may be undefined
+      if (hash && hash.data && hash.data.__app_id__) {
+        url = url.replace('__app_id__', hash.data.__app_id__);
+        delete hash.data['__app_id__'];
+      }
+      hash.crossDomain = true;
+      hash.xhrFields = {withCredentials: true};
+      return this._super(url, method, hash);
+    },
+    host: App.env.RMWebUrl,
+    namespace: App.Configs.restNamespace.aminfo,
+  });
+
+  App.DagProgressAdapter = App.AMInfoAdapter.extend({
+    buildURL: function(type, id, record) {
+      var url = this._super(type, undefined, record);
+      return url.replace('__app_id__', record.get('appId'))
+        .fmt(record.get('dagIdx'));
+    },
+    pathForType: function() {
+      return 'dagProgress?dagID=%@';
+    }
+  });
+
+  App.VertexProgressAdapter = App.AMInfoAdapter.extend({
+    findQuery: function(store, type, query) {
+      var record = query.metadata;
+      delete query.metadata;
+      return this.ajax(
+        this.buildURL(Ember.String.pluralize(type.typeKey),
+          record.vertexIds, Em.Object.create(record)), 'GET', { data: query});
+    },
+    buildURL: function(type, id, record) {
+      var url = this._super(type, undefined, record);
+      return url.replace('__app_id__', record.get('appId'))
+        .fmt(record.get('dagIdx'), id);
+    },
+    pathForType: function(typeName) {
+      return typeName + '?dagID=%@&vertexID=%@';
+    }
+  });
 };
 
 /* Order and include */

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js
index 3375e33..1fdf053 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js
@@ -24,7 +24,23 @@ App.DagController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
 	loading: true,
 
 	updateLoading: function() {
-    this.set('loading', false);
+    var that = this;
+    var loaders = [];
+    if (this.get('status') === 'RUNNING') {
+      // update the progress info if available. this need not block the UI
+      var aminfoLoader = that.store.find('dagProgress', that.get('id'), {
+        appId: that.get('applicationId'),
+        dagIdx: that.get('idx')
+      }).then(function(dagProgressInfo) {
+        that.set('progress', dagProgressInfo.get('progress'));
+      }).catch(function (error) {
+        Em.Logger.error("Failed to fetch dagProgress")
+      });
+      loaders.push(aminfoLoader);
+    }
+    Em.RSVP.allSettled(loaders).then(function(){
+      that.set('loading', false);
+    });
   }.observes('content'),
 
 	childDisplayViews: [

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js
index a7eb3ea..fed28c7 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js
@@ -24,6 +24,14 @@ App.DagIndexController = Em.ObjectController.extend({
 		return App.Helpers.misc.getStatusClassForEntity(this.get('model'));
 	}.property('id', 'status', 'counterGroups'),
 
+  progressStr: function() {
+    var pct;
+    if (Ember.typeOf(this.get('progress')) === 'number') {
+      pct = App.Helpers.number.fractionToPercentage(this.get('progress'));
+    }
+    return pct;
+  }.property('id', 'status', 'progress'),
+
 	totalTasks: function() {
 		return App.Helpers.misc.getCounterValueForDag(this.get('counterGroups'), 
 			this.get('id'), 'org.apache.tez.common.counters.DAGCounter', 'TOTAL_LAUNCHED_TASKS')

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
index 7cc5fbf..c26f83e 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
@@ -44,6 +44,40 @@ App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin
     this.setFiltersAndLoadEntities(filters);
   },
 
+  loadAdditional: function() {
+    var defer = Em.RSVP.defer();
+
+    var that = this;
+        vertices = this.get('entities');
+    var runningVerticesIdx = vertices
+      .filterBy('status', 'RUNNING')
+      .map(function(item) {
+        return item.get('id').split('_').splice(-1).pop();
+      });
+    if (runningVerticesIdx.length > 0) {
+      this.store.findQuery('vertexProgress', {
+        metadata: {
+          appId: that.get('applicationId'),
+          dagIdx: that.get('idx'),
+          vertexIds: runningVerticesIdx.join(',')
+        }
+      }).then(function(vertexProgressInfo) {
+        vertexProgressInfo.forEach(function(item) {
+          var model = vertices.findBy('id', item.get('id')) || Em.Object.create();
+          model.set('progress', item.get('progress'));
+        });
+      }).catch(function(error) {
+        Em.Logger.debug("failed to fetch vertex progress")
+      }).finally(function(){
+        defer.resolve();
+      })
+    } else {
+      defer.resolve();
+    }
+
+    return defer.promise;
+  },
+
   actions : {
     filterUpdated: function(filterID, value) {
       // any validations required goes here.
@@ -129,12 +163,18 @@ App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin
           template: Em.Handlebars.compile(
             '<span class="ember-table-content">&nbsp;\
             <i {{bind-attr class=":task-status view.cellContent.statusIcon"}}></i>\
-            &nbsp;&nbsp;{{view.cellContent.status}}</span>')
+            &nbsp;&nbsp;{{view.cellContent.status}}\
+            {{#if view.cellContent.progress}} {{bs-badge content=view.cellContent.progress}}{{/if}}</span>')
         }),
         getCellContent: function(row) {
+          var pct;
+          if (Ember.typeOf(row.get('progress')) === 'number') {
+            pct = App.Helpers.number.fractionToPercentage(row.get('progress'));
+          }
           return {
             status: row.get('status'),
-            statusIcon: App.Helpers.misc.getStatusClassForEntity(row)
+            statusIcon: App.Helpers.misc.getStatusClassForEntity(row),
+            progress: pct
           };
         }
       },
@@ -180,4 +220,4 @@ App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin
     );
   }.property(),
 
-});
\ No newline at end of file
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
index 55f9d26..9d1a243 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
@@ -87,6 +87,19 @@ App.DagsController = Em.ObjectController.extend(App.PaginatedContentMixin, App.C
             dag.set('tezApp', app);
           });
           loaders.push(fetcher);
+          if (dag.get('status') === 'RUNNING') {
+            amInfoFetcher = store.find('dagProgress', dag.get('id'), {
+              appId: dag.get('applicationId'),
+              dagIdx: dag.get('idx')
+            })
+            .then(function(dagProgressInfo) {
+              dag.set('progress', dagProgressInfo.get('progress'));
+            })
+            .catch(function(error) {
+              Em.Logger.error('Failed to fetch dagProgress' + error);
+            });
+            loaders.push(amInfoFetcher);
+          }
         }
       });
       Em.RSVP.allSettled(loaders).then(function(){
@@ -154,12 +167,18 @@ App.DagsController = Em.ObjectController.extend(App.PaginatedContentMixin, App.C
           template: Em.Handlebars.compile(
             '<span class="ember-table-content">&nbsp;\
             <i {{bind-attr class=":task-status view.cellContent.statusIcon"}}></i>\
-            &nbsp;&nbsp;{{view.cellContent.status}}</span>')
+            &nbsp;&nbsp;{{view.cellContent.status}}\
+            {{#if view.cellContent.progress}} {{bs-badge content=view.cellContent.progress}}{{/if}}</span>')
         }),
         getCellContent: function(row) {
+          var pct;
+          if (Ember.typeOf(row.get('progress')) === 'number') {
+            pct = App.Helpers.number.fractionToPercentage(row.get('progress'));
+          }
           return {
             status: row.get('status'),
-            statusIcon: App.Helpers.misc.getStatusClassForEntity(row)
+            statusIcon: App.Helpers.misc.getStatusClassForEntity(row),
+            progress: pct
           };
         }
       },

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
index b9054b1..438ec29 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
@@ -47,6 +47,44 @@ App.TezAppDagsController = Em.ObjectController.extend(App.PaginatedContentMixin,
     this.setFiltersAndLoadEntities(filters);
   },
 
+  loadEntities: function() {
+    var that = this;
+    var childEntityType = this.get('childEntityType');
+    var defaultErrMsg = 'Error while loading %@. could not connect to %@'
+      .fmt(childEntityType, App.env.timelineBaseUrl);
+
+
+    that.set('loading', true);
+
+    this.get('store').unloadAll(childEntityType);
+    this.get('store').findQuery(childEntityType, this.getFilterProperties()).then(function(entities){
+      that.set('entities', entities);
+
+      var loaders = [];
+      entities.forEach(function (dag) {
+        if (dag.get('status') === 'RUNNING') {
+          amInfoFetcher = that.store.find('dagProgress', dag.get('id'), {
+            appId: dag.get('applicationId'),
+            dagIdx: dag.get('idx')
+          }).then(function(dagProgressInfo) {
+              dag.set('progress', dagProgressInfo.get('progress'));
+          }).catch(function(error) {
+            Em.Logger.error('Failed to fetch dagProgress' + error);
+          });
+          loaders.push(amInfoFetcher);
+        }
+      });
+      Em.RSVP.allSettled(loaders).then(function(){
+        that.set('loading', false);
+      });
+    }).catch(function(error){
+      Em.Logger.error(error);
+      var err = App.Helpers.misc.formatError(error, defaultErrMsg);
+      var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);
+      App.Helpers.ErrorBar.getInstance().show(msg, err.details);
+    });
+  },
+
   actions : {
     filterUpdated: function(filterID, value) {
       // any validations required goes here.
@@ -97,12 +135,18 @@ App.TezAppDagsController = Em.ObjectController.extend(App.PaginatedContentMixin,
           template: Em.Handlebars.compile(
             '<span class="ember-table-content">&nbsp;\
             <i {{bind-attr class=":task-status view.cellContent.statusIcon"}}></i>\
-            &nbsp;&nbsp;{{view.cellContent.status}}</span>')
+            &nbsp;&nbsp;{{view.cellContent.status}}\
+            {{#if view.cellContent.progress}} {{bs-badge content=view.cellContent.progress}}{{/if}}</span>')
         }),
         getCellContent: function(row) {
+          var pct;
+          if (Ember.typeOf(row.get('progress')) === 'number') {
+            pct = App.Helpers.number.fractionToPercentage(row.get('progress'));
+          }
           return {
             status: row.get('status'),
-            statusIcon: App.Helpers.misc.getStatusClassForEntity(row)
+            statusIcon: App.Helpers.misc.getStatusClassForEntity(row),
+            progress: pct
           };
         }
       },

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
index 1c20b3e..e5e74e5 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
@@ -24,7 +24,26 @@ App.VertexController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
   loading: true,
 
   updateLoading: function() {
-    this.set('loading', false);
+    var loaders = [],
+      that = this;
+
+    if (this.get('status') == 'RUNNING') {
+      var vertexIdx = that.get('id').split('_').splice(-1).pop();
+      var progressLoader = this.store.find('vertexProgress', vertexIdx, {
+        appId: that.get('applicationId'),
+        dagIdx: that.get('dagIdx')
+      }).then(function(vertexProgressInfo) {
+        if (vertexProgressInfo) {
+          that.set('progress', vertexProgressInfo.get('progress'));
+        }
+      }).catch(function(error) {
+        Em.Logger.error("Failed to fetch vertexProgress" + error)
+      });
+      loaders.push(progressLoader);
+    }
+    Em.RSVP.allSettled(loaders).then(function(){
+      that.set('loading', false);
+    });
   }.observes('content'),
 
   childDisplayViews: [

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js
index a7b16c3..8c53db2 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js
@@ -24,6 +24,14 @@ App.VertexIndexController = Em.ObjectController.extend({
     return App.Helpers.misc.getStatusClassForEntity(this.get('model'));
   }.property('id', 'status', 'counterGroups'),
 
+  progressStr: function() {
+    var pct;
+    if (Ember.typeOf(this.get('progress')) === 'number') {
+      pct = App.Helpers.number.fractionToPercentage(this.get('progress'));
+    }
+    return pct;
+  }.property('id', 'status', 'progress'),
+
   hasFailedTasks: function() {
     return this.get('failedTasks') > 0;
   }.property('id', 'counterGroups'),

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/default-configs.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/default-configs.js b/tez-ui/src/main/webapp/app/scripts/default-configs.js
index eba6a7e..e438bad 100644
--- a/tez-ui/src/main/webapp/app/scripts/default-configs.js
+++ b/tez-ui/src/main/webapp/app/scripts/default-configs.js
@@ -35,12 +35,13 @@ $.extend(true, App.Configs, {
     version: "0.7.0",
 
     timelineBaseUrl: getDefaultTimelineUrl(),
-    RMWebUrl: getDefaultRMWebUrl(),
+    RMWebUrl: getDefaultRMWebUrl()
   },
 
   restNamespace: {
     timeline: 'ws/v1/timeline',
-    applicationHistory: 'ws/v1/applicationhistory'
+    applicationHistory: 'ws/v1/applicationhistory',
+    aminfo: 'proxy/__app_id__/ws/v1/tez'
   },
 
   tables: {

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/helpers/number.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/helpers/number.js b/tez-ui/src/main/webapp/app/scripts/helpers/number.js
index c72edb3..912e8f5 100644
--- a/tez-ui/src/main/webapp/app/scripts/helpers/number.js
+++ b/tez-ui/src/main/webapp/app/scripts/helpers/number.js
@@ -110,6 +110,16 @@ App.Helpers.number = {
    */
   isValidInt: function(value) {
     return value % 1 == 0;
+  },
+
+  /**
+   * converts fraction to percentage.
+   * @param {number} fraction assumes < 1
+   * @return {float} fixed decimal point formatted percentage
+   */
+  fractionToPercentage: function(number, decimal) {
+    decimal = decimal || 2;
+    return parseFloat((number * 100).toFixed(decimal)) + ' %';
   }
 
 };
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js b/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js
index 568d526..7ce5f5e 100644
--- a/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js
+++ b/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js
@@ -71,8 +71,19 @@ App.PaginatedContentMixin = Em.Mixin.create({
     this.get('store').unloadAll(childEntityType);
     this.get('store').findQuery(childEntityType, this.getFilterProperties()).then(function(entities){
       that.set('entities', entities);
-      that.set('loading', false);
-    }).catch(function(jqXHR){
+      var loaders = [];
+      try {
+        var loader = Em.tryInvoke(that, 'loadAdditional');
+        if (!!loader) {
+          loaders.push(loader);
+        }
+      } catch(error) {
+        Em.Logger.error("Exception invoking additional load", error);
+      }
+      Em.RSVP.allSettled(loaders).then(function(){
+          that.set('loading', false);
+      });
+    }).catch(function(error){
       Em.Logger.error(error);
       var err = App.Helpers.misc.formatError(error, defaultErrMsg);
       var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js b/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
index a0943e2..d135174 100644
--- a/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
+++ b/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
@@ -279,6 +279,7 @@ var timelineJsonToVertexMap = {
   id: 'entity',
   name: 'otherinfo.vertexName',
   dagID: 'primaryfilters.TEZ_DAG_ID.0',
+  applicationId: 'primaryfilters.applicationId.0',
   processorClassName: 'processorClassName',
   counterGroups: 'counterGroups',
   inputs: 'inputs',
@@ -545,3 +546,6 @@ App.TezAppSerializer = App.TimelineSerializer.extend({
     return Em.JsonMapper.map(hash, timelineJsonToTezAppMap);
   },
 });
+
+App.VertexProgressSerializer = App.DagProgressSerializer = DS.RESTSerializer.extend({});
+

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/scripts/models/dag.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/models/dag.js b/tez-ui/src/main/webapp/app/scripts/models/dag.js
index cc87f5d..e050037 100644
--- a/tez-ui/src/main/webapp/app/scripts/models/dag.js
+++ b/tez-ui/src/main/webapp/app/scripts/models/dag.js
@@ -17,6 +17,10 @@
 
 App.Dag = App.AbstractEntity.extend({
 
+  idx: function() {
+    return this.get('id').split('_').splice(-1).pop();
+  }.property('id'),
+
   submittedTime: DS.attr('number'),
   
   // start time of the entity
@@ -93,9 +97,16 @@ App.Edge = DS.Model.extend({
 
 App.Vertex = DS.Model.extend({
   name: DS.attr('string'),
+  vertexIdx: function() {
+    return this.get('id').split('_').splice(-1).pop();
+  }.property('id'),
 
   dag: DS.belongsTo('dag'),
   dagID: DS.attr('string'),
+  applicationId: DS.attr('string'),
+  dagIdx: function() {
+    return this.get('dagID').split('_').splice(-1).pop();
+  }.property('dagID'),
 
   /**
    * State of this vertex. Should be one of constants defined in
@@ -323,6 +334,18 @@ App.Task = App.AbstractEntity.extend({
   counterGroups: DS.hasMany('counterGroup', { inverse: 'parent' })
 });
 
+App.DagProgress = DS.Model.extend({
+  progress: DS.attr('number'),
+  appId: DS.attr('string'),
+  dagIdx: DS.attr('number')
+});
+
+App.VertexProgress = DS.Model.extend({
+  progress: DS.attr('number'),
+  appId: DS.attr('string'),
+  dagIdx: DS.attr('string')
+});
+
 App.KVDatum = DS.Model.extend({
   key: DS.attr('string'),
   value: DS.attr('string'),

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/templates/dag/index.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/dag/index.hbs b/tez-ui/src/main/webapp/app/templates/dag/index.hbs
index 0d38686..7e9dbcb 100644
--- a/tez-ui/src/main/webapp/app/templates/dag/index.hbs
+++ b/tez-ui/src/main/webapp/app/templates/dag/index.hbs
@@ -17,42 +17,43 @@
 }}
 
 <div class='type-table fill-full margin-small-horizontal'>
-	<div class='align-left'>
-		<table class='detail-list'>
-			<tbody>
-				<tr>
-					<td>{{t 'common.status'}}</td>
-					<td>
-						{{status}}
-						<i {{bind-attr class=':task-status taskIconStatus'}}></i>
-					</td>
+  <div class='align-left'>
+    <table class='detail-list'>
+      <tbody>
+        <tr>
+          <td>{{t 'common.status'}}</td>
+          <td>
+            {{status}}
+            <i {{bind-attr class=':task-status taskIconStatus'}}></i>
+            {{#if progressStr}} {{bs-badge content=progressStr}}{{/if}}
+          </td>
           <td>
             {{#if hasFailedTasks}}
               <a href='{{unbound failedTasksLink}}'>FailedTasks</a>
             {{/if}}
           </td>
-				</tr>
-			</tbody>
-		</table>
-	</div>
-	<div class='align-right'>
-		<table class='detail-list'>
-			<tbody>
-				<tr>
-					<td>{{t 'common.time.start'}}</td>
-					<td>{{formatUnixTimestamp startTime}}</td>
-				</tr>
-				<tr>
-					<td>{{t 'common.time.end'}}</td>
-					<td>{{formatUnixTimestamp endTime}}</td>
-				</tr>
-				<tr>
-					<td>{{t 'common.time.duration'}}</td>
-					<td>{{formatDuration startTime endTime}}</td>
-				</tr>
-			</tbody>
-		</table>
-	</div>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+  <div class='align-right'>
+    <table class='detail-list'>
+      <tbody>
+        <tr>
+          <td>{{t 'common.time.start'}}</td>
+          <td>{{formatUnixTimestamp startTime}}</td>
+        </tr>
+        <tr>
+          <td>{{t 'common.time.end'}}</td>
+          <td>{{formatUnixTimestamp endTime}}</td>
+        </tr>
+        <tr>
+          <td>{{t 'common.time.duration'}}</td>
+          <td>{{formatDuration startTime endTime}}</td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
 </div>
 
 {{#if diagnostics}}

http://git-wip-us.apache.org/repos/asf/tez/blob/d51103db/tez-ui/src/main/webapp/app/templates/vertex/index.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/vertex/index.hbs b/tez-ui/src/main/webapp/app/templates/vertex/index.hbs
index cbb0c44..bc2e7ef 100644
--- a/tez-ui/src/main/webapp/app/templates/vertex/index.hbs
+++ b/tez-ui/src/main/webapp/app/templates/vertex/index.hbs
@@ -32,6 +32,7 @@
           <td>
             <i {{bind-attr class=':task-status iconStatus'}}></i>
             {{status}}
+            {{#if progressStr}} {{bs-badge content=progressStr}}{{/if}}
           </td>
         </tr>
         <tr>