KYLIN-1600 diagnosis project & job

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

Branch: refs/heads/1.5.x-HBase1.x
Commit: 136a333d3300d1e3cc68faafd117045a816c69cd
Parents: a1032bd
Author: Jason <jiat...@163.com>
Authored: Tue May 3 19:15:44 2016 +0800
Committer: Jason <jiat...@163.com>
Committed: Tue May 3 19:23:46 2016 +0800

----------------------------------------------------------------------
 webapp/app/index.html                  |   2 +
 webapp/app/js/controllers/admin.js     |  13 +-
 webapp/app/js/controllers/badQuery.js  |  68 +++++++
 webapp/app/js/controllers/job.js       |  22 ++-
 webapp/app/js/model/jobConfig.js       |  11 +-
 webapp/app/js/services/badQuery.js     |  23 +++
 webapp/app/partials/admin/admin.html   | 278 +++++++++++++++-------------
 webapp/app/partials/jobs/badQuery.html |  53 ++++++
 webapp/app/partials/jobs/jobList.html  | 140 ++++++++++++++
 webapp/app/partials/jobs/jobs.html     | 169 +++--------------
 10 files changed, 498 insertions(+), 281 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index e109215..6286667 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -160,6 +160,7 @@
 
 <!--New GUI-->
 <script src="js/model/modelsManager.js"></script>
+<script src="js/services/badQuery.js"></script>
 
 <script src="js/controllers/page.js"></script>
 <script src="js/controllers/index.js"></script>
@@ -188,6 +189,7 @@
 <script src="js/controllers/modelEdit.js"></script>
 
 <script src="js/controllers/streamingConfig.js"></script>
+<script src="js/controllers/badQuery.js"></script>
 
 <!--New GUI-->
 <script src="js/controllers/models.js"></script>

http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/js/controllers/admin.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/admin.js 
b/webapp/app/js/controllers/admin.js
index ac96729..e77729a 100644
--- a/webapp/app/js/controllers/admin.js
+++ b/webapp/app/js/controllers/admin.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('AdminCtrl', function ($scope, AdminService, CacheService, 
TableService, loadingRequest, MessageService, $modal, SweetAlert,kylinConfig) {
+KylinApp.controller('AdminCtrl', function ($scope, AdminService, CacheService, 
TableService, loadingRequest, MessageService, $modal, 
SweetAlert,kylinConfig,ProjectModel,$window) {
   $scope.configStr = "";
   $scope.envStr = "";
 
@@ -247,6 +247,17 @@ KylinApp.controller('AdminCtrl', function ($scope, 
AdminService, CacheService, T
     }
   };
 
+  $scope.downloadBadQueryFiles = function(){
+    var _project = ProjectModel.selectedProject;
+    if (_project == null){
+      SweetAlert.swal('', "No project selected.", 'info');
+      return;
+    }
+    var downloadUrl = Config.service.url + 
'diag/project/'+_project+'/download';
+    $window.open(downloadUrl);
+  }
+
+
   $scope.getEnv();
   $scope.getConfig();
 });

http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/js/controllers/badQuery.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/badQuery.js 
b/webapp/app/js/controllers/badQuery.js
new file mode 100644
index 0000000..65cf65b
--- /dev/null
+++ b/webapp/app/js/controllers/badQuery.js
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+'use strict';
+
+KylinApp
+    .controller('BadQueryCtrl', function ($scope,BadQueryService, $q, 
$routeParams, $interval, $modal, ProjectService, MessageService, 
JobService,SweetAlert,ProjectModel,$window) {
+
+      $scope.badQueryList = [];
+
+      $scope.bqstate={
+        loading:true,
+        filterAttr: 'last_modified',
+        filterReverse: true,
+        reverseColumn: 'last_modified'
+      }
+
+      $scope.list = function(){
+        var _project = ProjectModel.selectedProject;
+          $scope.badQueryList = [];
+        if (_project == null){
+          $scope.bqstate.loading = false;
+          return;
+        }
+        BadQueryService.list({
+          entity:_project
+        }, function (queryList) {
+          angular.forEach(queryList, function (query) {
+            $scope.badQueryList.push(query);
+          })
+            $scope.bqstate.loading = false;
+        }, function (e) {
+          $scope.bqstate.loading = false;
+          if (e.data && e.data.exception) {
+            var message = e.data.exception;
+            var msg = !!(message) ? message : 'Failed to load query.';
+            SweetAlert.swal('Oops...', msg, 'error');
+          } else {
+            SweetAlert.swal('Oops...', "Failed to load query.", 'error');
+          }
+        });
+      }
+
+      $scope.list();
+
+      $scope.$watch('projectModel.selectedProject', function (newValue, 
oldValue) {
+        if(newValue!=oldValue||newValue==null){
+          $scope.list();
+        }
+
+      });
+
+    });

http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/js/controllers/job.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/job.js b/webapp/app/js/controllers/job.js
index c859c12..ae963c3 100644
--- a/webapp/app/js/controllers/job.js
+++ b/webapp/app/js/controllers/job.js
@@ -19,7 +19,7 @@
 'use strict';
 
 KylinApp
-    .controller('JobCtrl', function ($scope, $q, $routeParams, $interval, 
$modal, ProjectService, MessageService, 
JobService,SweetAlert,loadingRequest,UserService,jobConfig,JobList) {
+    .controller('JobCtrl', function ($scope, $q, $routeParams, $interval, 
$modal, ProjectService, MessageService, 
JobService,SweetAlert,loadingRequest,UserService,jobConfig,JobList,$window) {
 
         $scope.jobList = JobList;
         JobList.removeAll();
@@ -41,6 +41,17 @@ KylinApp
 
 
 
+        $scope.tabs=[
+          {
+            "title":"Jobs",
+            "active":true
+          },
+          {
+            "title": "Slow Queries",
+            "active": false
+          }
+        ]
+
         // projectName from page ctrl
         $scope.state = {loading: false, refreshing: false, filterAttr: 
'last_modified', filterReverse: true, reverseColumn: 'last_modified', 
projectName:$scope.projectModel.selectedProject};
 
@@ -166,6 +177,15 @@ KylinApp
             });
         }
 
+      $scope.diagnosisJob =function(job) {
+        if (!job){
+          SweetAlert.swal('', "No job selected.", 'info');
+          return;
+        }
+        var downloadUrl = Config.service.url + 
'diag/job/'+job.uuid+'/download';
+        $window.open(downloadUrl);
+      }
+
         $scope.openModal = function () {
             if (angular.isDefined($scope.state.selectedStep)) {
                 if ($scope.state.stepAttrToShow == "output") {

http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/js/model/jobConfig.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/jobConfig.js b/webapp/app/js/model/jobConfig.js
index af7044c..ae0a306 100644
--- a/webapp/app/js/model/jobConfig.js
+++ b/webapp/app/js/model/jobConfig.js
@@ -38,6 +38,15 @@ KylinApp.constant('jobConfig', {
     {attr: 'progress', name: 'Progress'},
     {attr: 'last_modified', name: 'Last Modified Time'},
     {attr: 'duration', name: 'Duration'}
-  ]
+  ],
+  queryitems: [
+  {attr: 'server', name: 'Server'},
+  {attr: 'sql', name: 'Sql'},
+  {attr: 'adj', name: 'Description'},
+  {attr: 'running_seconds', name: 'Running Seconds'},
+  {attr: 'start_time', name: 'Start Time'},
+  {attr: 'last_modified', name: 'Last Modified'},
+  {attr: 'thread', name: 'Thread'}
+]
 
 });

http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/js/services/badQuery.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/badQuery.js 
b/webapp/app/js/services/badQuery.js
new file mode 100755
index 0000000..7734da1
--- /dev/null
+++ b/webapp/app/js/services/badQuery.js
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+KylinApp.factory('BadQueryService', ['$resource', function ($resource, config) 
{
+  return $resource(Config.service.url + 'diag/:entity/:id/:action', {}, {
+    list: {method: 'GET', params: {action:'sql'}, cache: false, isArray: true}
+  });
+}]);

http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/partials/admin/admin.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/admin/admin.html 
b/webapp/app/partials/admin/admin.html
index 1411978..673187f 100644
--- a/webapp/app/partials/admin/admin.html
+++ b/webapp/app/partials/admin/admin.html
@@ -17,157 +17,169 @@
 -->
 
 <div class="container" style="padding-top: 80px">
-    <div class="col-md-5">
-        <div>
-            <h3>Server Config <button class="btn btn-xs btn-success" 
ng-click="getConfig()"><i class="fa fa-refresh"></i></button></h3>
-        </div>
-        <div style="padding-top: 10px">
-            <pre>{{configStr}}</pre>
-        </div>
+  <div class="col-md-5">
+    <div>
+      <h3>Server Config <button class="btn btn-xs btn-success" 
ng-click="getConfig()"><i class="fa fa-refresh"></i></button></h3>
     </div>
+    <div style="padding-top: 10px">
+      <pre>{{configStr}}</pre>
+    </div>
+  </div>
 
-    <div class="col-md-5">
-        <div>
-            <h3>Server Environment <button class="btn btn-xs btn-success" 
ng-click="getEnv()"><i class="fa fa-refresh"></i></button></h3>
-        </div>
-        <div style="padding-top: 10px">
-            <pre>{{envStr}}</pre>
-        </div>
+  <div class="col-md-5">
+    <div>
+      <h3>Server Environment <button class="btn btn-xs btn-success" 
ng-click="getEnv()"><i class="fa fa-refresh"></i></button></h3>
+    </div>
+    <div style="padding-top: 10px">
+      <pre>{{envStr}}</pre>
     </div>
+  </div>
 
-    <div class="col-md-2">
-        <div>
-            <h3>Actions</h3>
-        </div>
-        <div style="padding-top: 10px;width: 180px;">
-            <button class="btn btn-primary btn-lg btn-block" 
ng-click="reloadMeta()">
-                <label tooltip="Reload all metadata and clean cache" 
style="cursor: pointer;">Reload Metadata</label>
-            </button>
-        </div>
-        <div style="padding-top: 10px;width: 180px;">
-            <button class="btn btn-primary btn-lg btn-block" 
ng-click="calCardinality()">
-                <label tooltip="Calculate cardinality of tables" 
style="cursor: pointer;">Calculate Cardinality</label>
-            </button>
-        </div>
-        <div style="padding-top: 10px;width: 180px;" ng-if="false">
-            <button class="btn btn-success btn-lg btn-block" 
ng-click="cleanStorage()">
-                <label tooltip="Clean unused HDFS and HBASE space" 
style="cursor: pointer;">Clean Up Storage</label>
-            </button>
-        </div>
-        <div style="padding-top: 10px;width: 180px;" ng-if="isCacheEnabled()">
-            <button class="btn btn-primary btn-lg btn-block" 
ng-click="disableCache()">
-                <label tooltip="Disable Query Cache" style="cursor: 
pointer;">Disable Cache</label>
-            </button>
-        </div>
-      <div style="padding-top: 10px;width: 180px;" ng-if="!isCacheEnabled()">
-        <button class="btn btn-primary btn-lg btn-block" 
ng-click="enableCache()">
-          <label tooltip="Enable Query Cache" style="cursor: pointer;">Enable 
Cache</label>
-        </button>
-      </div>
-      <div style="padding-top: 10px;width: 180px;">
-            <button class="btn btn-primary btn-lg btn-block" 
ng-click="toSetConfig()">
-                <label tooltip="Update Server Config" style="cursor: 
pointer;">Set Config</label>
-            </button>
-        </div>
-        <div>
-            <h3>Links</h3>
-        </div>
-        <div style="padding-top: 10px" 
ng-if="config.reference_links['hadoop']">
-            <a class="label-lg label-yellow 
arrowed-right"style="font-size:18px;" tooltip="Cluster Resource Monitoring" 
href="{{config.reference_links['hadoop'].link}}" >
-                Hadoop Monitor
-            </a>
-        </div>
+  <div class="col-md-2">
+    <div>
+      <h3>Actions</h3>
+    </div>
+    <div style="padding-top: 10px;width: 260px;">
+      <!--<button class="btn btn-primary btn-lg btn-block" 
ng-click="reloadMeta()">-->
+      <!--<label tooltip="Reload all metadata and clean cache" style="cursor: 
pointer;">Reload Metadata</label>-->
+      <!--</button>-->
+      <a  class="btn btn-primary btn-lg btn-block" tooltip="Reload all 
metadata and clean cache" ng-click="reloadMeta()">Reload Metadata</a>
+    </div>
+    <div style="padding-top: 10px;width: 260px;">
+      <a ng-click="calCardinality();" tooltip="Calculate cardinality of 
tables" class="btn btn-primary btn-lg btn-block">Calculate Cardinality</a>
+
+      <!--<button class="btn btn-primary btn-lg btn-block" 
ng-click="calCardinality()">-->
+      <!--<label tooltip="Calculate cardinality of tables" style="cursor: 
pointer;">Calculate Cardinality</label>-->
+
+      <!--</button>-->
+    </div>
+    <div style="padding-top: 10px;width: 260px;" ng-if="false">
+      <!--<button class="btn btn-success btn-lg btn-block" 
ng-click="cleanStorage()">-->
+      <!--<label tooltip="Clean unused HDFS and HBASE space" style="cursor: 
pointer;">Clean Up Storage</label>-->
+      <!--</button>-->
+      <a class="btn btn-success btn-lg btn-block" tooltip="Clean unused HDFS 
and HBASE space" ng-click="cleanStorage()">Clean Up Storage</a>
+    </div>
+    <div style="padding-top: 10px;width: 260px;" ng-if="isCacheEnabled()">
+      <!--<button class="btn btn-primary btn-lg btn-block" 
ng-click="disableCache()">-->
+      <!--<label tooltip="Disable Query Cache" style="cursor: 
pointer;">Disable Cache</label>-->
+      <!--</button>-->
+      <a class="btn btn-primary btn-lg btn-block" 
ng-click="disableCache()">Disable Cache</a>
+    </div>
+    <div style="padding-top: 10px;width: 260px;" ng-if="!isCacheEnabled()">
+      <!--<button class="btn btn-primary btn-lg btn-block" 
ng-click="enableCache()">-->
+      <!--<label tooltip="Enable Query Cache" style="cursor: pointer;">Enable 
Cache</label>-->
+      <!--</button>-->
+      <a  class="btn btn-primary btn-lg btn-block" tooltip="Enable Query 
Cache" ng-click="enableCache()">Enable Cache</a>
+    </div>
+    <div style="padding-top: 10px;width: 260px;">
+      <!--<button class="btn btn-primary btn-lg btn-block" 
ng-click="toSetConfig()">-->
+      <!--<label tooltip="Update Server Config" style="cursor: pointer;">Set 
Config</label>-->
+      <!--</button>-->
+      <a class="btn btn-primary btn-lg btn-block" tooltip="Update Server 
Config"  class="btn btn-primary btn-lg"  ng-click="toSetConfig()">Set Config</a>
+    </div>
+    <div style="padding-top: 10px;width: 260px;">
+      <a ng-click="downloadBadQueryFiles();" tooltip="Download selected 
project Diagnosis Info" class="btn btn-primary btn-lg btn-block"><i class="fa 
fa-ambulance"></i> Diagnosis</a>
+    </div>
+
+    <div>
+      <h3>Links</h3>
+    </div>
+    <div style="padding-top: 10px" ng-if="config.reference_links['hadoop']">
+      <a class="label-lg label-yellow arrowed-right"style="font-size:18px;" 
tooltip="Cluster Resource Monitoring" 
href="{{config.reference_links['hadoop'].link}}" >
+        Hadoop Monitor
+      </a>
     </div>
+  </div>
 </div>
 
 <script type="text/ng-template" id="calCardinality.html">
-    <div class="modal-header">
-        <h4>Load Hive Table Metadata</h4>
-    </div>
-    <div class="modal-body load-hive-metawrapper">
-        <label for="table">Table Name:</label>
-        <input ng-model="$parent.tableName" class="form-control" id="table" 
placeholder="table1,table2"/>
-        <label>Delimiter:</label>
+  <div class="modal-header">
+    <h4>Load Hive Table Metadata</h4>
+  </div>
+  <div class="modal-body load-hive-metawrapper">
+    <label for="table">Table Name:</label>
+    <input ng-model="$parent.tableName" class="form-control" id="table" 
placeholder="table1,table2"/>
+    <label>Delimiter:</label>
 
-        <div class="radio">
-            <label>
-                <input type="radio" name="deliRadios" 
data-ng-model="$parent.delimiter" ng-value="0">default
-                -- System will try to get the format from hive metadata, if 
you are not sure, please choose the
-                "default".
-            </label>
-        </div>
-        <div class="radio">
-            <label>
-                <input type="radio" name="deliRadios" 
data-ng-model="$parent.delimiter" ng-value="1">\177
-            </label>
-        </div>
-        <div class="radio">
-            <label>
-                <input type="radio" name="deliRadios" 
data-ng-model="$parent.delimiter" ng-value="2">tab
-            </label>
-        </div>
-        <label>Format:</label>
+    <div class="radio">
+      <label>
+        <input type="radio" name="deliRadios" 
data-ng-model="$parent.delimiter" ng-value="0">default
+        -- System will try to get the format from hive metadata, if you are 
not sure, please choose the
+        "default".
+      </label>
+    </div>
+    <div class="radio">
+      <label>
+        <input type="radio" name="deliRadios" 
data-ng-model="$parent.delimiter" ng-value="1">\177
+      </label>
+    </div>
+    <div class="radio">
+      <label>
+        <input type="radio" name="deliRadios" 
data-ng-model="$parent.delimiter" ng-value="2">tab
+      </label>
+    </div>
+    <label>Format:</label>
 
-        <div class="radio">
-            <label>
-                <input type="radio" name="formatRadios" 
data-ng-model="$parent.format" ng-value="0">default
-                -- System will try to get the format from hive metadata, if 
you are not sure, please choose the
-                "default".
-            </label>
-        </div>
-        <div class="radio">
-            <label>
-                <input type="radio" name="formatRadios" 
data-ng-model="$parent.format" ng-value="1">text
-            </label>
-        </div>
-        <div class="radio">
-            <label>
-                <input type="radio" name="formatRadios" 
data-ng-model="$parent.format" ng-value="2">sequence
-            </label>
-        </div>
+    <div class="radio">
+      <label>
+        <input type="radio" name="formatRadios" data-ng-model="$parent.format" 
ng-value="0">default
+        -- System will try to get the format from hive metadata, if you are 
not sure, please choose the
+        "default".
+      </label>
     </div>
-    <div class="modal-footer">
-        <button class="btn btn-primary" ng-click="calculate()">Sync</button>
-        <button class="btn btn-primary" ng-click="cancel()">Cancel</button>
+    <div class="radio">
+      <label>
+        <input type="radio" name="formatRadios" data-ng-model="$parent.format" 
ng-value="1">text
+      </label>
+    </div>
+    <div class="radio">
+      <label>
+        <input type="radio" name="formatRadios" data-ng-model="$parent.format" 
ng-value="2">sequence
+      </label>
     </div>
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-primary" ng-click="calculate()">Sync</button>
+    <button class="btn btn-primary" ng-click="cancel()">Cancel</button>
+  </div>
 </script>
 
 <script type="text/ng-template" id="updateConfig.html">
-    <ng-form name="config_update_form">
-        <div class="modal-header">
-            <h4>Update Config</h4>
-        </div>
-        <div class="modal-body">
-            <div class="form-group">
-                <label><b>Key</b></label>
+  <ng-form name="config_update_form">
+    <div class="modal-header">
+      <h4>Update Config</h4>
+    </div>
+    <div class="modal-body">
+      <div class="form-group">
+        <label><b>Key</b></label>
 
-                <div class="clearfix">
-                    <input name="key_input" type="text" class="form-control" 
placeholder="Config Key.."
-                           ng-model="state.key"
-                           required/>
+        <div class="clearfix">
+          <input name="key_input" type="text" class="form-control" 
placeholder="Config Key.."
+                 ng-model="state.key"
+                 required/>
 
-                    <p class="text-warning"
-                       ng-show="config_update_form.key_input.$invalid && 
!config_update_form.key_input.$pristine">&nbsp;&nbsp;Key
-                        is required.</p>
-                </div>
-            </div>
-            <div class="form-group">
-                <label><b>Value</b></label>
+          <p class="text-warning"
+             ng-show="config_update_form.key_input.$invalid && 
!config_update_form.key_input.$pristine">&nbsp;&nbsp;Key
+            is required.</p>
+        </div>
+      </div>
+      <div class="form-group">
+        <label><b>Value</b></label>
 
-                <div class="clearfix">
-                    <input name="value_input" type="text" class="form-control" 
placeholder="Config Value.."
-                           ng-model="state.value"
-                           required/>
+        <div class="clearfix">
+          <input name="value_input" type="text" class="form-control" 
placeholder="Config Value.."
+                 ng-model="state.value"
+                 required/>
 
-                    <p class="text-warning"
-                       ng-show="config_update_form.value_input.$invalid && 
!config_update_form.value_input.$pristine">&nbsp;&nbsp;Value
-                        is required.</p>
-                </div>
-            </div>
-        </div>
-        <div class="modal-footer">
-            <button class="btn btn-primary" ng-click="update()">Update</button>
-            <button class="btn btn-primary" ng-click="cancel()">Cancel</button>
+          <p class="text-warning"
+             ng-show="config_update_form.value_input.$invalid && 
!config_update_form.value_input.$pristine">&nbsp;&nbsp;Value
+            is required.</p>
         </div>
-    </ng-form>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <button class="btn btn-primary" ng-click="update()">Update</button>
+      <button class="btn btn-primary" ng-click="cancel()">Cancel</button>
+    </div>
+  </ng-form>
 </script>

http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/partials/jobs/badQuery.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/badQuery.html 
b/webapp/app/partials/jobs/badQuery.html
new file mode 100644
index 0000000..73806a7
--- /dev/null
+++ b/webapp/app/partials/jobs/badQuery.html
@@ -0,0 +1,53 @@
+
+<div class="row" style="margin-top:15px;" ng-controller="BadQueryCtrl">
+
+  <!--No Job-->
+  <div ng-if="!bqstate.loading && badQueryList.length==0">
+    <div ng-if="projectModel.selectedProject==null" no-result text="No project 
selected"></div>
+    <div ng-if="projectModel.selectedProject!==null" no-result text="No Slow 
Query."></div>
+  </div>
+  <!--Loading Jobs-->
+  <div ng-if="bqstate.loading">
+    <loading text="Loading Queries ..."></loading>
+  </div>
+  <!--Jobs Table Content-->
+  <table ng-if="badQueryList.length>0" class="table table-striped 
table-bordered table-hover dataTable no-footer">
+    <thead>
+    <tr style="cursor: pointer">
+      <th ng-repeat="queryitem in jobConfig.queryitems"
+          ng-click="bqstate.filterAttr= 
queryitem.attr;bqstate.reverseColumn=queryitem.attr;bqstate.filterReverse=!bqstate.filterReverse;
 ">
+        {{queryitem.name}}
+        <i ng-if="bqstate.reverseColumn!= queryitem.attr"
+           class="fa fa-unsorted"></i>
+        <i ng-if="bqstate.reverseColumn== queryitem.attr && 
!bqstate.filterReverse"
+           class="fa fa-sort-asc"></i>
+        <i ng-if="bqstate.reverseColumn== queryitem.attr && 
bqstate.filterReverse"
+           class="fa fa-sort-desc"></i>
+      </th>
+    </tr>
+    </thead>
+    <tbody  class="odd table table-striped table-bordered table-hover 
dataTable no-footer">
+    <tr
+      ng-repeat="bquery in badQueryList | 
orderObjectBy:bqstate.filterAttr:bqstate.filterReverse"
+      ng-class="{accordion:true}" ng-click="bqstate.selectedQuery = bquery"
+      style="cursor: pointer"
+      class="{{bquery==bqstate.selectedQuery? 'tr-highlight': ''}} 
table-bordered">
+      <td style="max-width: 350px;word-wrap: break-word;word-break: normal;">
+        {{bquery.server}}
+      </td>
+      <td>{{bquery.sql}}</td>
+      <td>
+        {{bquery.adj}}
+      </td>
+      <td>{{bquery.running_seconds + '(s)'}}</td>
+      <td>{{bquery.start_time |utcToConfigTimeZone}}</td>
+      <td>
+        {{bquery.last_modified |utcToConfigTimeZone}}
+      </td>
+      <td>
+        {{bquery.thread}}
+      </td>
+    </tr>
+    </tbody>
+  </table>
+</div>

http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/partials/jobs/jobList.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/jobList.html 
b/webapp/app/partials/jobs/jobList.html
new file mode 100644
index 0000000..366a1bf
--- /dev/null
+++ b/webapp/app/partials/jobs/jobList.html
@@ -0,0 +1,140 @@
+<!--Jobs Table-->
+<div class="row" style="margin-top:15px;" ng-controller="JobCtrl">
+
+  <div ng-class="{'col-xs-8': state.showSteps, 'col-xs-12': !state.showSteps}">
+    <div  class="dataTables_wrapper form-inline no-footer" >
+      <!--Jobs Table Header-->
+      <div class="row">
+
+        <!--Cube Name: -->
+        <div class="col-xs-3">
+          <form class="" ng-submit="jobList.removeAll();reload()" 
style="display: inline" >
+              <span class="input-icon input-icon-right nav-search" 
style="font-size:14px;"><b>Cube Name:</b>
+                  <input type="text" placeholder="Filter ..." 
class="nav-search-input" ng-model="cubeName" />
+                  <i class="ace-icon fa fa-search blue" 
ng-click="jobList.removeAll();reload()"></i>
+              </span>
+          </form>
+        </div>
+
+        <!--<div class="col-xs-2"><label 
class="table-header-text">Jobs</label></div>-->
+        <div class="col-xs-9">
+          <!--STATUS-->
+          <div class="pull-right">
+            <!--Job History Time Filter-->
+            <label>Jobs in:
+              <select data-ng-model="timeFilter"
+                      data-ng-options="s.name for s in jobConfig.timeFilter">
+              </select>
+            </label>
+            <label ng-repeat="s in jobConfig.allStatus" 
class="checkbox-inline" >
+              <input  type="checkbox"
+                      value="{{s.name}}"
+                      ng-checked="status.indexOf(s) > -1"
+                      ng-click="toggleSelection(s);" />{{s.name}}
+            </label>
+            <!--Refresh Jobs-->
+            <button class="btn btn-success btn-xs" style="margin-left: 10px" 
ng-click="jobList.removeAll();reload();"><i class="fa fa-refresh"></i></button>
+          </div>
+        </div>
+      </div>
+      <!--No Job-->
+      <div ng-if="!state.loading && getLength(jobList.jobs)==0">
+        <div no-result text="No Job."></div>
+      </div>
+      <!--Loading Jobs-->
+      <div ng-if="state.loading">
+        <loading text="Loading Jobs ..."></loading>
+      </div>
+      <!--Jobs Table Content-->
+      <table ng-if="getLength(jobList.jobs)>0" class="table table-striped 
table-bordered table-hover dataTable no-footer">
+        <thead>
+        <tr style="cursor: pointer">
+          <th ng-repeat="theaditem in jobConfig.theaditems"
+              ng-click="state.filterAttr= 
theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;
 ">
+            {{theaditem.name}}
+            <i ng-if="state.reverseColumn!= theaditem.attr"
+               class="fa fa-unsorted"></i>
+            <i ng-if="state.reverseColumn== theaditem.attr && 
!state.filterReverse"
+               class="fa fa-sort-asc"></i>
+            <i ng-if="state.reverseColumn== theaditem.attr && 
state.filterReverse"
+               class="fa fa-sort-desc"></i>
+          </th>
+          <th>Actions</th>
+          <th></th>
+        </tr>
+        </thead>
+        <tbody  class="odd table table-striped table-bordered table-hover 
dataTable no-footer">
+        <tr
+          ng-repeat="(uuid,job) in jobList.jobs | 
orderObjectBy:state.filterAttr:state.filterReverse"
+          ng-class="{accordion:true}" ng-click="state.selectedJob = job"
+          ng-dblclick="state.showSteps= !state.showSteps; state.selectedJob = 
job"
+          style="cursor: pointer"
+          class="{{job==state.selectedJob? 'tr-highlight': ''}} 
table-bordered">
+          <td style="max-width: 350px;word-wrap: break-word;word-break: 
normal;">
+            {{ job.name}}
+          </td>
+          <td>{{ job.related_cube}}</td>
+          <td>
+            <div ng-switch on="job.job_status">
+              <div ng-switch-when="ERROR" tooltip="ERROR">
+                <progressbar class="progress-striped" value="job.progress" 
type="danger">
+                  {{job.job_status}}
+                </progressbar>
+              </div>
+              <div ng-switch-when="FINISHED" tooltip="FINISHED">
+                <progressbar class="progress-striped" value="job.progress" 
type="success">
+                  {{job.progress}}%
+                </progressbar>
+              </div>
+              <div ng-switch-when="PENDING" tooltip="PENDING">
+                <progressbar class="progress-striped active" 
value="job.progress"
+                             type="pending">{{job.job_status}}
+                </progressbar>
+              </div>
+              <div ng-switch-when="RUNNING" tooltip="RUNNING">
+                <progressbar class="progress-striped active" 
value="job.progress"
+                             type="info">{{job.progress | number:2}}%
+                </progressbar>
+              </div>
+              <div ng-switch-when="DISCARDED" tooltip="DISCARDED">
+                <progressbar class="progress-striped" value="job.progress" 
type="inverse">
+                  {{job.progress | number:2}}%
+                </progressbar>
+              </div>
+            </div>
+          </td>
+          <td>{{ job.last_modified == 0 ? '' : (job.last_modified 
|utcToConfigTimeZone)}}</td>
+          <td>{{(job.duration/60 | number:2) + ' mins'}}</td>
+          <td>
+            <div class="btn-group"
+                 ng-if="job.job_status!='DISCARDED' && 
job.job_status!='FINISHED'">
+              <button type="button" class="btn btn-default btn-xs 
dropdown-toggle"
+                      data-toggle="dropdown">
+                Action <span class="ace-icon fa fa-caret-down 
icon-on-right"></span>
+              </button>
+              <ul class="dropdown-menu" role="menu">
+                <li ng-if="job.job_status=='ERROR'"><a 
ng-click="resume(job)">Resume</a></li>
+                <li ng-if="job.job_status=='RUNNING' || job.job_status=='NEW' 
|| job.job_status=='PENDING' || job.job_status=='ERROR'">
+                  <a ng-click="cancel(job)">Discard</a>
+                  <a ng-click="diagnosisJob(job)">Diagnosis</a>
+                </li>
+              </ul>
+            </div>
+            <span ng-if="job.job_status=='DISCARDED' || 
job.job_status=='FINISHED'">N/A</span>
+          </td>
+          <td>
+            <button class="btn btn-info btn-xs" ng-click="state.showSteps= 
!state.showSteps; state.selectedJob = job">
+              <i class="fa fa-chevron-circle-right"></i>
+            </button>
+          </td>
+        </tr>
+        </tbody>
+      </table>
+    </div>
+
+    <kylin-pagination data="jobList.jobs" load-func="list" action="action"/>
+  </div>
+  <div class="col-xs-4" ng-if="state.showSteps">
+    <div ng-include src="'partials/jobs/job_steps.html'"></div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/kylin/blob/136a333d/webapp/app/partials/jobs/jobs.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/jobs.html 
b/webapp/app/partials/jobs/jobs.html
index cc5840b..e2aa3f4 100644
--- a/webapp/app/partials/jobs/jobs.html
+++ b/webapp/app/partials/jobs/jobs.html
@@ -17,154 +17,33 @@
 -->
 
 <div class="page-header row">
-    <!--Project: -->
-    <div class="col-xs-3">
-        <form ng-if="userService.isAuthorized()">
-            <div class="form-group" 
ng-if="userService.hasRole('ROLE_MODELER')" >
-                <a class="btn btn-xs btn-info" href="projects" tooltip="Manage 
Project"><i class="fa fa-gears"></i></a>
-              <a class="btn btn-xs btn-primary" 
ng-if="userService.hasRole('ROLE_MODELER')" style="width: 29px" tooltip="Add 
Project" ng-click="toCreateProj()">
-                    <i class="fa fa-plus"></i>
-                </a>
-            </div>
-        </form>
-    </div>
-    <!--Cube Name: -->
-    <div class="col-xs-3">
-        <form class="" ng-submit="jobList.removeAll();reload()" 
style="display: inline" >
-            <span class="input-icon input-icon-right nav-search" 
style="font-size:14px;"><b>Cube Name:</b>
-                <input type="text" placeholder="Filter ..." 
class="nav-search-input" ng-model="cubeName" />
-                <i class="ace-icon fa fa-search blue" 
ng-click="jobList.removeAll();reload()"></i>
-            </span>
-        </form>
-    </div>
+  <!--Project: -->
+  <div class="col-xs-3">
+    <form ng-if="userService.isAuthorized()">
+      <div class="form-group" ng-if="userService.hasRole('ROLE_MODELER')" >
+        <a class="btn btn-xs btn-info" href="projects" tooltip="Manage 
Project"><i class="fa fa-gears"></i></a>
+        <a class="btn btn-xs btn-primary" 
ng-if="userService.hasRole('ROLE_MODELER')" style="width: 29px" tooltip="Add 
Project" ng-click="toCreateProj()">
+          <i class="fa fa-plus"></i>
+        </a>
+      </div>
+    </form>
+  </div>
 </div>
 
-<!--Jobs Table-->
-<div class="row">
-    <div ng-class="{'col-xs-8': state.showSteps, 'col-xs-12': 
!state.showSteps}">
-        <div  class="dataTables_wrapper form-inline no-footer" >
-            <!--Jobs Table Header-->
-            <div class="row">
-                <div class="col-xs-2"><label 
class="table-header-text">Jobs</label></div>
-                <div class="col-xs-10">
-                    <!--STATUS-->
-                    <div class="pull-right">
-                      <!--Job History Time Filter-->
-                      <label>Jobs in:
-                        <select data-ng-model="timeFilter"
-                                data-ng-options="s.name for s in 
jobConfig.timeFilter">
-                        </select>
-                      </label>
-                      <label ng-repeat="s in jobConfig.allStatus" 
class="checkbox-inline" >
-                        <input  type="checkbox"
-                                value="{{s.name}}"
-                                ng-checked="status.indexOf(s) > -1"
-                                ng-click="toggleSelection(s);" />{{s.name}}
-                      </label>
-                      <!--Refresh Jobs-->
-                      <button class="btn btn-success btn-xs" 
style="margin-left: 10px" ng-click="jobList.removeAll();reload();"><i class="fa 
fa-refresh"></i></button>
-                    </div>
-                </div>
-            </div>
-            <!--No Job-->
-            <div ng-if="!state.loading && getLength(jobList.jobs)==0">
-              <div no-result text="No Job."></div>
-            </div>
-            <!--Loading Jobs-->
-            <div ng-if="state.loading">
-              <loading text="Loading Jobs ..."></loading>
-            </div>
-            <!--Jobs Table Content-->
-            <table ng-if="getLength(jobList.jobs)>0" class="table 
table-striped table-bordered table-hover dataTable no-footer">
-                <thead>
-                    <tr style="cursor: pointer">
-                        <th ng-repeat="theaditem in jobConfig.theaditems"
-                            ng-click="state.filterAttr= 
theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;
 ">
-                            {{theaditem.name}}
-                            <i ng-if="state.reverseColumn!= theaditem.attr"
-                               class="fa fa-unsorted"></i>
-                            <i ng-if="state.reverseColumn== theaditem.attr && 
!state.filterReverse"
-                               class="fa fa-sort-asc"></i>
-                            <i ng-if="state.reverseColumn== theaditem.attr && 
state.filterReverse"
-                               class="fa fa-sort-desc"></i>
-                        </th>
-                        <th>Actions</th>
-                        <th></th>
-                    </tr>
-                </thead>
-                <tbody  class="odd table table-striped table-bordered 
table-hover dataTable no-footer">
-                <tr
-                    ng-repeat="(uuid,job) in jobList.jobs | 
orderObjectBy:state.filterAttr:state.filterReverse"
-                    ng-class="{accordion:true}" ng-click="state.selectedJob = 
job"
-                    ng-dblclick="state.showSteps= !state.showSteps; 
state.selectedJob = job"
-                    style="cursor: pointer"
-                    class="{{job==state.selectedJob? 'tr-highlight': ''}} 
table-bordered">
-                    <td style="max-width: 350px;word-wrap: 
break-word;word-break: normal;">
-                        {{ job.name}}
-                    </td>
-                    <td>{{ job.related_cube}}</td>
-                    <td>
-                        <div ng-switch on="job.job_status">
-                            <div ng-switch-when="ERROR" tooltip="ERROR">
-                                <progressbar class="progress-striped" 
value="job.progress" type="danger">
-                                    {{job.job_status}}
-                                </progressbar>
-                            </div>
-                            <div ng-switch-when="FINISHED" tooltip="FINISHED">
-                                <progressbar class="progress-striped" 
value="job.progress" type="success">
-                                    {{job.progress}}%
-                                </progressbar>
-                            </div>
-                            <div ng-switch-when="PENDING" tooltip="PENDING">
-                                <progressbar class="progress-striped active" 
value="job.progress"
-                                             type="pending">{{job.job_status}}
-                                </progressbar>
-                            </div>
-                            <div ng-switch-when="RUNNING" tooltip="RUNNING">
-                                <progressbar class="progress-striped active" 
value="job.progress"
-                                             type="info">{{job.progress | 
number:2}}%
-                                </progressbar>
-                            </div>
-                            <div ng-switch-when="DISCARDED" 
tooltip="DISCARDED">
-                                <progressbar class="progress-striped" 
value="job.progress" type="inverse">
-                                    {{job.progress | number:2}}%
-                                </progressbar>
-                            </div>
-                        </div>
-                    </td>
-                    <td>{{ job.last_modified == 0 ? '' : (job.last_modified 
|utcToConfigTimeZone)}}</td>
-                    <td>{{(job.duration/60 | number:2) + ' mins'}}</td>
-                    <td>
-                        <div class="btn-group"
-                             ng-if="job.job_status!='DISCARDED' && 
job.job_status!='FINISHED'">
-                            <button type="button" class="btn btn-default 
btn-xs dropdown-toggle"
-                                    data-toggle="dropdown">
-                                Action <span class="ace-icon fa fa-caret-down 
icon-on-right"></span>
-                            </button>
-                            <ul class="dropdown-menu" role="menu">
-                                <li ng-if="job.job_status=='ERROR'"><a 
ng-click="resume(job)">Resume</a></li>
-                                <li ng-if="job.job_status=='RUNNING' || 
job.job_status=='NEW' || job.job_status=='PENDING' || job.job_status=='ERROR'">
-                                    <a ng-click="cancel(job)">Discard</a>
-                                </li>
-                            </ul>
-                        </div>
-                        <span ng-if="job.job_status=='DISCARDED' || 
job.job_status=='FINISHED'">N/A</span>
-                    </td>
-                    <td>
-                        <button class="btn btn-info btn-xs" 
ng-click="state.showSteps= !state.showSteps; state.selectedJob = job">
-                            <i class="fa fa-chevron-circle-right"></i>
-                        </button>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-        </div>
 
-        <kylin-pagination data="jobList.jobs" load-func="list" 
action="action"/>
-    </div>
-    <div class="col-xs-4" ng-if="state.showSteps">
-        <div ng-include src="'partials/jobs/job_steps.html'"></div>
-    </div>
+<div class="row models-main dataTables_wrapper"  
style="padding-top:10px;padding-left: 5px;">
+  <div ng-class="row">
+    <tabset>
+      <tab heading="Jobs" select="jobTabSelected('jobs')" 
active="tabs[2].active">
+        <div class="col-xs-12" ng-include 
src="'partials/jobs/jobList.html'"></div>
+      </tab>
+      <tab heading="Slow Queries" select="jobTabSelected('query')" 
active="tabs[1].active">
+        <div class="col-xs-12" ng-include 
src="'partials/jobs/badQuery.html'"></div>
+      </tab>
+    </tabset>
+  </div>
 </div>
 
+
+
 <div ng-include="'partials/projects/project_create.html'"></div>

Reply via email to