You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by zh...@apache.org on 2015/07/02 13:55:06 UTC

[1/4] incubator-kylin git commit: KYLIN-792 ,add performance module

Repository: incubator-kylin
Updated Branches:
  refs/heads/0.7-staging cbcfd59df -> a935c7bae


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index 6824498..f1087ed 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -30,20 +30,21 @@
     <!-- ref:css css/styles.min.<%= buildNumber %>.css -->
     <link rel="stylesheet" type="text/css" href="components/bootstrap/dist/css/bootstrap.min.css">
     <link rel="stylesheet" type="text/css" href="components/font-awesome/css/font-awesome.css">
-
+    <link rel="stylesheet" type="text/css" href="css/AdminLTE-fonts.css">
+    <link rel="stylesheet" type="text/css" href="components/ng-grid/ng-grid.css">
     <link rel="stylesheet" type="text/css" href="components/angular-tree-control/css/tree-control.css">
     <link rel="stylesheet" type="text/css" href="components/angular-tree-control/css/tree-control-attribute.css">
+    <link rel="stylesheet" type="text/css" href="components/animate.css/animate.css">
+
     <link rel="stylesheet" type="text/css" href="components/messenger/build/css/messenger.css">
     <link rel="stylesheet" type="text/css" href="components/messenger/build/css/messenger-theme-ice.css">
-    <link rel="stylesheet" type="text/css" href="components/ng-grid/ng-grid.css">
     <link rel="stylesheet" type="text/css" href="components/chosen/chosen.css">
     <link rel="stylesheet" type="text/css" href="components/angular-chosen-localytics/chosen-spinner.css">
-    <link rel="stylesheet" type="text/css" href="components/animate.css/animate.css">
     <link rel="stylesheet" type="text/css" href="components/nvd3/nv.d3.min.css">
-
-    <link rel="stylesheet" type="text/css" href="css/AdminLTE-fonts.css">
     <link rel="stylesheet" type="text/css" href="css/AdminLTE.css">
     <link rel="stylesheet" type="text/css" href="components/bootstrap-sweetalert/lib/sweet-alert.css">
+    <link rel="stylesheet" type="text/css" href="components/angular-busy/dist/angular-busy.css">
+
 
     <link rel="stylesheet/less" href="less/build.less">
     <!-- endref -->
@@ -93,7 +94,7 @@
 
 <script src="components/moment/moment.js"></script>
 <script src="components/d3/d3.min.js"></script>
-<script src="components/nvd3/nv.d3.min.js"></script>
+<script src="components/nvd3/nv.d3.js"></script>
 <script src="components/angularjs-nvd3-directives/dist/angularjs-nvd3-directives.js"></script>
 <script src="components/bootstrap-sweetalert/lib/sweet-alert.js"></script>
 <script src="components/angular-sweetalert/SweetAlert.js"></script>
@@ -101,6 +102,7 @@
 <script src="components/angular-underscore/angular-underscore.js"></script>
 <script src="components/jquery-ui/jquery-ui.min.js"></script>
 <script src="components/angular-ui-sortable/sortable.js"></script>
+<script src="components/angular-busy/dist/angular-busy.js"></script>
 
 <script src="js/app.js"></script>
 <script src="js/config.js"></script>
@@ -127,6 +129,7 @@
 <script src="js/services/tree.js"></script>
 <script src="js/services/users.js"></script>
 <script src="js/services/ngLoading.js"></script>
+<script src="js/services/dashboard.js"></script>
 
 <script src="js/model/cubeConfig.js"></script>
 <script src="js/model/jobConfig.js"></script>
@@ -157,6 +160,7 @@
 <script src="js/controllers/cubeFilter.js"></script>
 <script src="js/controllers/cubeRefresh.js"></script>
 <script src="js/controllers/cubeAdvanceSetting.js"></script>
+<script src="js/controllers/dashboard.js"></script>
 <!-- endref -->
 
 <!-- ref:remove -->

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/js/app.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/app.js b/webapp/app/js/app.js
index 59d679e..ba288cb 100644
--- a/webapp/app/js/app.js
+++ b/webapp/app/js/app.js
@@ -17,4 +17,4 @@
  */
 
 //Kylin Application Module
-KylinApp = angular.module('kylin', ['ngRoute', 'ngResource', 'ngGrid', 'ui.bootstrap', 'ui.ace', 'base64', 'angularLocalStorage', 'localytics.directives', 'treeControl', 'nvd3ChartDirectives', 'ngLoadingRequest', 'oitozero.ngSweetAlert', 'ngCookies', 'angular-underscore', 'ngAnimate', 'ui.sortable']);
+KylinApp = angular.module('kylin', ['ngRoute', 'ngResource', 'ngGrid', 'ui.bootstrap', 'ui.ace', 'base64', 'angularLocalStorage', 'localytics.directives', 'treeControl', 'nvd3ChartDirectives', 'ngLoadingRequest', 'oitozero.ngSweetAlert', 'ngCookies', 'angular-underscore', 'ngAnimate', 'ui.sortable',,'cgBusy']);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/js/controllers/dashboard.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/dashboard.js b/webapp/app/js/controllers/dashboard.js
new file mode 100644
index 0000000..40b7b8e
--- /dev/null
+++ b/webapp/app/js/controllers/dashboard.js
@@ -0,0 +1,237 @@
+/*
+ * 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('DashBoardCtrl', function ($scope, DashBoardService, $log, $q) {
+
+
+    $scope.stastic = {
+        countUser: 0,
+        last30DayPercentile: 0,
+        cubeStorage: 0,
+        avgDayQuery: 0,
+        cubesCount: 0
+    }
+
+    $scope.eachDayPercentileData=[];
+
+
+    $scope.reduceCubeSourceTicks=false;
+
+    // each day percentile chart
+    $scope.cubeInfo = function () {
+      var cubeSourceRecords ={"key":"Cube Source Records","values":[],"sizes":[]};
+      $scope.cubeInfoPromise = DashBoardService.listCubes({},
+            function (data) {
+                if(data.length>30){
+                    $scope.reduceCubeSourceTicks=true;
+                }
+                for (var i = 0; i < data.length; i++) {
+                  cubeSourceRecords.values.push([data[i].name,parseInt(data[i].input_records_count)]);
+                  cubeSourceRecords.sizes.push((data[i].size_kb));
+                   $log.info(data[i]);
+                }
+              $scope.cubeUsageData = [cubeSourceRecords];
+
+            }, function (result) {
+                $log.error(result);
+            }).$promise;
+    }();
+
+
+    $scope.cubeSourceYAxisTickFormat = function(){
+        return d3.format('0');
+    }
+
+    $scope.avgDayQuery = function () {
+        $scope.avgDayQueryPromise = DashBoardService.avgDayQuery({},
+            function (data) {
+                if (!isNaN(data[0][0])) {
+                    $scope.stastic.avgDayQuery = Math.round(data[0][0]);
+                } else {
+                    $log.info("No data available.");
+                }
+                $log.info("avg day query:" + data);
+            }, function (result) {
+                $log.error(result);
+            }).$promise;
+    }();
+
+    $scope.totalQueryUser = function () {
+        $scope.queryUserPromise = DashBoardService.totalQueryUser({},
+            function (data) {
+                if (!isNaN(data[0][0])) {
+                    $scope.stastic.userCount = data[0][0];
+                } else {
+                    $log.info("No data available.");
+                }
+
+                $log.info("total query user:" + data);
+            }, function (result) {
+                $log.error(result);
+            }).$promise;
+    }();
+
+    $scope.last30DayPercentile = function () {
+        $scope.last30DayPercentilePromise = DashBoardService.last30DayPercentile({},
+            function (data) {
+                if (!isNaN(data[0][0])) {
+                    $scope.stastic.last30DayPercentile = Math.round(data[0][0] * 100) / 100;
+                } else {
+                    $log.info("No data available.");
+                }
+                $log.info("last 30 Day 90th Percentile:" + data);
+            }, function (result) {
+                $log.error(result);
+            }).$promise;
+    }();
+
+
+  //daily query num
+  $scope.dailyQueryData = [];
+
+
+  // last 30 days
+  $scope.dailyQueryCount = function () {
+    var queryCount ={"key":"Query Count","bar":true,"values":[]};
+    $scope.dailyQueryCountPromise = DashBoardService.dailyQueryCount({},
+      function (data) {
+        for (var i = 0; i < data.length; i++) {
+          $scope.dailyQueryData.push(parseInt(data[i][1]));
+          queryCount.values.push([new Date(data[i][0]).getTime()/1000,data[i][1]]);
+        }
+        console.log("daily query count");
+        $scope.eachDayPercentileData.push(queryCount);
+      }, function (result) {
+        $log.error(result);
+      }).$promise;
+  };
+
+    $scope.eachDayPercentile = function () {
+        var percenTile90 ={"key":"90%-ile","values":[]},percenTile95 = {"key":"95%-ile","values":[]},queryCount ={"key":"Query Count","bar":true,"values":[]};;
+        $scope.eachDayPercentilePromise = DashBoardService.eachDayPercentile({},
+            function (data) {
+                for (var i = 0; i < data.length; i++) {
+                    var _latency90 = data[i][1].split(",")[0].substr(1);
+                    var _latency95 = data[i][1].split(",")[1].substr(0, data[i][1].length - 1);
+                    var _querycount = data[i][2];
+                    percenTile90.values.push([new Date(data[i][0]).getTime()/1000,Math.round(parseFloat(_latency90) * 100) / 100]);
+                    percenTile95.values.push([new Date(data[i][0]).getTime()/1000,Math.round(parseFloat(_latency95) * 100) / 100]);
+                    queryCount.values.push([new Date(data[i][0]).getTime()/1000,Math.round(parseInt(_querycount) * 100) / 100]);
+                }
+                 $scope.eachDayPercentileData=[percenTile90,percenTile95,queryCount];
+             }, function (result) {
+                $log.error(result);
+            }).$promise;
+    }();
+
+
+  $scope.dailyLatencyReportRightYaxis = function(){
+    return "Query Latency";
+  }
+
+  $scope.xAxisTickFormatFunction = function(){
+    return function(d){
+      return d3.time.format('%Y-%m-%d')(moment.unix(d).toDate());
+    }
+  };
+
+
+    $scope.legendColorFunction = function(){
+        return function(d){
+            return '#E01B5D';
+        }
+    };
+
+
+    $scope.reduceProjectPercentileTicks=false;
+
+    $scope.projectPercentile = function () {
+
+        var percenTile90 ={"key":"90%-ile","values":[]},percenTile95 = {"key":"95%-ile","values":[]};
+
+
+        $scope.projectPercentilePromise = DashBoardService.projectPercentile({},
+            function (data) {
+                if(data.length>30){
+                    $scope.reduceProjectPercentileTicks=true;
+                }
+                for (var i = 0; i < data.length; i++) {
+
+                    var _latency90 = data[i][1].split(",")[0].substr(1);
+                    var _latency95 = data[i][1].split(",")[1].substr(0, data[i][1].length - 1);
+                    percenTile90.values.push([data[i][0],Math.round(parseFloat(_latency90) * 100) / 100]);
+                    percenTile95.values.push([data[i][0],Math.round(parseFloat(_latency95) * 100) / 100]);
+
+                }
+                $scope.eachProjectPercentileData=[percenTile90,percenTile95];
+            }, function (result) {
+                $log.error(result);
+            }).$promise;
+    }();
+
+  $scope.projectPercentileToolTipContentFunction = function(key, x, y, e, graph) {
+    return '<table>'+'<tr>'+'<td>'+'<strong>Latency</strong>'+'</td>'+'<td>'+' : '+y+'(S)'+'</td>'+'</tr>'+'<tr>'+'<td>'+'<strong>Percentile</strong>'+'</td>'+'<td>'+' : '+key+'</td>'+'</tr>'+'<tr>'+'<td>'+'<strong>Project</strong>'+'</td>'+'<td>'+' : '+x+'</td>'+'</tr>'+'</table>';
+
+  }
+
+  $scope.dailyPercentileToolTip = function(key, x, y, e, graph) {
+      var suffix ='';
+      if(key.indexOf('ile')!=-1){
+          suffix = '(S)';
+      }
+      return '<table>'+'<tr>'+'<td>'+'<strong>'+key+'</strong>'+'</td>'+'<td>'+' : '+y+suffix+'</td>'+'</tr>'+'<tr>'+'<td>'+'<strong>Date</strong>'+'</td>'+'<td>'+' : '+x+'</td>'+'</tr>'+'</table>';
+
+  }
+  $scope.cubeToolTipContentFunction = function(key, x, y, e, graph) {
+    return '<table>'+'<tr>'+'<td>'+'<strong>Source Records</strong>'+'</td>'+'<td>'+' : '+parseInt(y)+'</td>'+'</tr>'+'<tr>'+'<td>'+'<strong>Source Size</strong>'+'</td>'+'<td>'+' : '+$scope.dataSize(e.series.sizes[e.pointIndex]*1024)+'</td>'+'</tr>'+'<tr>'+'<td>'+'<strong>Cube Name</strong>'+'</td>'+'<td>'+' : '+x+'</td>'+'</tr>'+'</table>';
+  }
+
+  $scope.commonToolTipContentFunction = function(key, x, y, e, graph) {
+    return '<p>' +  x +':'+y+ '</p>';
+  }
+
+    $scope.cubesStorage = function () {
+        $scope.cubesStoragePromise = DashBoardService.cubesStorage({},
+            function (cubes) {
+                $scope.stastic.cubesCount = cubes.length;
+                var _cubeStorage = $scope.getTotalSize(cubes);
+                $scope.stastic.cubeStorage = _cubeStorage;
+            }, function (result) {
+                $log.error(result);
+            }).$promise;
+    }();
+
+    $scope.getTotalSize = function (cubes) {
+        var size = 0;
+        if (!cubes) {
+            return 0;
+        }
+        else {
+            for (var i = 0; i < cubes.length; i++) {
+                size += cubes[i].size_kb;
+            }
+            return $scope.dataSize(size * 1024);
+        }
+    };
+
+});
+
+
+

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/js/services/dashboard.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/dashboard.js b/webapp/app/js/services/dashboard.js
new file mode 100644
index 0000000..f5b1454
--- /dev/null
+++ b/webapp/app/js/services/dashboard.js
@@ -0,0 +1,32 @@
+/*
+ * 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('DashBoardService', ['$resource', function ($resource, config) {
+    return $resource(Config.service.url + 'performance/:action', {}, {
+//        avgCubeLatency: {method: 'GET', params: {action: 'avgCubeLatency'}, isArray: true},
+        avgDayQuery: {method: 'GET', params: {action: 'avgDayQuery'}, isArray: true},
+        dailyQueryCount: {method: 'GET', params: {action: 'dailyQueryCount'}, isArray: true},
+        eachDayPercentile: {method: 'GET', params: {action: 'eachDayPercentile'}, isArray: true}, // last 30 day 90,95 percentile for each day
+        projectPercentile: {method: 'GET', params: {action: 'projectPercentile'}, isArray: true}, // last 30 day 90,95 percentile for each project
+        cubesStorage: {method: 'GET', params: {action: 'cubesStorage'}, isArray: true},
+        last30DayPercentile: {method: 'GET', params: {action: 'last30DayPercentile'}, isArray: true},//90th percentile of last 30 day
+        totalQueryUser: {method: 'GET', params: {action: 'totalQueryUser'}, isArray: true},
+        listCubes: {method: 'GET', params: {action: 'listCubes'}, isArray: true}
+    });
+}])
+;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/js/services/users.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/users.js b/webapp/app/js/services/users.js
index d05ca94..891ad89 100644
--- a/webapp/app/js/services/users.js
+++ b/webapp/app/js/services/users.js
@@ -49,9 +49,16 @@ KylinApp.service('UserService', function ($http, $q) {
     var homePage = "/login";
 
     if (curUser.userDetails && curUser.userDetails.authorities) {
-      angular.forEach(curUser.userDetails.authorities, function (authority, index) {
-        homePage = (!!roles[authority.authority]) ? roles[authority.authority] : homePage;
-      });
+       var authorities = curUser.userDetails.authorities;
+       for(var i=0;i<authorities.length;i++){
+           if(authorities[i].authority==="ROLE_ADMIN"){
+               homePage = roles[authorities[i].authority];
+               break;
+           }else{
+               homePage = roles[authorities[i].authority]
+           }
+       }
+
     }
 
     return homePage;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/less/app.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/app.less b/webapp/app/less/app.less
index 162c929..4edf83c 100644
--- a/webapp/app/less/app.less
+++ b/webapp/app/less/app.less
@@ -605,3 +605,20 @@ ul.messenger .messenger-message-inner ,.ngCellText{
   max-height: 300px;
   overflow-y: auto;
 }
+
+.dashboard_wrapper{
+  min-height: 100%;
+  background-color: #ecf0f5;
+  z-index: 800;
+}
+
+
+.size-h1{font-size:36px}
+.size-h2{font-size:30px}
+.size-h3{font-size:24px}
+.size-h4{font-size:18px}
+
+.text-muted {
+  color: #777;
+}
+.tick line {display: none;}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/partials/admin/admin.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/admin/admin.html b/webapp/app/partials/admin/admin.html
index c17aba4..c7b23f0 100644
--- a/webapp/app/partials/admin/admin.html
+++ b/webapp/app/partials/admin/admin.html
@@ -71,6 +71,9 @@
             <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>
+            <a href="dashboard">
+                Dashboard
+            </a>
         </div>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/partials/dashboard.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/dashboard.html b/webapp/app/partials/dashboard.html
new file mode 100644
index 0000000..acccfe4
--- /dev/null
+++ b/webapp/app/partials/dashboard.html
@@ -0,0 +1,228 @@
+<!--
+* 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.
+-->
+<div class="wrapper">
+  <aside class="main-sidebar" style="padding-top:0px !important;">
+    <!-- sidebar: style can be found in sidebar.less -->
+    <section class="sidebar" style="height: auto;">
+
+    </section>
+    <!-- /.sidebar -->
+  </aside>
+
+  <div class="content-wrapper" style="min-height: 800px;">
+
+    <section class="content-header">
+      <h1>
+        Dashboard
+        <small></small>
+      </h1>
+    </section>
+
+    <section class="content">
+      <!-- Info boxes -->
+      <div class="row">
+        <div class="col-md-3 col-sm-6 col-xs-12">
+          <div class="info-box">
+            <span class="info-box-icon bg-aqua"><i class="fa fa-users"></i></span>
+
+            <div class="info-box-content" cg-busy="{promise:queryUserPromise,message:'Loading...'}">
+              <span class="info-box-number size-h2 text-muted">{{stastic.userCount}}</span>
+              <span class="info-box-text size-h4 text-muted">Users</span>
+            </div>
+            <!-- /.info-box-content -->
+          </div>
+          <!-- /.info-box -->
+        </div>
+        <!-- /.col -->
+        <div class="col-md-3 col-sm-6 col-xs-12">
+          <div class="info-box">
+            <span class="info-box-icon bg-red"><i class="fa fa-eye"></i></span>
+
+            <div class="info-box-content" cg-busy="{promise:last30DayPercentilePromise,message:'Loading...'}">
+              <span class="info-box-number size-h2 text-muted">{{stastic.last30DayPercentile}} S</span>
+              <span class="info-box-text size-h4 text-muted">90%-ile Latency (last 30 days)</span>
+            </div>
+            <!-- /.info-box-content -->
+          </div>
+          <!-- /.info-box -->
+        </div>
+        <!-- /.col -->
+
+        <div class="col-md-3 col-sm-6 col-xs-12">
+          <div class="info-box">
+            <span class="info-box-icon bg-green"><i class="fa fa-database"></i></span>
+
+            <div class="info-box-content" cg-busy="{promise:cubesStoragePromise,message:'Loading...'}">
+              <span class="info-box-number size-h2 text-muted">{{stastic.cubeStorage}}</span>
+              <span class="info-box-text size-h4 text-muted">Storage</span>
+            </div>
+            <!-- /.info-box-content -->
+          </div>
+          <!-- /.info-box -->
+        </div>
+        <!-- /.col -->
+        <div class="col-md-3 col-sm-6 col-xs-12">
+          <div class="info-box">
+            <span class="info-box-icon bg-yellow"><i class="fa fa-cubes"></i></span>
+
+            <div class="info-box-content" cg-busy="{promise:cubesStoragePromise,message:'Loading...'}">
+              <span class="info-box-number size-h2 text-muted">{{stastic.cubesCount}}</span>
+              <span class="info-box-text size-h4 text-muted">Cubes</span>
+            </div>
+            <!-- /.info-box-content -->
+          </div>
+          <!-- /.info-box -->
+        </div>
+        <!-- /.col -->
+      </div>
+      <!-- /.row -->
+
+      <div class="row" ng-controller="DashBoardCtrl">
+        <div class="col-md-12">
+          <div class="box">
+            <div class="box-header with-border">
+              <h3 class="box-title">Query Latency (last 30 days)</h3>
+            </div>
+            <!-- /.box-header -->
+            <div class="box-body">
+
+
+              <div class="row">
+                <div class="col-md-12">
+                  <p class="text-center">
+                    <strong></strong>
+                  </p>
+
+
+                        <!-- Sales Chart Canvas -->
+                        <!--<div cg-busy="{promise:queryCountDailyPercentilePromise,message:'Loading...'}">-->
+                        <div cg-busy="[eachDayPercentilePromise]">
+
+                            <nvd3-line-plus-bar-chart
+                                    data="eachDayPercentileData"
+                                    objectequality="true"
+                                    margin="{left:100,top:10,bottom:20,right:100}"
+                                    showXAxis="true"
+                                    showYAxis="true"
+                                    y1AxisLabel="Query Count"
+                                    y2AxisLabel="Query Latency(seconds)"
+                                    forceY="[0]"
+                                    height="400"
+                                    xaxisrotatelabels="-45"
+                                    tooltips="true"
+                                    useInteractiveGuideline="true"
+                                    showLegend="true"
+                                    legendWidth="200"
+                                    legendHeight="100"
+                                    xAxisTickFormat="xAxisTickFormatFunction()"
+                                    interactive="true"
+                                    tooltipcontent="dailyPercentileToolTip"
+                                    >
+                              <svg></svg>
+                            </nvd3-line-plus-bar-chart>
+                        </div>
+                  <!-- /.chart-responsive -->
+                </div>
+                <!-- /.col -->
+              </div>
+              <!-- /.row -->
+
+              <div class="row">
+                <div class="col-md-6">
+                  <div class="box">
+                    <div class="box-header with-border">
+                      <h3 class="box-title">Cube Source</h3>
+                    </div>
+                    <div class="box-body">
+                        <!-- Sales Chart Canvas -->
+                        <div cg-busy="{promise:cubeInfoPromise}">
+                        <nvd3-multi-bar-chart
+                          margin="{left:100,top:10,bottom:100,right:60}"
+                          data="cubeUsageData"
+                          objectequality="true"
+                          height="350"
+                          showXAxis="true"
+                          reducexticks="{{reduceCubeSourceTicks}}"
+                          xaxisrotatelabels="-45"
+                          showYAxis="true"
+                          forceY="[0]"
+                          xAxisLabel="Cube Name"
+                          yAxisLabel="Cube Source Records"
+                          showLegend="true"
+                          tooltips="true"
+                          legendWidth="200"
+                          legendHeight="100"
+                          tooltips="true"
+                          yAxisTickFormat="cubeSourceYAxisTickFormat()"
+                          tooltipcontent="cubeToolTipContentFunction"
+                          >
+                          <svg></svg>
+                        </nvd3-multi-bar-chart>
+                          </div>
+                    </div>
+                  </div>
+                </div>
+
+                <div class="col-md-6">
+                  <div class="box">
+                    <div class="box-header with-border">
+                      <h3 class="box-title">Project Latency (last 30 days)</h3>
+                    </div>
+                    <div class="box-body">
+                        <!-- Sales Chart Canvas -->
+                        <div cg-busy="{promise:projectPercentilePromise}">
+                          <nvd3-multi-bar-chart
+                            margin="{left:100,top:10,bottom:100,right:60}"
+                            data="eachProjectPercentileData"
+                            objectequality="true"
+                            height="350"
+                            showXAxis="true"
+                            xAxisLabel="Project Name"
+                            reducexticks="{{reduceProjectPercentileTicks}}"
+                            xaxisrotatelabels="-45"
+                            showYAxis="true"
+                            yAxisLabel="Query Latency(seconds)"
+                            showLegend="true"
+                            legendWidth="200"
+                            legendHeight="100"
+                            tooltips="true"
+                            tooltipcontent="projectPercentileToolTipContentFunction"
+                            >
+                            <svg></svg>
+                          </nvd3-multi-bar-chart>
+
+                        </div>
+                    </div>
+                  </div>
+
+
+                </div>
+              </div>
+
+
+            </div>
+            <!-- ./box-body -->
+          </div>
+          <!-- /.box -->
+        </div>
+        <!-- /.col -->
+      </div>
+      <!-- /.row -->
+    </section>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/partials/header.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/header.html b/webapp/app/partials/header.html
index eb94664..74e03a0 100644
--- a/webapp/app/partials/header.html
+++ b/webapp/app/partials/header.html
@@ -26,7 +26,7 @@
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                 </button>
-                <a class="navbar-brand" style="padding: 2px 10px 0px 0px"><img src="image/logo.png" height="40px" width="40px"/><small> Kylin </small></a>
+                <a class="navbar-brand" style="padding: 2px 10px 0px 0px;"><img src="image/logo.png" height="40px" width="40px"/><small> Kylin </small></a>
             </div>
 
             <div class="navbar-collapse collapse" collapse="isCollapsed">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/routes.json
----------------------------------------------------------------------
diff --git a/webapp/app/routes.json b/webapp/app/routes.json
index 9f13c70..6401528 100644
--- a/webapp/app/routes.json
+++ b/webapp/app/routes.json
@@ -1,5 +1,12 @@
 [
     {
+      "url": "/dashboard",
+      "params": {
+        "templateUrl": "partials/dashboard.html",
+        "controller": "DashBoardCtrl"
+      }
+    },
+    {
         "url": "/cubes",
         "params": {
             "templateUrl": "partials/cubes/cubes.html",

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/bower.json
----------------------------------------------------------------------
diff --git a/webapp/bower.json b/webapp/bower.json
index 298cba3..f9d99fb 100755
--- a/webapp/bower.json
+++ b/webapp/bower.json
@@ -19,7 +19,7 @@
     "moment": "2.5.1",
     "d3": "3.4.4",
     "nvd3": "1.1.15-beta",
-    "angularjs-nvd3-directives": "0.0.5-beta",
+    "angularjs-nvd3-directives": "0.0.7",
     "angular-sweetalert": "~1.0.3",
     "bootstrap-sweetalert": "~0.4.3",
     "angular-underscore": "~0.5.0",
@@ -27,8 +27,8 @@
     "underscore": "~1.7.0",
     "fuelux": "~3.5.1",
     "angular-animate": "1.2",
-    "angular-cookies":"1.2"
-
+    "angular-cookies": "1.2",
+    "angular-busy": "~4.0"
   },
   "devDependencies": {
     "less.js": "~1.4.0",
@@ -39,9 +39,9 @@
     "nvd3": "1.1.15-beta",
     "d3": "3.4.4",
     "moment": "2.4.0",
+    "angular-busy": "~4.0",
     "angular-resource": "1.2.15",
-    "angularLocalStorage": "0.1.7",
     "angular-cookies": "~1.2.0-rc.2",
-    "angular-animate": "1.2"
+    "angular-animate": "~1.2"
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/grunt.json
----------------------------------------------------------------------
diff --git a/webapp/grunt.json b/webapp/grunt.json
index 9a4499f..fa272c9 100755
--- a/webapp/grunt.json
+++ b/webapp/grunt.json
@@ -40,6 +40,7 @@
                 "app/components/angular-underscore/angular-underscore.js",
                 "app/components/jquery-ui/jquery-ui.min.js",
                 "app/components/angular-ui-sortable/sortable.js",
+                "app/components/angular-busy/dist/angular-busy.js",
                 "tmp/js/scripts.js"
             ],
             "dest": "tmp/js/scripts.min.js"
@@ -60,6 +61,7 @@
                 "app/components/nvd3/nv.d3.min.css",
                 "app/css/AdminLTE.css",
                 "app/components/bootstrap-sweetalert/lib/sweet-alert.css",
+                "app/components/angular-busy/dist/angular-busy.css",
                 "tmp/css/styles.css"
             ],
             "dest": "tmp/css/styles.min.css"


[4/4] incubator-kylin git commit: KYLIN-792 ,add performance module

Posted by zh...@apache.org.
KYLIN-792 ,add performance module


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

Branch: refs/heads/0.7-staging
Commit: a935c7bae805b2e93736e8f7cb93dc0f0e6f467d
Parents: cbcfd59
Author: jiazhong <ji...@ebay.com>
Authored: Wed May 27 23:01:10 2015 +0800
Committer: jiazhong <ji...@ebay.com>
Committed: Thu Jul 2 19:51:40 2015 +0800

----------------------------------------------------------------------
 conf/kylin.properties                           |   12 +
 .../test_case_data/sandbox/kylin.properties     |   14 +
 monitor/pom.xml                                 |  169 +
 .../apache/kylin/monitor/ApiRequestParser.java  |  241 +
 .../java/org/apache/kylin/monitor/Client.java   |   63 +
 .../org/apache/kylin/monitor/ConfigUtils.java   |  220 +
 .../org/apache/kylin/monitor/DebugClient.java   |   62 +
 .../org/apache/kylin/monitor/FileUtils.java     |  116 +
 .../apache/kylin/monitor/HiveJdbcClient.java    |  223 +
 .../kylin/monitor/MonitorMetaManager.java       |  217 +
 .../org/apache/kylin/monitor/QueryParser.java   |  249 +
 monitor/src/main/resources/log4j.properties     |   31 +
 .../org/apache/kylin/monitor/ParseLogTest.java  |   77 +
 pom.xml                                         |    1 +
 script/prepare.sh                               |    2 +
 server/pom.xml                                  |    5 +
 .../rest/controller/PerformanceController.java  |  125 +
 .../kylin/rest/filter/KylinApiFilter.java       |  121 +
 .../apache/kylin/rest/service/CubeService.java  |    4 +
 .../kylin/rest/service/PerformService.java      |  123 +
 server/src/main/resources/kylinSecurity.xml     |    1 +
 server/src/main/webapp/WEB-INF/web.xml          |  122 +-
 webapp/app/css/AdminLTE.css                     | 4782 ++++++++++--------
 webapp/app/index.html                           |   16 +-
 webapp/app/js/app.js                            |    2 +-
 webapp/app/js/controllers/dashboard.js          |  237 +
 webapp/app/js/services/dashboard.js             |   32 +
 webapp/app/js/services/users.js                 |   13 +-
 webapp/app/less/app.less                        |   17 +
 webapp/app/partials/admin/admin.html            |    3 +
 webapp/app/partials/dashboard.html              |  228 +
 webapp/app/partials/header.html                 |    2 +-
 webapp/app/routes.json                          |    7 +
 webapp/bower.json                               |   10 +-
 webapp/grunt.json                               |    2 +
 35 files changed, 5391 insertions(+), 2158 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/conf/kylin.properties
----------------------------------------------------------------------
diff --git a/conf/kylin.properties b/conf/kylin.properties
index cf9756e..b1ebccc 100644
--- a/conf/kylin.properties
+++ b/conf/kylin.properties
@@ -101,3 +101,15 @@ deploy.env=DEV
 
 ###########################config info for sandbox#######################
 kylin.sandbox=true
+
+
+###########################config info for kylin monitor#######################
+# hive jdbc url
+kylin.hive.jdbc.connection.url=
+
+#config where to parse query log,split with comma ,will also read $KYLIN_HOME/tomcat/logs/ by default
+ext.log.base.dir = /tmp/kylin_log1,/tmp/kylin_log2
+
+#will create external hive table to query result csv file
+#will set to kylin_query_log by default if not config here
+query.log.parse.result.table = kylin_query_log

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/examples/test_case_data/sandbox/kylin.properties
----------------------------------------------------------------------
diff --git a/examples/test_case_data/sandbox/kylin.properties b/examples/test_case_data/sandbox/kylin.properties
index efaef5c..8f73f64 100644
--- a/examples/test_case_data/sandbox/kylin.properties
+++ b/examples/test_case_data/sandbox/kylin.properties
@@ -102,3 +102,17 @@ deploy.env=DEV
 ###########################config info for sandbox#######################
 kylin.sandbox=true
 
+
+###########################config info for kylin monitor#######################
+# hive jdbc url
+kylin.hive.jdbc.connection.url= jdbc:hive2://sandbox:10000
+
+#config where to parse query log,split with comma ,will also read $KYLIN_HOME/tomcat/logs/ by default
+ext.log.base.dir = /tmp/kylin_log1,/tmp/kylin_log2
+
+#will create external hive table to query result csv file
+#will set to kylin_query_log by default if not config here
+query.log.parse.result.table = kylin_query_log
+
+
+

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/pom.xml
----------------------------------------------------------------------
diff --git a/monitor/pom.xml b/monitor/pom.xml
new file mode 100644
index 0000000..a6fc87c
--- /dev/null
+++ b/monitor/pom.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.kylin</groupId>
+        <artifactId>kylin</artifactId>
+        <version>0.7.2-incubating-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>kylin-monitor</artifactId>
+    <packaging>jar</packaging>
+    <name>Kylin:Monitor</name>
+    <url>http://maven.apache.org</url>
+
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <hadoop.version>2.6.0</hadoop.version>
+        <hive.version>0.14.0</hive.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.17</version>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.opencsv</groupId>
+            <artifactId>opencsv</artifactId>
+            <version>2.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-hdfs</artifactId>
+            <version>${hadoop.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-auth</artifactId>
+            <version>${hadoop.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-common</artifactId>
+            <version>${hadoop.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <!--hbase dependency-->
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-hadoop2-compat</artifactId>
+            <version>${hbase-hadoop2.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-common</artifactId>
+            <version>${hbase-hadoop2.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-client</artifactId>
+            <version>${hbase-hadoop2.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-server</artifactId>
+            <version>${hbase-hadoop2.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!--hbase dependency-->
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-hadoop2-compat</artifactId>
+            <version>${hbase-hadoop2.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-common</artifactId>
+            <version>${hbase-hadoop2.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-client</artifactId>
+            <version>${hbase-hadoop2.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-server</artifactId>
+            <version>${hbase-hadoop2.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <!-- Hive dependencies -->
+        <dependency>
+            <groupId>org.apache.hive</groupId>
+            <artifactId>hive-jdbc</artifactId>
+            <version>${hive.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>org.apache.kylin.monitor.Client</mainClass>
+                        </manifest>
+                    </archive>
+
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                    <appendAssemblyId>false</appendAssemblyId>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/main/java/org/apache/kylin/monitor/ApiRequestParser.java
----------------------------------------------------------------------
diff --git a/monitor/src/main/java/org/apache/kylin/monitor/ApiRequestParser.java b/monitor/src/main/java/org/apache/kylin/monitor/ApiRequestParser.java
new file mode 100644
index 0000000..0321549
--- /dev/null
+++ b/monitor/src/main/java/org/apache/kylin/monitor/ApiRequestParser.java
@@ -0,0 +1,241 @@
+/*
+ * 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.
+*/
+
+package org.apache.kylin.monitor;
+
+import au.com.bytecode.opencsv.CSVWriter;
+import org.apache.commons.io.filefilter.RegexFileFilter;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.*;
+import org.apache.log4j.Logger;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author jiazhong
+ */
+public class ApiRequestParser {
+
+    final static Logger logger = Logger.getLogger(ApiRequestParser.class);
+    final static Charset ENCODING = StandardCharsets.UTF_8;
+    static String REQUEST_PARSE_RESULT_PATH = null;
+    final static String REQUEST_LOG_FILE_PATTERN = "kylin_request.log.(\\d{4}-\\d{2}-\\d{2})$";
+    final static String REQUEST_LOG_PARSE_RESULT_FILENAME = "kylin_request_log.csv";
+    static String DEPLOY_ENV;
+
+
+    final static String[] KYLIN_REQUEST_CSV_HEADER = {"REQUESTER", "REQ_TIME","REQ_DATE", "URI", "METHOD", "QUERY_STRING", "PAYLOAD", "RESP_STATUS", "TARGET", "ACTION","DEPLOY_ENV"};
+
+    private ConfigUtils monitorConfig;
+
+    public ApiRequestParser() {
+        monitorConfig = ConfigUtils.getInstance();
+        try {
+            monitorConfig.loadMonitorParam();
+            DEPLOY_ENV = monitorConfig.getDeployEnv();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void start() throws IOException, ParseException {
+        ApiRequestParser.REQUEST_PARSE_RESULT_PATH = ConfigUtils.getInstance().getRequestLogParseResultDir() + REQUEST_LOG_PARSE_RESULT_FILENAME;
+        this.parseRequestInit();
+
+        //get api req log files have been read
+        String[] hasReadFiles = MonitorMetaManager.getReadApiReqLogFileList();
+
+        List<File> files = this.getRequestLogFiles();
+        for (File file : files) {
+            if (!Arrays.asList(hasReadFiles).contains(file.getName())) {
+                this.parseRequestLog(file.getPath(), ApiRequestParser.REQUEST_PARSE_RESULT_PATH);
+                MonitorMetaManager.markApiReqLogFileAsRead(file.getName());
+            }
+        }
+    }
+
+    public void parseRequestInit() throws IOException {
+        logger.info("parse api request initializing...");
+        FileSystem fs = null;
+        try {
+            Configuration conf = new Configuration();
+            fs = FileSystem.get(conf);
+            org.apache.hadoop.fs.Path path = new org.apache.hadoop.fs.Path(ApiRequestParser.REQUEST_PARSE_RESULT_PATH);
+            if (!fs.exists(path)) {
+                fs.create(path);
+
+                //need to close before get FileSystem again
+                fs.close();
+                this.writeResultToHdfs(ApiRequestParser.REQUEST_PARSE_RESULT_PATH, ApiRequestParser.KYLIN_REQUEST_CSV_HEADER);
+            }
+        } catch (Exception e) {
+            fs.close();
+            logger.info("Failed to init:", e);
+        }
+    }
+
+    //parse query log and convert to csv file to hdfs
+    public void parseRequestLog(String filePath, String dPath) throws ParseException, IOException {
+
+        logger.info("Start parsing kylin api request file " + filePath + " !");
+
+//        writer config init
+        FileSystem fs = this.getHdfsFileSystem();
+        org.apache.hadoop.fs.Path resultStorePath = new org.apache.hadoop.fs.Path(dPath);
+        OutputStreamWriter writer = new OutputStreamWriter(fs.append(resultStorePath));
+        CSVWriter cwriter = new CSVWriter(writer,'|',CSVWriter.NO_QUOTE_CHARACTER);
+
+        Pattern p_available = Pattern.compile("/kylin/api/(cubes|user)+.*");
+        Pattern p_request = Pattern.compile("^.*\\[.*KylinApiFilter.logRequest.*\\].*REQUEST:.*REQUESTER=(.*);REQ_TIME=(\\w+ (\\d{4}-\\d{2}-\\d{2}).*);URI=(.*);METHOD=(.*);QUERY_STRING=(.*);PAYLOAD=(.*);RESP_STATUS=(.*);$");
+        Pattern p_uri = Pattern.compile("/kylin/api/(\\w+)(/.*/)*(.*)$");
+        Matcher m_available = p_available.matcher("");
+        Matcher m_request = p_request.matcher("");
+        Matcher m_uri = p_uri.matcher("");
+
+        Path path = Paths.get(filePath);
+        try {
+            BufferedReader reader = Files.newBufferedReader(path, ENCODING);
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                //reset the input
+                m_available.reset(line);
+                m_request.reset(line);
+
+                //filter unnecessary info
+                if (m_available.find()) {
+                    //filter GET info
+                    if (m_request.find() && !m_request.group(5).equals("GET")) {
+
+                        List<String> groups = new ArrayList<String>();
+                        for (int i = 1; i <= m_request.groupCount(); i++) {
+                            groups.add(m_request.group(i));
+                        }
+
+                        String uri = m_request.group(4);
+                        m_uri.reset(uri);
+                        if (m_uri.find()) {
+
+                            //add target
+                            groups.add(m_uri.group(1));
+
+                            //add action
+                            if (m_uri.group(1).equals("cubes")) {
+                                switch (m_request.group(5)) {
+                                    case "DELETE":
+                                        groups.add("drop");
+                                        break;
+                                    case "POST":
+                                        groups.add("save");
+                                        break;
+                                    default:
+                                        //add parse action
+                                        groups.add(m_uri.group(3));
+                                        break;
+                                }
+                            }
+
+                        }
+                        groups.add(DEPLOY_ENV);
+                        String[] recordArray = groups.toArray(new String[groups.size()]);
+                        //write to hdfs
+                        cwriter.writeNext(recordArray);
+                    }
+                }
+
+
+            }
+        } catch (IOException ex) {
+            logger.info("Failed to write to hdfs:", ex);
+        } finally {
+            writer.close();
+            cwriter.close();
+            fs.close();
+        }
+
+        logger.info("Finish parsing file " + filePath + " !");
+    }
+
+    public void writeResultToHdfs(String dPath, String[] record) throws IOException {
+        OutputStreamWriter writer = null;
+        CSVWriter cwriter = null;
+        FileSystem fs = null;
+        try {
+
+            fs = this.getHdfsFileSystem();
+            org.apache.hadoop.fs.Path resultStorePath = new org.apache.hadoop.fs.Path(dPath);
+            writer = new OutputStreamWriter(fs.append(resultStorePath));
+            cwriter = new CSVWriter(writer,'|',CSVWriter.NO_QUOTE_CHARACTER);
+            cwriter.writeNext(record);
+
+        } catch (IOException e) {
+            logger.info("Exception", e);
+        } finally {
+            writer.close();
+            cwriter.close();
+            fs.close();
+        }
+    }
+
+    public List<File> getRequestLogFiles() {
+        List<File> logFiles = new ArrayList<File>();
+
+//        String request_log_file_pattern = monitorConfig.getRequestLogFilePattern();
+
+        List<String> request_log_dir_list = monitorConfig.getLogBaseDir();
+        FileFilter filter = new RegexFileFilter(REQUEST_LOG_FILE_PATTERN);
+
+        for (String path : request_log_dir_list) {
+            logger.info("fetch api request log file from path:" + path);
+            File request_log_dir = new File(path);
+            File[] request_log_files = request_log_dir.listFiles(filter);
+            if (request_log_files == null) {
+                logger.warn("no api request log file found under path" + path);
+                break;
+            }
+            Collections.addAll(logFiles, request_log_files);
+        }
+
+        return logFiles;
+    }
+
+    public FileSystem getHdfsFileSystem() throws IOException {
+        Configuration conf = new Configuration();
+//        conf.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");
+        FileSystem fs = null;
+        try {
+            fs = FileSystem.get(conf);
+        } catch (IOException e) {
+            fs.close();
+            logger.info("Failed to get hdfs FileSystem", e);
+        }
+        return fs;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/main/java/org/apache/kylin/monitor/Client.java
----------------------------------------------------------------------
diff --git a/monitor/src/main/java/org/apache/kylin/monitor/Client.java b/monitor/src/main/java/org/apache/kylin/monitor/Client.java
new file mode 100644
index 0000000..eadce54
--- /dev/null
+++ b/monitor/src/main/java/org/apache/kylin/monitor/Client.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+*/
+
+
+package org.apache.kylin.monitor;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+
+import java.io.File;
+
+
+/**
+ * Created by jiazhong on 2015/5/7.
+ */
+public class Client {
+
+
+    static {
+        //set monitor log path
+        String KYLIN_HOME = ConfigUtils.getKylinHome();
+        String CATALINA_HOME = null;
+        if(!StringUtils.isEmpty(KYLIN_HOME)){
+            CATALINA_HOME = ConfigUtils.getKylinHome() + File.separator + "tomcat"+File.separator;
+            System.out.println("will use "+CATALINA_HOME+"/logs to put monitor log");
+        }else{
+            CATALINA_HOME = "";
+            System.out.println("will use default path to put monitor log");
+        }
+        //log4j config will use this
+        System.setProperty("CATALINA_HOME",CATALINA_HOME);
+    }
+    final static Logger logger = Logger.getLogger(Client.class);
+
+
+
+    public static void main(String[] args) {
+        logger.info("monitor client start parsing...");
+        QueryParser queryParser = new QueryParser();
+        HiveJdbcClient jdbcClient = new HiveJdbcClient();
+        try {
+            queryParser.start();
+            jdbcClient.start();
+        } catch (Exception e) {
+            logger.info("Exception",e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/main/java/org/apache/kylin/monitor/ConfigUtils.java
----------------------------------------------------------------------
diff --git a/monitor/src/main/java/org/apache/kylin/monitor/ConfigUtils.java b/monitor/src/main/java/org/apache/kylin/monitor/ConfigUtils.java
new file mode 100644
index 0000000..f38b701
--- /dev/null
+++ b/monitor/src/main/java/org/apache/kylin/monitor/ConfigUtils.java
@@ -0,0 +1,220 @@
+/*
+ * 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.
+*/
+
+
+package org.apache.kylin.monitor;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import java.io.*;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Created by jiazhong on 2015/4/28.
+ */
+public class ConfigUtils {
+
+    final static Logger logger = Logger.getLogger(ConfigUtils.class);
+
+    private static ConfigUtils ourInstance = new ConfigUtils();
+
+    private Properties monitorConfig = new Properties();
+
+    public static ConfigUtils getInstance() {
+        return ourInstance;
+    }
+
+    private ConfigUtils() {
+    }
+
+    public static final String KYLIN_EXT_LOG_BASE_DIR = "ext.log.base.dir";
+    public static final String KYLIN_METADATA_URL = "kylin.metadata.url";
+
+    public static final String KYLIN_HOME = "KYLIN_HOME";
+    public static final String KYLIN_CONF = "KYLIN_CONF";
+    public static final String KYLIN_LOG_CONF_HOME = "KYLIN_LOG_CONF_HOME";
+    public static final String CATALINA_HOME = "CATALINA_HOME";
+
+    public static final String KYLIN_HDFS_WORKING_DIR = "kylin.hdfs.working.dir";
+
+    public static final String KYLIN_MONITOR_CONF_PROP_FILE = "kylin.properties";
+    public static final String QUERY_LOG_PARSE_RESULT_TABLE = "query.log.parse.result.table";
+    public static final String DEFAULT_QUERY_LOG_PARSE_RESULT_TABLE = "kylin_query_log";
+
+    public static final String DEPLOY_ENV = "deploy.env";
+
+
+    public static final String HIVE_JDBC_CON_URL = "kylin.hive.jdbc.connection.url";
+
+
+    public void loadMonitorParam() throws IOException {
+        Properties props = new Properties();
+        InputStream resourceStream = this.getKylinPropertiesAsInputSteam();
+        props.load(resourceStream);
+        this.monitorConfig = props;
+    }
+
+
+    public static InputStream getKylinPropertiesAsInputSteam() {
+        File propFile = getKylinMonitorProperties();
+        if (propFile == null || !propFile.exists()) {
+            logger.error("fail to locate kylin.properties");
+            throw new RuntimeException("fail to locate kylin.properties");
+        }
+        try {
+            return new FileInputStream(propFile);
+        } catch (FileNotFoundException e) {
+            logger.error("this should not happen");
+            throw new RuntimeException(e);
+        }
+
+    }
+
+
+    private static File getKylinMonitorProperties() {
+        String kylinConfHome = System.getProperty(KYLIN_CONF);
+        if (!StringUtils.isEmpty(kylinConfHome)) {
+            logger.info("load kylin.properties file from " + kylinConfHome + ". (from KYLIN_CONF System.property)");
+            return getKylinPropertiesFile(kylinConfHome);
+        }
+
+        logger.warn("KYLIN_CONF property was not set, will seek KYLIN_HOME env variable");
+
+        String kylinHome = getKylinHome();
+        if (StringUtils.isEmpty(kylinHome))
+            throw new RuntimeException("Didn't find KYLIN_CONF or KYLIN_HOME, please set one of them");
+
+        String path = kylinHome + File.separator + "conf";
+        logger.info("load kylin.properties file from " + kylinHome+". (from KYLIN_HOME System.env)");
+        return getKylinPropertiesFile(path);
+
+    }
+
+    public static String getKylinHome() {
+        String kylinHome = System.getenv(KYLIN_HOME);
+        if (StringUtils.isEmpty(kylinHome)) {
+            logger.warn("KYLIN_HOME was not set");
+            return kylinHome;
+        }
+        logger.info("KYLIN_HOME is :"+kylinHome);
+        return kylinHome;
+    }
+
+    private static File getKylinPropertiesFile(String path) {
+        if (path == null) {
+            return null;
+        }
+        return new File(path, KYLIN_MONITOR_CONF_PROP_FILE);
+    }
+
+
+    /*
+     * get where to path log
+     */
+    public List<String> getLogBaseDir() {
+        List<String> logDirList = new ArrayList<String>();
+
+        String kylinLogConfHome = System.getProperty(KYLIN_LOG_CONF_HOME);
+        if (!StringUtils.isEmpty(kylinLogConfHome)) {
+            logger.info("Use KYLIN_LOG_CONF_HOME=" + KYLIN_LOG_CONF_HOME);
+            logDirList.add(kylinLogConfHome);
+        }
+
+        String kylinExtLogBaseDir = getExtLogBaseDir();
+        if (!StringUtils.isEmpty(kylinExtLogBaseDir)) {
+            String[] extPaths = kylinExtLogBaseDir.split(",");
+            for(String path:extPaths){
+                if(!StringUtils.isEmpty(path)){
+                    logger.info("Use ext log dir=" + path);
+                    logDirList.add(path.trim());
+                }
+            }
+        }
+
+        String kylinHome = getKylinHome();
+        if (!StringUtils.isEmpty(kylinHome))
+            if(logDirList.isEmpty()){
+               throw new RuntimeException("Didn't find KYLIN_CONF or KYLIN_HOME or KYLIN_EXT_LOG_BASE_DIR, please set one of them");
+            }
+        else{
+            String path = kylinHome + File.separator + "tomcat" + File.separator + "logs";
+            logDirList.add(path);
+        }
+
+        return logDirList;
+    }
+
+
+    public  String getMetadataUrl(){
+        return this.monitorConfig.getProperty(KYLIN_METADATA_URL);
+    }
+
+    public String getExtLogBaseDir() {
+        return this.monitorConfig.getProperty(KYLIN_EXT_LOG_BASE_DIR);
+    }
+
+    public String getKylinHdfsWorkingDir() {
+        return this.monitorConfig.getProperty(KYLIN_HDFS_WORKING_DIR);
+    }
+    public String getQueryLogParseResultDir() {
+        return this.getKylinHdfsWorkingDir()+"/performance/query/";
+    }
+
+    public String getQueryLogResultTable() {
+        String query_log_parse_result_table = this.monitorConfig.getProperty(QUERY_LOG_PARSE_RESULT_TABLE);
+        if(!StringUtils.isEmpty(query_log_parse_result_table)){
+            return query_log_parse_result_table;
+        }else{
+            return DEFAULT_QUERY_LOG_PARSE_RESULT_TABLE;
+        }
+    }
+
+    public String getRequestLogParseResultDir() {
+        return this.getKylinHdfsWorkingDir()+"/performance/request/";
+    }
+
+    public String getHiveJdbcConUrl() {
+        return this.monitorConfig.getProperty(HIVE_JDBC_CON_URL);
+    }
+
+    public String getLogParseResultMetaDir() {
+        return this.getKylinHdfsWorkingDir()+"/performance/metadata/";
+    }
+
+    public String getDeployEnv(){
+        return this.monitorConfig.getProperty(DEPLOY_ENV);
+    }
+
+
+    public static void addClasspath(String path) throws Exception {
+        File file = new File(path);
+
+        if (file.exists()) {
+            URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
+            Class<URLClassLoader> urlClass = URLClassLoader.class;
+            Method method = urlClass.getDeclaredMethod("addURL", new Class[] { URL.class });
+            method.setAccessible(true);
+            method.invoke(urlClassLoader, new Object[] { file.toURI().toURL() });
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/main/java/org/apache/kylin/monitor/DebugClient.java
----------------------------------------------------------------------
diff --git a/monitor/src/main/java/org/apache/kylin/monitor/DebugClient.java b/monitor/src/main/java/org/apache/kylin/monitor/DebugClient.java
new file mode 100644
index 0000000..a7230e6
--- /dev/null
+++ b/monitor/src/main/java/org/apache/kylin/monitor/DebugClient.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+*/
+
+
+package org.apache.kylin.monitor;
+
+import org.apache.log4j.Logger;
+import java.io.File;
+
+
+/**
+ * Created by jiazhong on 2015/5/7
+ */
+public class DebugClient {
+
+    static{
+        //set catalina.home temp
+        System.setProperty(ConfigUtils.CATALINA_HOME, "../server/");
+    }
+
+    final static Logger logger = Logger.getLogger(DebugClient.class);
+
+
+    public static void main(String[] args) throws Exception {
+
+        // test_case_data/sandbox/ contains HDP 2.2 site xmls which is dev sandbox
+        ConfigUtils.addClasspath(new File("../examples/test_case_data/sandbox").getAbsolutePath());
+
+        //set log base dir ,will also get from $KYLIN_HOME/tomcat/logs and config [ext.log.base.dir] in kylin.properties
+        System.setProperty(ConfigUtils.KYLIN_LOG_CONF_HOME, "../server/logs");
+
+        //get kylin.properties ,if not exist will get from $KYLIN_HOME/conf/
+        System.setProperty(ConfigUtils.KYLIN_CONF, "../examples/test_case_data/sandbox");
+
+
+        QueryParser queryParser = new QueryParser();
+        HiveJdbcClient jdbcClient = new HiveJdbcClient();
+
+        try {
+            queryParser.start();
+            jdbcClient.start();
+        } catch (Exception e) {
+            logger.info("Exception ",e);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/main/java/org/apache/kylin/monitor/FileUtils.java
----------------------------------------------------------------------
diff --git a/monitor/src/main/java/org/apache/kylin/monitor/FileUtils.java b/monitor/src/main/java/org/apache/kylin/monitor/FileUtils.java
new file mode 100644
index 0000000..555409b
--- /dev/null
+++ b/monitor/src/main/java/org/apache/kylin/monitor/FileUtils.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+*/
+
+
+package org.apache.kylin.monitor;
+
+import au.com.bytecode.opencsv.CSVWriter;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.log4j.Logger;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+/**
+ * Created by jiazhong on 2015/6/18.
+ */
+public class FileUtils {
+
+    final static Logger logger = Logger.getLogger(FileUtils.class);
+
+    public static boolean pathCheck(String filePath) throws IOException {
+        logger.info("checking file:"+filePath);
+        FileSystem fs = null;
+        try {
+            Configuration conf = new Configuration();
+            fs = FileSystem.get(conf);
+            org.apache.hadoop.fs.Path path = new org.apache.hadoop.fs.Path(filePath);
+            if (!fs.exists(path)) {
+                fs.create(path);
+                fs.close();
+                return false;
+            }
+        } catch (Exception e) {
+            fs.close();
+            logger.info("Failed to init:", e);
+        }
+        return true;
+    }
+
+
+    /*
+    * write parse result to hdfs
+    */
+    public static void clearHdfsFile(String dPath) throws IOException {
+        OutputStreamWriter writer = null;
+        FileSystem fs = null;
+        try {
+            fs = getHdfsFileSystem();
+            org.apache.hadoop.fs.Path resultStorePath = new org.apache.hadoop.fs.Path(dPath);
+            writer = new OutputStreamWriter(fs.create(resultStorePath, true));
+
+        } catch (Exception e) {
+            logger.info("Exception", e);
+        } finally {
+            writer.close();
+            fs.close();
+        }
+    }
+
+    /*
+    * write parse result to hdfs
+    */
+    public static void appendResultToHdfs(String dPath, String[] record) throws IOException {
+        OutputStreamWriter writer = null;
+        CSVWriter cwriter = null;
+        FileSystem fs = null;
+        try {
+            fs = getHdfsFileSystem();
+            org.apache.hadoop.fs.Path resultStorePath = new org.apache.hadoop.fs.Path(dPath);
+            writer = new OutputStreamWriter(fs.append(resultStorePath));
+            cwriter = new CSVWriter(writer, '|', CSVWriter.NO_QUOTE_CHARACTER);
+
+            cwriter.writeNext(record);
+
+        } catch (Exception e) {
+            logger.info("Exception", e);
+        } finally {
+            writer.close();
+            cwriter.close();
+            fs.close();
+        }
+    }
+
+    /*
+     * get hdfs fileSystem
+     */
+    public static FileSystem getHdfsFileSystem() throws IOException {
+        Configuration conf = new Configuration();
+//        conf.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");
+        FileSystem fs = null;
+        try {
+            fs = FileSystem.newInstance(conf);
+        } catch (IOException e) {
+            fs.close();
+            logger.info("Failed to get hdfs FileSystem", e);
+        }
+        return fs;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/main/java/org/apache/kylin/monitor/HiveJdbcClient.java
----------------------------------------------------------------------
diff --git a/monitor/src/main/java/org/apache/kylin/monitor/HiveJdbcClient.java b/monitor/src/main/java/org/apache/kylin/monitor/HiveJdbcClient.java
new file mode 100644
index 0000000..71a3a68
--- /dev/null
+++ b/monitor/src/main/java/org/apache/kylin/monitor/HiveJdbcClient.java
@@ -0,0 +1,223 @@
+/*
+ * 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.
+*/
+
+
+package org.apache.kylin.monitor;
+
+import org.apache.log4j.Logger;
+import org.datanucleus.util.StringUtils;
+
+import java.io.IOException;
+import java.sql.*;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+/**
+ * Created by jiazhong on 2015/6/17.
+ */
+public class HiveJdbcClient {
+
+    static String SQL_GENERATE_QUERY_LOG_TABLE = "CREATE EXTERNAL TABLE IF NOT EXISTS [QUERY_LOG_TABLE_NAME] (REQUEST_TIME STRING,REQUEST_DATE DATE, QUERY_SQL STRING,QUERY_USER STRING,IS_SUCCESS STRING,QUERY_LATENCY DECIMAL(19,4),QUERY_PROJECT STRING,REALIZATION_NAMES STRING,CUBOID_IDS STRING,TOTAL_SCAN_COUNT INT,RESULT_ROW_COUNT INT,ACCEPT_PARTIAL STRING,IS_PARTIAL_RESULT STRING,HIT_CACHE STRING,MESSAGE STRING,DEPLOY_ENV STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '|' LINES TERMINATED BY '\\n' LOCATION '[QUERY_LOG_PARSE_RESULT_DIR]' TBLPROPERTIES (\"SKIP.HEADER.LINE.COUNT\"=\"1\")";
+
+    static String SQL_TOTAL_QUERY_USER = "SELECT  COUNT(DISTINCT QUERY_USER) FROM [QUERY_LOG_TABLE_NAME]";
+
+    static String SQL_AVG_DAY_QUERY = "SELECT AVG(A.COUNT_QUERY) FROM (SELECT COUNT(*) COUNT_QUERY,REQUEST_DATE FROM  [QUERY_LOG_TABLE_NAME] GROUP BY REQUEST_DATE) A";
+
+    static String SQL_LAST_30_DAYILY_QUERY_COUNT = "SELECT REQUEST_DATE, COUNT(*) FROM  [QUERY_LOG_TABLE_NAME]  WHERE  REQUEST_DATE>=[START_DATE] AND REQUEST_DATE<[END_DATE]  GROUP BY REQUEST_DATE";
+
+
+    //last 30 days
+    static String SQL_90_PERCENTTILE_LAST_30_DAY = "SELECT PERCENTILE_APPROX(LOG.QUERY_LATENCY,0.9) FROM (SELECT QUERY_LATENCY FROM [QUERY_LOG_TABLE_NAME]  WHERE IS_SUCCESS='true' AND REQUEST_DATE>=[START_DATE] AND REQUEST_DATE<[END_DATE]) LOG";
+
+    //0.9,0.95 [each day] percentile in last 30 days
+    static String SQL_EACH_DAY_PERCENTILE = "SELECT REQUEST_DATE, PERCENTILE_APPROX(QUERY_LATENCY,ARRAY(0.9,0.95)),COUNT(*) FROM  [QUERY_LOG_TABLE_NAME]  WHERE IS_SUCCESS='true' AND REQUEST_DATE>=[START_DATE] AND REQUEST_DATE<[END_DATE]  GROUP BY REQUEST_DATE";
+
+    //0.9,0.95 [project] percentile in last 30 days
+    static String SQL_DAY_PERCENTILE_BY_PROJECT = "SELECT QUERY_PROJECT, PERCENTILE_APPROX(QUERY_LATENCY,ARRAY(0.9,0.95)) FROM  [QUERY_LOG_TABLE_NAME]  WHERE IS_SUCCESS='true' AND  REQUEST_DATE>=[START_DATE] AND REQUEST_DATE<[END_DATE]  GROUP BY QUERY_PROJECT";
+
+
+
+    static String QUERY_LOG_TABLE_NAME = "KYLIN_QUERY_LOG";
+
+    final static Logger logger = Logger.getLogger(HiveJdbcClient.class);
+
+
+    private static String driverName = "org.apache.hive.jdbc.HiveDriver";
+    private static ConfigUtils monitorConfig = ConfigUtils.getInstance();
+
+    static {
+        try {
+            Class.forName(driverName);
+            monitorConfig.loadMonitorParam();
+            QUERY_LOG_TABLE_NAME = monitorConfig.getQueryLogResultTable();
+            if (StringUtils.isEmpty(QUERY_LOG_TABLE_NAME)) {
+                logger.error("table name not defined ,please set param [query.log.parse.result.table] in kylin.properties");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    /*
+     * will create external hive table for [query] log parse result csv file on hdfs
+     * and will generate metric data in csv file on hdfs for web dashboard
+     */
+    public void start() throws SQLException, IOException {
+
+        String CON_URL = monitorConfig.getHiveJdbcConUrl();
+
+        Connection con = DriverManager.getConnection(CON_URL, "", "");
+        Statement stmt = con.createStatement();
+        ResultSet res = null;
+
+        SQL_GENERATE_QUERY_LOG_TABLE = generateQueryLogSql();
+        logger.info("Running Sql (Create Table):" + SQL_GENERATE_QUERY_LOG_TABLE);
+        stmt.execute(SQL_GENERATE_QUERY_LOG_TABLE);
+
+        SQL_TOTAL_QUERY_USER = generateUserCountSql();
+        logger.info("Running Sql (Total User):" + SQL_TOTAL_QUERY_USER);
+        res = stmt.executeQuery(SQL_TOTAL_QUERY_USER);
+
+        String total_query_user_path = monitorConfig.getLogParseResultMetaDir() + "total_query_user.csv";
+        FileUtils.pathCheck(total_query_user_path);
+        FileUtils.clearHdfsFile(total_query_user_path);
+        while (res.next()) {
+            FileUtils.appendResultToHdfs(total_query_user_path, new String[]{res.getString(1)});
+            logger.info("Total User:" + res.getString(1));
+        }
+
+        SQL_AVG_DAY_QUERY = generateAvgDayQuery();
+        logger.info("Running Sql (Avg Day Query):" + SQL_AVG_DAY_QUERY);
+        res = stmt.executeQuery(SQL_AVG_DAY_QUERY);
+
+        String avg_day_query_path = monitorConfig.getLogParseResultMetaDir() + "avg_day_query.csv";
+        FileUtils.pathCheck(avg_day_query_path);
+        FileUtils.clearHdfsFile(avg_day_query_path);
+        while (res.next()) {
+            FileUtils.appendResultToHdfs(avg_day_query_path, new String[]{res.getString(1)});
+            logger.info("avg day query:" + res.getString(1));
+        }
+
+
+        SQL_LAST_30_DAYILY_QUERY_COUNT = generateLast30DayilyQueryCount();
+        logger.info("Running Sql (Daily Query Count):" + SQL_LAST_30_DAYILY_QUERY_COUNT);
+        res = stmt.executeQuery(SQL_LAST_30_DAYILY_QUERY_COUNT);
+
+        String last_30_daily_query_count_path = monitorConfig.getLogParseResultMetaDir() + "last_30_daily_query_count.csv";
+        FileUtils.pathCheck(last_30_daily_query_count_path);
+        FileUtils.clearHdfsFile(last_30_daily_query_count_path);
+        while (res.next()) {
+            FileUtils.appendResultToHdfs(last_30_daily_query_count_path, new String[]{res.getString(1),res.getString(2)});
+            logger.info("last 30 daily query count:" + res.getString(1)+","+res.getString(2));
+        }
+
+
+        //90 percentile latency for all query in last 30 days
+        SQL_90_PERCENTTILE_LAST_30_DAY = generateNintyPercentileSql();
+        logger.info("Running Sql (last 30 days ,90 percentile query latency):" + SQL_90_PERCENTTILE_LAST_30_DAY);
+        res = stmt.executeQuery(SQL_90_PERCENTTILE_LAST_30_DAY);
+
+        String last_30_day_90_percentile_latency = monitorConfig.getLogParseResultMetaDir() + "last_30_day_90_percentile_latency.csv";
+        FileUtils.pathCheck(last_30_day_90_percentile_latency);
+        FileUtils.clearHdfsFile(last_30_day_90_percentile_latency);
+        while (res.next()) {
+            FileUtils.appendResultToHdfs(last_30_day_90_percentile_latency, new String[]{res.getString(1)});
+            logger.info("last 30 day 90 percentile latency:" + res.getString(1));
+        }
+
+        //90,95 project percentile latency for all query in last 30 days
+        SQL_DAY_PERCENTILE_BY_PROJECT = generateProjectPercentileSql();
+        logger.info("Running Sql (last 30 days ,90,95 percentile query latency by project):" + SQL_DAY_PERCENTILE_BY_PROJECT);
+        res = stmt.executeQuery(SQL_DAY_PERCENTILE_BY_PROJECT);
+
+        String last_30_day_project_percentile_latency_path = monitorConfig.getLogParseResultMetaDir() + "project_90_95_percentile_latency.csv";
+        FileUtils.pathCheck(last_30_day_project_percentile_latency_path);
+        FileUtils.clearHdfsFile(last_30_day_project_percentile_latency_path);
+        while (res.next() && res.getMetaData().getColumnCount() == 2) {
+            FileUtils.appendResultToHdfs(last_30_day_project_percentile_latency_path, new String[]{res.getString(1), res.getString(2)});
+            logger.info(res.getString(1) + "," + res.getString(2));
+        }
+
+        //0.9,0.95 percentile latency of every day in last 30 day
+        SQL_EACH_DAY_PERCENTILE = generateEachDayPercentileSql();
+        logger.info("Running sql (0.9,0.95 latency):" + SQL_EACH_DAY_PERCENTILE);
+        String each_day_percentile_file = monitorConfig.getLogParseResultMetaDir() + "each_day_90_95_percentile_latency.csv";
+        FileUtils.pathCheck(each_day_percentile_file);
+        FileUtils.clearHdfsFile(each_day_percentile_file);
+
+        res = stmt.executeQuery(SQL_EACH_DAY_PERCENTILE);
+        while (res.next() && res.getMetaData().getColumnCount() == 3) {
+            FileUtils.appendResultToHdfs(each_day_percentile_file, new String[]{res.getString(1), res.getString(2),res.getString(3)});
+            logger.info(res.getString(1) + "," + res.getString(2)+ "," + res.getString(3));
+        }
+
+    }
+
+    public String generateQueryLogSql() {
+        String query_log_parse_result_dir = monitorConfig.getQueryLogParseResultDir();
+        String query_log_table_name = monitorConfig.getQueryLogResultTable();
+        return SQL_GENERATE_QUERY_LOG_TABLE.replace("[QUERY_LOG_PARSE_RESULT_DIR]", query_log_parse_result_dir).replace("[QUERY_LOG_TABLE_NAME]", query_log_table_name);
+    }
+
+    public String generateUserCountSql() {
+        return SQL_TOTAL_QUERY_USER.replace("[QUERY_LOG_TABLE_NAME]", QUERY_LOG_TABLE_NAME);
+    }
+
+    public String generateAvgDayQuery() {
+        return SQL_AVG_DAY_QUERY.replace("[QUERY_LOG_TABLE_NAME]", QUERY_LOG_TABLE_NAME);
+    }
+
+    public String generateLast30DayilyQueryCount() {
+        SQL_LAST_30_DAYILY_QUERY_COUNT = SQL_LAST_30_DAYILY_QUERY_COUNT.replace("[QUERY_LOG_TABLE_NAME]", QUERY_LOG_TABLE_NAME);
+        return monthStasticSqlConvert(SQL_LAST_30_DAYILY_QUERY_COUNT);
+    }
+
+
+
+    //last 30 days
+    public String generateNintyPercentileSql() {
+        SQL_90_PERCENTTILE_LAST_30_DAY = SQL_90_PERCENTTILE_LAST_30_DAY.replace("[QUERY_LOG_TABLE_NAME]", QUERY_LOG_TABLE_NAME);
+        return monthStasticSqlConvert(SQL_90_PERCENTTILE_LAST_30_DAY);
+    }
+
+    //last 30 days,each day 90,95 percentile
+    public String generateProjectPercentileSql() {
+        SQL_DAY_PERCENTILE_BY_PROJECT = SQL_DAY_PERCENTILE_BY_PROJECT.replace("[QUERY_LOG_TABLE_NAME]", QUERY_LOG_TABLE_NAME);
+        return monthStasticSqlConvert(SQL_DAY_PERCENTILE_BY_PROJECT);
+    }
+
+    public String generateEachDayPercentileSql() {
+        SQL_EACH_DAY_PERCENTILE = SQL_EACH_DAY_PERCENTILE.replace("[QUERY_LOG_TABLE_NAME]", QUERY_LOG_TABLE_NAME);
+        return monthStasticSqlConvert(SQL_EACH_DAY_PERCENTILE);
+    }
+
+    public String monthStasticSqlConvert(String sql) {
+
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+        Calendar cal = Calendar.getInstance();
+        cal.add(Calendar.DATE, -1);
+        String endDate = format.format(cal.getTime());
+        cal.add(Calendar.DATE, -30);
+        String startDate = format.format(cal.getTime());
+        return sql.replace("[START_DATE]", "'" + startDate + "'").replace("[END_DATE]", "'" + endDate + "'");
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/main/java/org/apache/kylin/monitor/MonitorMetaManager.java
----------------------------------------------------------------------
diff --git a/monitor/src/main/java/org/apache/kylin/monitor/MonitorMetaManager.java b/monitor/src/main/java/org/apache/kylin/monitor/MonitorMetaManager.java
new file mode 100644
index 0000000..c01cf66
--- /dev/null
+++ b/monitor/src/main/java/org/apache/kylin/monitor/MonitorMetaManager.java
@@ -0,0 +1,217 @@
+/*
+ * 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.
+*/
+
+
+package org.apache.kylin.monitor;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.*;
+import org.apache.hadoop.hbase.client.*;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.log4j.Logger;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Created by jiazhong on 2015/5/25.
+ */
+public class MonitorMetaManager {
+
+    private static ConfigUtils monitorConfig = ConfigUtils.getInstance();
+
+    static String TABLE_NAME = "kylin_metadata";
+    final static String COLUMN_FAMILY = "f";
+    final static String COLUMN = "c";
+    final static String ROW_KEY_QUERY_READ_FILES = "/performance/query_log_files_already_read";
+    final static String ROW_KEY_QUERY_READING_FILE = "/performance/query_log_file_reading";
+    final static String ROW_KEY_QUERY_READING_FILE_LINE = "/performance/query_log_file_reading";
+
+
+    final static String ROW_KEY_API_REQ_LOG_READ_FILES = "/performance/api_req_log_files_already_read";
+
+
+    final static Logger logger = Logger.getLogger(MonitorMetaManager.class);
+
+    static Configuration conf = null;
+
+    static {
+        try {
+            monitorConfig.loadMonitorParam();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        conf = HBaseConfiguration.create();
+    }
+
+
+    /*
+     * meta data initialize
+     * @unused
+     */
+    public static void init() throws Exception {
+        MonitorMetaManager.TABLE_NAME = MonitorMetaManager.getMetadataUrlPrefix();
+        logger.info("Monitor Metadata Table :"+MonitorMetaManager.TABLE_NAME);
+        logger.info("init monitor metadata,create table if not exist");
+        MonitorMetaManager.creatTable(TABLE_NAME, new String[]{COLUMN_FAMILY});
+    }
+
+    public static String getMetadataUrlPrefix() {
+        String hbaseMetadataUrl = monitorConfig.getMetadataUrl();
+        String defaultPrefix = "kylin_metadata";
+        int cut = hbaseMetadataUrl.indexOf('@');
+        String tmp = cut < 0 ? defaultPrefix : hbaseMetadataUrl.substring(0, cut);
+        return tmp;
+    }
+
+
+    /*
+     * mark query file as read after parsing
+     */
+    public static void markQueryFileAsRead(String filename) throws IOException {
+        String read_query_log_file = MonitorMetaManager.getReadQueryLogFiles();
+        if(StringUtils.isEmpty(read_query_log_file)){
+            read_query_log_file =  filename;
+        }else{
+            read_query_log_file = read_query_log_file.concat(",").concat(filename);
+        }
+        MonitorMetaManager.updateData(TABLE_NAME, ROW_KEY_QUERY_READ_FILES, COLUMN_FAMILY,COLUMN, read_query_log_file);
+    }
+
+    /*
+     * mark reading file for tracking
+     */
+    public static void markQueryReadingFile(String query_reading_file) throws IOException {
+        MonitorMetaManager.updateData(TABLE_NAME, ROW_KEY_QUERY_READING_FILE, COLUMN_FAMILY,COLUMN, query_reading_file);
+    }
+
+    /*
+     * mark reading line for tracking
+     */
+    public static void markQueryReadingLine(String line_num) throws IOException {
+        MonitorMetaManager.updateData(TABLE_NAME, ROW_KEY_QUERY_READING_FILE_LINE, COLUMN_FAMILY,COLUMN, line_num);
+    }
+
+
+    /*
+     * get has been read file name list
+     */
+    public static String[] getReadQueryLogFileList() throws IOException {
+        String fileList = MonitorMetaManager.getReadQueryLogFiles();
+        return fileList.split(",");
+    }
+
+    /*
+     * get has been read query log file
+     */
+    public static String getReadQueryLogFiles() throws IOException {
+        return getListWithRowkey(TABLE_NAME, ROW_KEY_QUERY_READ_FILES);
+    }
+
+
+    /*
+     * get has been read file
+    */
+    public static String getListWithRowkey(String table, String rowkey) throws IOException {
+        Result result = getResultByRowKey(table, rowkey);
+        String fileList = null;
+        if (result.list() != null) {
+            for (KeyValue kv : result.list()) {
+                fileList = Bytes.toString(kv.getValue());
+            }
+
+        }
+        fileList = fileList==null?"":fileList;
+        return fileList;
+    }
+
+
+    /*
+     * mark api req log file as read after parsing
+     */
+    public static void markApiReqLogFileAsRead(String filename) throws IOException {
+        String read_api_req_log_files = MonitorMetaManager.getReadApiReqLogFiles();
+        if (StringUtils.isEmpty(read_api_req_log_files)) {
+            read_api_req_log_files = filename;
+        } else {
+            read_api_req_log_files = read_api_req_log_files.concat(",").concat(filename);
+        }
+        MonitorMetaManager.updateData(TABLE_NAME, ROW_KEY_API_REQ_LOG_READ_FILES, COLUMN_FAMILY,COLUMN, read_api_req_log_files);
+    }
+
+
+    /*
+     * get has been read log file name list
+     */
+    public static String[] getReadApiReqLogFileList() throws IOException {
+        String fileList = MonitorMetaManager.getReadApiReqLogFiles();
+        return fileList.split(",");
+    }
+
+    /*
+    * get has been read api request log file
+    */
+    public static String getReadApiReqLogFiles() throws IOException {
+        return getListWithRowkey(TABLE_NAME, ROW_KEY_API_REQ_LOG_READ_FILES);
+    }
+
+
+    /*
+     * create table in hbase
+     */
+    public static void creatTable(String tableName, String[] family) throws Exception {
+        HBaseAdmin admin = new HBaseAdmin(conf);
+        HTableDescriptor desc = new HTableDescriptor(tableName);
+        for (int i = 0; i < family.length; i++) {
+            desc.addFamily(new HColumnDescriptor(family[i]));
+        }
+        if (admin.tableExists(tableName)) {
+            logger.info("table Exists!");
+        } else {
+            admin.createTable(desc);
+            logger.info("create table Success!");
+        }
+    }
+
+    /*
+     * update cell in hbase
+     */
+    public static void updateData(String tableName, String rowKey, String family,String column, String value) throws IOException {
+        HTable table = new HTable(conf, Bytes.toBytes(tableName));
+        Put put = new Put(rowKey.getBytes());
+        put.add(family.getBytes(), column.getBytes(), value.getBytes());
+        try {
+            table.put(put);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        logger.info("end insert data ......");
+    }
+
+    /*
+     * get result by rowkey
+     */
+    public static Result getResultByRowKey(String tableName, String rowKey) throws IOException {
+        HTable table = new HTable(conf, Bytes.toBytes(tableName));
+        Get get = new Get(Bytes.toBytes(rowKey));
+        Result result = table.get(get);
+        return result;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/main/java/org/apache/kylin/monitor/QueryParser.java
----------------------------------------------------------------------
diff --git a/monitor/src/main/java/org/apache/kylin/monitor/QueryParser.java b/monitor/src/main/java/org/apache/kylin/monitor/QueryParser.java
new file mode 100644
index 0000000..fc8a403
--- /dev/null
+++ b/monitor/src/main/java/org/apache/kylin/monitor/QueryParser.java
@@ -0,0 +1,249 @@
+/*
+ * 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.
+*/
+
+package org.apache.kylin.monitor;
+
+import au.com.bytecode.opencsv.CSVWriter;
+import org.apache.commons.io.filefilter.RegexFileFilter;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.*;
+import org.apache.log4j.Logger;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author jiazhong
+ */
+public class QueryParser {
+
+    final static Logger logger = Logger.getLogger(QueryParser.class);
+    final static Charset ENCODING = StandardCharsets.UTF_8;
+    final static String QUERY_LOG_FILE_PATTERN = "kylin_query.log.(\\d{4}-\\d{2}-\\d{2})$";
+    final static String QUERY_LOG_PARSE_RESULT_FILENAME = "kylin_query_log.csv";
+    static String QUERY_PARSE_RESULT_PATH = null;
+    static  String DEPLOY_ENV;
+
+    final static String[] KYLIN_QUERY_CSV_HEADER = {"REQ_TIME","REQ_DATE", "SQL", "USER", "IS_SUCCESS", "LATENCY", "PROJECT", "REALIZATION NAMES", "CUBOID IDS", "TOTAL SCAN COUNT", "RESULT ROW COUNT", "ACCEPT PARTIAL", "IS PARTIAL RESULT", "HIT CACHE", "MESSAGE","DEPLOY_ENV"};
+
+    private ConfigUtils monitorConfig;
+
+    public QueryParser() {
+        monitorConfig = ConfigUtils.getInstance();
+        try {
+            monitorConfig.loadMonitorParam();
+            DEPLOY_ENV = monitorConfig.getDeployEnv();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /*
+     * will parse kylin query log files ,and append result to csv on hdfs
+     * files read will be marked,will not read again
+     */
+
+    public void start() throws IOException, ParseException {
+        QueryParser.QUERY_PARSE_RESULT_PATH = ConfigUtils.getInstance().getQueryLogParseResultDir() + QUERY_LOG_PARSE_RESULT_FILENAME;
+        this.parseQueryInit();
+
+        //get query file has been read
+        String[] hasReadFiles = MonitorMetaManager.getReadQueryLogFileList();
+
+        //get all log files
+        List<File> files = this.getQueryLogFiles();
+
+        for (File file : files) {
+            if (!Arrays.asList(hasReadFiles).contains(file.getName())) {
+                this.parseQueryLog(file.getPath(), QueryParser.QUERY_PARSE_RESULT_PATH);
+                MonitorMetaManager.markQueryFileAsRead(file.getName());
+            }
+        }
+    }
+
+    public void parseQueryInit() throws IOException {
+        logger.info("parse query initializing...");
+        FileSystem fs = null;
+        try {
+            Configuration conf = new Configuration();
+            fs = FileSystem.get(conf);
+            org.apache.hadoop.fs.Path path = new org.apache.hadoop.fs.Path(QueryParser.QUERY_PARSE_RESULT_PATH);
+            if (!fs.exists(path)) {
+                fs.create(path);
+                fs.close(); //need to close before get FileSystem again
+                this.writeResultToHdfs(QueryParser.QUERY_PARSE_RESULT_PATH, QueryParser.KYLIN_QUERY_CSV_HEADER);
+            }
+        } catch (IOException e) {
+            fs.close();
+            logger.info("Failed to init:", e);
+        }
+    }
+
+    //parse query log and convert to csv file to hdfs
+    public void parseQueryLog(String filePath, String dPath) throws ParseException, IOException {
+
+        logger.info("Start parsing file " + filePath + " !");
+
+//        writer config init
+        FileSystem fs = this.getHdfsFileSystem();
+        org.apache.hadoop.fs.Path resultStorePath = new org.apache.hadoop.fs.Path(dPath);
+        OutputStreamWriter writer = new OutputStreamWriter(fs.append(resultStorePath));
+        CSVWriter cwriter = new CSVWriter(writer,'|',CSVWriter.NO_QUOTE_CHARACTER);
+
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
+        Pattern p_query_start = Pattern.compile("^\\[.*\\]:\\[(.*),.*\\]\\[.*\\]\\[.*QueryService.logQuery.*\\].*");
+        Pattern p_query_end = Pattern.compile("^Message:(.*)$");
+        Pattern p_query_body = Pattern.compile("^\\[.*\\]:\\[((\\d{4}-\\d{2}-\\d{2}).*)\\]\\[.*\\]\\[.*\\].*\n^=+\\[QUERY\\]=+\n^SQL:(.*)\n^User:(.*)\n^Success:(.*)\n^Duration:(.*)\n^Project:(.*)\n^(Realization Names|Cube Names): \\[(.*)\\]\n^Cuboid Ids: \\[(.*)\\]\n^Total scan count:(.*)\n^Result row count:(.*)\n^Accept Partial:(.*)\n(^Is Partial Result:(.*)\n)?^Hit Cache:(.*)\n^Message:(.*)", Pattern.MULTILINE);
+        Matcher m_query_start = p_query_start.matcher("");
+        Matcher m_query_end = p_query_end.matcher("");
+        Matcher m_query_body = p_query_body.matcher("");
+
+        boolean query_start = false;
+        StringBuffer query_body = new StringBuffer("");
+        Path path = Paths.get(filePath);
+        try {
+            BufferedReader reader = Files.newBufferedReader(path, ENCODING);
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                m_query_start.reset(line); //reset the input
+                m_query_end.reset(line);
+
+                // set start flag ,clear StringBuffer
+                if (m_query_start.find()) {
+                    query_start = true;
+                    query_body = new StringBuffer("");
+                }
+                if (query_start) {
+                    query_body.append(line + "\n");
+                }
+                if (m_query_end.find()) {
+                    query_start = false;
+                    m_query_body.reset(query_body);
+                    logger.info("parsing query...");
+                    logger.info(query_body);
+//                    skip group(8) and group(14)
+                    if (m_query_body.find()) {
+                        ArrayList<String> groups = new ArrayList<String>();
+                        int grp_count = m_query_body.groupCount();
+                        for (int i = 1; i <= grp_count; i++) {
+                            if (i != 8 && i != 14) {
+                                String grp_item = m_query_body.group(i);
+                                grp_item = grp_item ==null?"":grp_item.trim();
+                                groups.add(grp_item);
+                            }
+                        }
+
+                        long start_time = format.parse(groups.get(0)).getTime() - (int) (Double.parseDouble(groups.get(5)) * 1000);
+                        groups.set(0, format.format(new Date(start_time)));
+                        groups.add(DEPLOY_ENV);
+                        String[] recordArray = groups.toArray(new String[groups.size()]);
+//                        write to hdfs
+                        cwriter.writeNext(recordArray);
+
+                    }
+
+                }
+
+            }
+        } catch (IOException ex) {
+            logger.info("Failed to write to hdfs:", ex);
+        } finally {
+            writer.close();
+            cwriter.close();
+            fs.close();
+        }
+
+        logger.info("Finish parsing file " + filePath + " !");
+
+    }
+
+    /*
+     * write parse result to hdfs
+     */
+    public void writeResultToHdfs(String dPath, String[] record) throws IOException {
+        OutputStreamWriter writer = null;
+        CSVWriter cwriter = null;
+        FileSystem fs = null;
+        try {
+            fs = this.getHdfsFileSystem();
+            org.apache.hadoop.fs.Path resultStorePath = new org.apache.hadoop.fs.Path(dPath);
+            writer = new OutputStreamWriter(fs.append(resultStorePath));
+            cwriter = new CSVWriter(writer,'|',CSVWriter.NO_QUOTE_CHARACTER);
+
+            cwriter.writeNext(record);
+
+        } catch (IOException e) {
+            logger.info("Exception", e);
+        } finally {
+            writer.close();
+            cwriter.close();
+            fs.close();
+        }
+    }
+
+
+    /*
+     * get all query log files
+     */
+    public List<File> getQueryLogFiles() {
+        List<File> logFiles = new ArrayList<File>();
+
+        List<String> query_log_dir_list = monitorConfig.getLogBaseDir();
+        FileFilter filter = new RegexFileFilter(QUERY_LOG_FILE_PATTERN);
+
+        for (String path : query_log_dir_list) {
+            logger.info("fetching query log file from path:" + path);
+            File query_log_dir = new File(path);
+            File[] query_log_files = query_log_dir.listFiles(filter);
+            if (query_log_files == null) {
+                logger.warn("no query log file found under path" + path);
+                continue;
+            }
+
+            Collections.addAll(logFiles, query_log_files);
+        }
+        return logFiles;
+    }
+
+
+    /*
+     * get hdfs fileSystem
+     */
+    public FileSystem getHdfsFileSystem() throws IOException {
+        Configuration conf = new Configuration();
+        conf.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");
+        FileSystem fs = null;
+        try {
+            fs = FileSystem.get(conf);
+        } catch (IOException e) {
+            fs.close();
+            logger.info("Failed to get hdfs FileSystem", e);
+        }
+        return fs;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/monitor/src/main/resources/log4j.properties b/monitor/src/main/resources/log4j.properties
new file mode 100644
index 0000000..6dec581
--- /dev/null
+++ b/monitor/src/main/resources/log4j.properties
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+log4j.rootLogger=INFO,stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=L4J [%d{yyyy-MM-dd HH:mm:ss,SSS}][%p][%c] - %m%n
+
+log4j.appender.monitor=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.monitor.layout=org.apache.log4j.PatternLayout
+log4j.appender.monitor.File=${CATALINA_HOME}logs/kylin_monitor.log
+log4j.appender.monitor.layout.ConversionPattern=[%t]:[%d{yyyy-MM-dd HH:mm:ss,SSS}][%p][%l] - %m%n
+log4j.appender.monitor.Append=true
+
+#log4j.logger.org.apache.hadoop=ERROR
+log4j.logger.org.apache.kylin=DEBUG,monitor

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/monitor/src/test/java/org/apache/kylin/monitor/ParseLogTest.java
----------------------------------------------------------------------
diff --git a/monitor/src/test/java/org/apache/kylin/monitor/ParseLogTest.java b/monitor/src/test/java/org/apache/kylin/monitor/ParseLogTest.java
new file mode 100644
index 0000000..7b4e7b7
--- /dev/null
+++ b/monitor/src/test/java/org/apache/kylin/monitor/ParseLogTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+*/
+
+
+package org.apache.kylin.monitor;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.ParseException;
+
+/**
+ * Created by jiazhong on 2015/5/27.
+ */
+public class ParseLogTest {
+
+    private QueryParser queryParser;
+    private ApiRequestParser apiReqParser;
+
+    @BeforeClass
+    public static void beforeClass() throws Exception {
+        //set catalina.home temp
+        System.setProperty(ConfigUtils.CATALINA_HOME, "../server/");
+
+        //test_case_data/sandbox/ contains HDP 2.2 site xmls which is dev sandbox
+        ConfigUtils.addClasspath(new File("../examples/test_case_data/sandbox").getAbsolutePath());
+
+        //get log base dir
+        System.setProperty(ConfigUtils.KYLIN_LOG_CONF_HOME, "../examples/test_case_data/performance_data");
+
+        //get kylin.properties
+        System.setProperty(ConfigUtils.KYLIN_CONF, "../examples/test_case_data/sandbox");
+
+    }
+
+
+    @Before
+    public void before(){
+        queryParser = new QueryParser();
+        apiReqParser = new ApiRequestParser();
+    }
+
+    @Test
+    public void test() throws Exception {
+        testQueryParseing();
+        testApiReqParsing();
+    }
+
+    private void testQueryParseing() throws IOException, ParseException {
+        queryParser.getQueryLogFiles();
+    }
+
+    private void testApiReqParsing(){
+        apiReqParser.getRequestLogFiles();
+    }
+
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 5748328..cdd8191 100644
--- a/pom.xml
+++ b/pom.xml
@@ -557,6 +557,7 @@
         <module>query</module>
         <module>server</module>
         <module>jdbc</module>
+        <module>monitor</module>
         <module>invertedindex</module>
     </modules>
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/script/prepare.sh
----------------------------------------------------------------------
diff --git a/script/prepare.sh b/script/prepare.sh
index a8b1c7d..f0702f8 100755
--- a/script/prepare.sh
+++ b/script/prepare.sh
@@ -33,11 +33,13 @@ cp server/target/kylin-server-${version}.war tomcat/webapps/kylin.war
 cp job/target/kylin-job-${version}-job.jar lib/kylin-job-${version}.jar
 cp storage/target/kylin-storage-${version}-coprocessor.jar lib/kylin-coprocessor-${version}.jar
 cp jdbc/target/kylin-jdbc-${version}.jar lib/kylin-jdbc-${version}.jar
+cp monitor/target/kylin-monitor-${version}.jar lib/kylin-monitor-${version}.jar
 # Copied file becomes 000 for some env (e.g. my Cygwin)
 chmod 644 tomcat/webapps/kylin.war
 chmod 644 lib/kylin-job-${version}.jar
 chmod 644 lib/kylin-coprocessor-${version}.jar
 chmod 644 lib/kylin-jdbc-${version}.jar
+chmod 644 lib/kylin-monitor-${version}.jar
 
 echo "add js css to war"
 if [ ! -d "webapp/dist" ]

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 1578c62..8500426 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -444,6 +444,11 @@
             <version>${jetty.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.github.isrsal</groupId>
+            <artifactId>spring-mvc-logger</artifactId>
+            <version>0.2</version>
+        </dependency>
     </dependencies>
 
     <build>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/server/src/main/java/org/apache/kylin/rest/controller/PerformanceController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/PerformanceController.java b/server/src/main/java/org/apache/kylin/rest/controller/PerformanceController.java
new file mode 100644
index 0000000..735db51
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/controller/PerformanceController.java
@@ -0,0 +1,125 @@
+/*
+ * 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.
+*/
+
+package org.apache.kylin.rest.controller;
+
+import com.codahale.metrics.annotation.Metered;
+import com.codahale.metrics.annotation.Timed;
+import net.sf.ehcache.CacheManager;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.rest.service.CubeService;
+import org.apache.kylin.rest.service.PerformService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Handle query requests.
+ *
+ * @author xduo
+ */
+@Controller
+@RequestMapping(value = "/performance")
+public class PerformanceController extends BasicController {
+
+    private static final Logger logger = LoggerFactory.getLogger(PerformanceController.class);
+
+
+    @Autowired
+    private PerformService performService;
+
+    @Autowired
+    private CubeService cubeService;
+
+    @Autowired
+    private CacheManager cacheManager;
+
+    @RequestMapping(value = "/eachDayPercentile", method = RequestMethod.GET)
+    @ResponseBody
+    @Timed(name = "eachDayPercentile")
+    public List<String[]> eachDayPercentile() throws IOException {
+        return performService.eachDayPercentile();
+    }
+
+    @RequestMapping(value = "/projectPercentile", method = RequestMethod.GET)
+    @ResponseBody
+    @Timed(name = "projectPercentile")
+    public List<String[]> projectPercentile() throws IOException {
+        return performService.projectPercentile();
+    }
+
+
+    @RequestMapping(value = "/last30DayPercentile", method = RequestMethod.GET)
+    @ResponseBody
+    @Timed(name = "last30DayPercentile")
+    public List<String[]> last30DayPercentile() throws IOException {
+        return performService.last30DayPercentile();
+    }
+
+    @RequestMapping(value = "/cubesStorage", method = {RequestMethod.GET})
+    @ResponseBody
+    @Metered(name = "cubesStorage")
+    public List<CubeInstance> getCubeStorage() {
+        return cubeService.listAllCubes(null, null);
+    }
+
+
+    @RequestMapping(value = "/totalQueryUser", method = {RequestMethod.GET})
+    @ResponseBody
+    @Metered(name = "totalQueryUser")
+    public List<String[]> totalQueryUser() throws IOException {
+        return performService.getTotalQueryUser();
+    }
+
+    @RequestMapping(value = "/dailyQueryCount", method = {RequestMethod.GET})
+    @ResponseBody
+    @Metered(name = "dailyQueryCount")
+    public List<String[]> dailyQueryCount() throws IOException {
+        return performService.dailyQueryCount();
+    }
+
+    @RequestMapping(value = "/avgDayQuery", method = {RequestMethod.GET})
+    @ResponseBody
+    @Metered(name = "avgDayQuery")
+    public List<String[]> avgDayQuery() throws IOException {
+        return performService.avgDayQuery();
+    }
+
+    @RequestMapping(value = "/listCubes", method = {RequestMethod.GET})
+    @ResponseBody
+    @Metered(name = "listCubes")
+    public List<CubeInstance> getCubes() {
+        return cubeService.listAllCubes(null,null);
+    }
+
+
+
+    public void setCubeService(CubeService cubeService) {
+        this.cubeService = cubeService;
+    }
+
+    public void setPerformService(PerformService performService) {
+        this.performService = performService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/server/src/main/java/org/apache/kylin/rest/filter/KylinApiFilter.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/filter/KylinApiFilter.java b/server/src/main/java/org/apache/kylin/rest/filter/KylinApiFilter.java
new file mode 100644
index 0000000..035b57d
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/filter/KylinApiFilter.java
@@ -0,0 +1,121 @@
+package org.apache.kylin.rest.filter;
+
+import com.github.isrsal.logging.RequestWrapper;
+import com.github.isrsal.logging.ResponseWrapper;
+import com.sun.jersey.core.util.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Created by jiazhong on 2015/4/20.
+ */
+
+public class KylinApiFilter extends OncePerRequestFilter {
+    protected static final Logger logger = LoggerFactory.getLogger(KylinApiFilter.class);
+    private static final String REQUEST_PREFIX = "Request: ";
+    private static final String RESPONSE_PREFIX = "Response: ";
+    private AtomicLong id = new AtomicLong(1L);
+
+    public KylinApiFilter() {
+    }
+
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+        if(logger.isDebugEnabled()) {
+            long requestId = this.id.incrementAndGet();
+            request = new RequestWrapper(Long.valueOf(requestId), (HttpServletRequest)request);
+            response = new ResponseWrapper(Long.valueOf(requestId), (HttpServletResponse)response);
+        }
+
+        try {
+            filterChain.doFilter((ServletRequest)request, (ServletResponse)response);
+        } finally {
+            if(logger.isDebugEnabled()) {
+                this.logRequest((HttpServletRequest)request,(ResponseWrapper)response);
+//                this.logResponse((ResponseWrapper)response);
+            }
+
+        }
+
+    }
+
+    private void logRequest(HttpServletRequest request,ResponseWrapper response) {
+        StringBuilder msg = new StringBuilder();
+        msg.append("REQUEST: ");
+        HttpSession session = request.getSession(true);
+        SecurityContext context = (SecurityContext)session.getAttribute("SPRING_SECURITY_CONTEXT");
+
+        String requester="";
+        if(context!=null){
+            Authentication authentication=  context.getAuthentication();
+            if(authentication!=null){
+                requester = authentication.getName();
+            }
+
+        }else {
+            final String authorization = request.getHeader("Authorization");
+            if (authorization != null && authorization.startsWith("Basic")) {
+                // Authorization: Basic base64credentials
+                String base64Credentials = authorization.substring("Basic".length()).trim();
+                String credentials = new String(Base64.decode(base64Credentials), Charset.forName("UTF-8"));
+                // credentials = username:password
+                String[] values = credentials.split(":", 2);
+                requester = values[0];
+            }
+        }
+        msg.append("REQUESTER="+requester);
+
+        SimpleDateFormat format = new SimpleDateFormat("z yyyy-MM-dd HH:mm:ss");
+        msg.append(";REQ_TIME=" + format.format(new Date()));
+        msg.append(";URI=").append(request.getRequestURI());
+        msg.append(";METHOD=").append(request.getMethod());
+        msg.append(";QUERY_STRING=").append(request.getQueryString());
+        if(request instanceof RequestWrapper && !this.isMultipart(request)) {
+            RequestWrapper requestWrapper = (RequestWrapper)request;
+
+            try {
+                String e = requestWrapper.getCharacterEncoding() != null?requestWrapper.getCharacterEncoding():"UTF-8";
+                msg.append(";PAYLOAD=").append(new String(requestWrapper.toByteArray(), e));
+            } catch (UnsupportedEncodingException var6) {
+                logger.warn("Failed to parse request payload", var6);
+            }
+        }
+        msg.append(";RESP_STATUS="+response.getStatus()).append(";");
+
+        logger.debug(msg.toString());
+    }
+
+    private boolean isMultipart(HttpServletRequest request) {
+        return request.getContentType() != null && request.getContentType().startsWith("multipart/form-data");
+    }
+
+    private void logResponse(ResponseWrapper response) {
+        StringBuilder msg = new StringBuilder();
+        msg.append("RESPONSE: ");
+        msg.append("REQUEST_ID=").append(response.getId());
+
+        try {
+            msg.append("; payload=").append(new String(response.toByteArray(), response.getCharacterEncoding()));
+        } catch (UnsupportedEncodingException var4) {
+            logger.warn("Failed to parse response payload", var4);
+        }
+
+        logger.debug(msg.toString());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
index de97a7b..71e9f19 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
@@ -19,6 +19,9 @@
 package org.apache.kylin.rest.service;
 
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FSDataInputStream;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hbase.client.HTable;
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.util.HBaseRegionSizeCalculator;
@@ -556,4 +559,5 @@ public class CubeService extends BasicService {
     }
 
 
+
 }


[2/4] incubator-kylin git commit: KYLIN-792 ,add performance module

Posted by zh...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/webapp/app/css/AdminLTE.css
----------------------------------------------------------------------
diff --git a/webapp/app/css/AdminLTE.css b/webapp/app/css/AdminLTE.css
index ac467b8..e91795e 100644
--- a/webapp/app/css/AdminLTE.css
+++ b/webapp/app/css/AdminLTE.css
@@ -1,116 +1,143 @@
+@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic);
 /*!
- *   AdminLTE v1.2
- *   Author: AlmsaeedStudio.com
+ *   AdminLTE v2.1.0
+ *   Author: Almsaeed Studio
+ *	 Website: Almsaeed Studio <http://almsaeedstudio.com>
  *   License: Open source - MIT
  *           Please visit http://opensource.org/licenses/MIT for more information
 !*/
 /*
-    Core: General style
-----------------------------
-*/
+ * Core: General Layout Style
+ * -------------------------
+ */
 html,
 body {
-  font-family: 'Source Sans Pro', sans-serif;
-  -webkit-font-smoothing: antialiased;
   min-height: 100%;
 }
-a {
-  color: #3c8dbc;
+.layout-boxed html,
+.layout-boxed body {
+  height: 100%;
 }
-a:hover,
-a:active,
-a:focus {
-  outline: none;
-  text-decoration: none;
-  color: #72afd2;
+body {
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  font-weight: 400;
+  overflow-x: hidden;
+  overflow-y: auto;
 }
-/* Layouts */
+/* Layout */
 .wrapper {
   min-height: 100%;
+  position: relative;
+  overflow: hidden!important;
 }
 .wrapper:before,
 .wrapper:after {
-  display: table;
   content: " ";
+  display: table;
 }
 .wrapper:after {
   clear: both;
 }
-/* Header */
-body > .header {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  z-index: 1030;
-}
-/* Define 2 column template */
-.right-side,
-.left-side {
+.layout-boxed .wrapper {
+  max-width: 1250px;
+  margin: 0 auto;
   min-height: 100%;
-  display: block;
+  box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
+  position: relative;
 }
-/*right side - contins main content*/
-.right-side {
-  background-color: #f9f9f9;
-  margin-left: 220px;
+.layout-boxed {
+  background: url('../img/boxed-bg.jpg') repeat fixed;
 }
-/*left side - contains sidebar*/
-.left-side {
-  position: absolute;
-  width: 220px;
-  top: 0;
+/*
+ * Content Wrapper - contains the main content
+ * ```.right-side has been deprecated as of v2.0.0 in favor of .content-wrapper  ```
+ */
+.content-wrapper,
+.right-side,
+.main-footer {
+  -webkit-transition: -webkit-transform 0.3s ease-in-out, margin 0.3s ease-in-out;
+  -moz-transition: -moz-transform 0.3s ease-in-out, margin 0.3s ease-in-out;
+  -o-transition: -o-transform 0.3s ease-in-out, margin 0.3s ease-in-out;
+  transition: transform 0.3s ease-in-out, margin 0.3s ease-in-out;
+  margin-left: 230px;
+  z-index: 820;
+}
+.layout-top-nav .content-wrapper,
+.layout-top-nav .right-side,
+.layout-top-nav .main-footer {
+  margin-left: 0;
 }
-@media screen and (min-width: 992px) {
-  .left-side {
-    top: 50px;
-  }
-  /*Right side strech mode*/
-  .right-side.strech {
+@media (max-width: 767px) {
+  .content-wrapper,
+  .right-side,
+  .main-footer {
     margin-left: 0;
   }
-  .right-side.strech > .content-header {
-    margin-top: 0px;
-  }
-  /* Left side collapse */
-  .left-side.collapse-left {
-    left: -220px;
-  }
 }
-/*Give content full width on xs screens*/
-@media screen and (max-width: 992px) {
-  .right-side {
+@media (min-width: 768px) {
+  .sidebar-collapse .content-wrapper,
+  .sidebar-collapse .right-side,
+  .sidebar-collapse .main-footer {
     margin-left: 0;
   }
 }
-/*
-    By default the layout is not fixed but if you add the class .fixed to the body element
-    the sidebar and the navbar will automatically become poisitioned fixed
-*/
-body.fixed > .header,
-body.fixed .left-side,
-body.fixed .navbar {
+@media (max-width: 767px) {
+  .sidebar-open .content-wrapper,
+  .sidebar-open .right-side,
+  .sidebar-open .main-footer {
+    -webkit-transform: translate(230px, 0);
+    -ms-transform: translate(230px, 0);
+    -o-transform: translate(230px, 0);
+    transform: translate(230px, 0);
+  }
+}
+.content-wrapper,
+.right-side {
+  min-height: 100%;
+  background-color: #ecf0f5;
+  z-index: 800;
+}
+.main-footer {
+  background: #fff;
+  padding: 15px;
+  color: #444;
+  border-top: 1px solid #d2d6de;
+}
+/* Fixed layout */
+.fixed .main-header,
+.fixed .main-sidebar,
+.fixed .left-side {
   position: fixed;
 }
-body.fixed > .header {
+.fixed .main-header {
   top: 0;
   right: 0;
   left: 0;
 }
-body.fixed .navbar {
-  left: 0;
-  right: 0;
+.fixed .content-wrapper,
+.fixed .right-side {
+  padding-top: 50px;
+}
+@media (max-width: 767px) {
+  .fixed .content-wrapper,
+  .fixed .right-side {
+    padding-top: 100px;
+  }
 }
-body.fixed .wrapper {
-  margin-top: 50px;
+.fixed.layout-boxed .wrapper {
+  max-width: 100%;
 }
 /* Content */
 .content {
-  padding: 20px 15px;
-  background: #f9f9f9;
-  overflow: auto;
+  min-height: 250px;
+  padding: 15px;
+  margin-right: auto;
+  margin-left: auto;
+  padding-left: 15px;
+  padding-right: 15px;
 }
-/* Utility */
 /* H1 - H6 font */
 h1,
 h2,
@@ -126,607 +153,747 @@ h6,
 .h6 {
   font-family: 'Source Sans Pro', sans-serif;
 }
-/* All images should be responsive */
-img {
-  max-width: 100% !important;
-}
-.sort-highlight {
-  background: #f4f4f4;
-  border: 1px dashed #ddd;
-  margin-bottom: 10px;
-}
-/* 10px padding and margins */
-.pad {
-  padding: 10px;
-}
-.margin {
-  margin: 10px;
-}
-/* Display inline */
-.inline {
-  display: inline;
-  width: auto;
-}
-/* Background colors */
-.bg-red,
-.bg-yellow,
-.bg-aqua,
-.bg-blue,
-.bg-light-blue,
-.bg-green,
-.bg-navy,
-.bg-teal,
-.bg-olive,
-.bg-lime,
-.bg-orange,
-.bg-fuchsia,
-.bg-purple,
-.bg-maroon,
-.bg-black {
-  color: #f9f9f9 !important;
-}
-.bg-gray {
-  background-color: #eaeaec !important;
+/* General Links */
+a {
+  color: #3c8dbc;
 }
-.bg-black {
-  background-color: #222222 !important;
+a:hover,
+a:active,
+a:focus {
+  outline: none;
+  text-decoration: none;
+  color: #72afd2;
 }
-.bg-red {
-  background-color: #f56954 !important;
+/* Page Header */
+.page-header {
+  margin: 10px 0 20px 0;
+  font-size: 22px;
 }
-.bg-yellow {
-  background-color: #f39c12 !important;
+.page-header > small {
+  color: #666;
+  display: block;
+  margin-top: 5px;
 }
-.bg-aqua {
-  background-color: #00c0ef !important;
+/*
+ * Component: Main Header
+ * ----------------------
+ */
+.main-header {
+  position: relative;
+  max-height: 100px;
+  z-index: 1030;
 }
-.bg-blue {
-  background-color: #0073b7 !important;
+.main-header > .navbar {
+  -webkit-transition: margin-left 0.3s ease-in-out;
+  -o-transition: margin-left 0.3s ease-in-out;
+  transition: margin-left 0.3s ease-in-out;
+  margin-bottom: 0;
+  margin-left: 230px;
+  border: none;
+  min-height: 50px;
+  border-radius: 0;
 }
-.bg-light-blue {
-  background-color: #3c8dbc !important;
+.layout-top-nav .main-header > .navbar {
+  margin-left: 0!important;
 }
-.bg-green {
-  background-color: #00a65a !important;
+.main-header #navbar-search-input {
+  background: rgba(255, 255, 255, 0.2);
+  border-color: transparent;
 }
-.bg-navy {
-  background-color: #001f3f !important;
+.main-header #navbar-search-input:focus,
+.main-header #navbar-search-input:active {
+  border-color: rgba(0, 0, 0, 0.1) !important;
+  background: rgba(255, 255, 255, 0.9);
 }
-.bg-teal {
-  background-color: #39cccc !important;
+.main-header #navbar-search-input::-moz-placeholder {
+  color: #ccc;
+  opacity: 1;
 }
-.bg-olive {
-  background-color: #3d9970 !important;
+.main-header #navbar-search-input:-ms-input-placeholder {
+  color: #ccc;
 }
-.bg-lime {
-  background-color: #01ff70 !important;
+.main-header #navbar-search-input::-webkit-input-placeholder {
+  color: #ccc;
 }
-.bg-orange {
-  background-color: #ff851b !important;
+.main-header .navbar-custom-menu,
+.main-header .navbar-right {
+  float: right;
 }
-.bg-fuchsia {
-  background-color: #f012be !important;
+@media (max-width: 991px) {
+  .main-header .navbar-custom-menu a,
+  .main-header .navbar-right a {
+    color: inherit;
+    background: transparent;
+  }
 }
-.bg-purple {
-  background-color: #932ab6 !important;
+@media (max-width: 767px) {
+  .main-header .navbar-right {
+    float: none;
+  }
+  .navbar-collapse .main-header .navbar-right {
+    margin: 7.5px -15px;
+  }
+  .main-header .navbar-right > li {
+    color: inherit;
+    border: 0;
+  }
 }
-.bg-maroon {
-  background-color: #85144b !important;
+.main-header .sidebar-toggle {
+  float: left;
+  background-color: transparent;
+  background-image: none;
+  padding: 15px 15px;
+  font-family: fontAwesome;
 }
-/* Text colors */
-.text-red {
-  color: #f56954 !important;
+.main-header .sidebar-toggle:before {
+  content: "\f0c9";
 }
-.text-yellow {
-  color: #f39c12 !important;
+.main-header .sidebar-toggle:hover {
+  color: #fff;
 }
-.text-aqua {
-  color: #00c0ef !important;
+.main-header .sidebar-toggle:focus,
+.main-header .sidebar-toggle:active {
+  background: transparent;
 }
-.text-blue {
-  color: #0073b7 !important;
+.main-header .sidebar-toggle .icon-bar {
+  display: none;
 }
-.text-black {
-  color: #222222 !important;
+.main-header .navbar .nav > li.user > a > .fa,
+.main-header .navbar .nav > li.user > a > .glyphicon,
+.main-header .navbar .nav > li.user > a > .ion {
+  margin-right: 5px;
 }
-.text-light-blue {
-  color: #3c8dbc !important;
+.main-header .navbar .nav > li > a > .label {
+  position: absolute;
+  top: 9px;
+  right: 7px;
+  text-align: center;
+  font-size: 9px;
+  padding: 2px 3px;
+  line-height: .9;
 }
-.text-green {
-  color: #00a65a !important;
+.main-header .logo {
+  -webkit-transition: width 0.3s ease-in-out;
+  -o-transition: width 0.3s ease-in-out;
+  transition: width 0.3s ease-in-out;
+  display: block;
+  float: left;
+  height: 50px;
+  font-size: 20px;
+  line-height: 50px;
+  text-align: center;
+  width: 230px;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  padding: 0 15px;
+  font-weight: 300;
+  overflow: hidden;
 }
-.text-navy {
-  color: #001f3f !important;
+.main-header .logo .logo-lg {
+  display: block;
 }
-.text-teal {
-  color: #39cccc !important;
+.main-header .logo .logo-mini {
+  display: none;
 }
-.text-olive {
-  color: #3d9970 !important;
+.main-header .navbar-brand {
+  color: #fff;
 }
-.text-lime {
-  color: #01ff70 !important;
+.content-header {
+  position: relative;
+  padding: 15px 15px 0 15px;
 }
-.text-orange {
-  color: #ff851b !important;
+.content-header > h1 {
+  margin: 0;
+  font-size: 24px;
 }
-.text-fuchsia {
-  color: #f012be !important;
+.content-header > h1 > small {
+  font-size: 15px;
+  display: inline-block;
+  padding-left: 4px;
+  font-weight: 300;
 }
-.text-purple {
-  color: #932ab6 !important;
+.content-header > .breadcrumb {
+  float: right;
+  background: transparent;
+  margin-top: 0px;
+  margin-bottom: 0;
+  font-size: 12px;
+  padding: 7px 5px;
+  position: absolute;
+  top: 15px;
+  right: 10px;
+  border-radius: 2px;
 }
-.text-maroon {
-  color: #85144b !important;
+.content-header > .breadcrumb > li > a {
+  color: #444;
+  text-decoration: none;
+  display: inline-block;
 }
-/*Hide elements by display none only*/
-.hide {
-  display: none !important;
+.content-header > .breadcrumb > li > a > .fa,
+.content-header > .breadcrumb > li > a > .glyphicon,
+.content-header > .breadcrumb > li > a > .ion {
+  margin-right: 5px;
 }
-/* Remove borders */
-.no-border {
-  border: 0px !important;
+.content-header > .breadcrumb > li + li:before {
+  content: '>\00a0';
 }
-/* Remove padding */
-.no-padding {
-  padding: 0px !important;
+@media (max-width: 991px) {
+  .content-header > .breadcrumb {
+    position: relative;
+    margin-top: 5px;
+    top: 0;
+    right: 0;
+    float: none;
+    background: #d2d6de;
+    padding-left: 10px;
+  }
+  .content-header > .breadcrumb li:before {
+    color: #97a0b3;
+  }
 }
-/* Remove margins */
-.no-margin {
-  margin: 0px !important;
+.navbar-toggle {
+  color: #fff;
+  border: 0;
+  margin: 0;
+  padding: 15px 15px;
 }
-/* Remove box shadow */
-.no-shadow {
-  box-shadow: none!important;
+@media (max-width: 991px) {
+  .navbar-custom-menu .navbar-nav > li {
+    float: left;
+  }
+  .navbar-custom-menu .navbar-nav {
+    margin: 0;
+    float: left;
+  }
+  .navbar-custom-menu .navbar-nav > li > a {
+    padding-top: 15px;
+    padding-bottom: 15px;
+    line-height: 20px;
+  }
 }
-/* Don't display when printing */
-@media print {
-  .no-print {
-    display: none;
+@media (max-width: 767px) {
+  .main-header {
+    position: relative;
   }
-  .left-side,
-  .header,
-  .content-header {
-    display: none;
+  .main-header .logo,
+  .main-header .navbar {
+    width: 100%;
+    float: none;
+    position: relative!important;
   }
-  .right-side {
+  .main-header .navbar {
     margin: 0;
   }
+  .main-header .navbar-custom-menu {
+    float: right;
+  }
+  .main-sidebar,
+  .left-side {
+    padding-top: 100px!important;
+  }
 }
-/* Remove border radius */
-.flat {
-  -webkit-border-radius: 0 !important;
-  -moz-border-radius: 0 !important;
-  border-radius: 0 !important;
-}
-/* Change the color of the striped tables */
-.table-striped > tbody > tr:nth-child(odd) > td,
-.table-striped > tbody > tr:nth-child(odd) > th {
-  background-color: #f3f4f5;
-}
-.table.no-border,
-.table.no-border td,
-.table.no-border th {
-  border: 0;
-}
-/* .text-center in tables */
-table.text-center,
-table.text-center td,
-table.text-center th {
-  text-align: center;
-}
-.table.align th {
-  text-align: left;
+@media (max-width: 991px) {
+  .navbar-collapse.pull-left {
+    float: none!important;
+  }
+  .navbar-collapse.pull-left + .navbar-custom-menu {
+    display: block;
+    position: absolute;
+    top: 0;
+    right: 40px;
+  }
 }
-.table.align td {
-  text-align: right;
+/*
+ * Component: Sidebar
+ * ------------------
+ */
+.main-sidebar,
+.left-side {
+  position: absolute;
+  top: 0;
+  left: 0;
+  padding-top: 50px;
+  min-height: 100%;
+  width: 230px;
+  z-index: 810;
+  -webkit-transition: -webkit-transform 0.3s ease-in-out, width 0.3s ease-in-out;
+  -moz-transition: -moz-transform 0.3s ease-in-out, width 0.3s ease-in-out;
+  -o-transition: -o-transform 0.3s ease-in-out, width 0.3s ease-in-out;
+  transition: transform 0.3s ease-in-out, width 0.3s ease-in-out;
 }
-.text-bold,
-.text-bold.table td,
-.text-bold.table th {
-  font-weight: 700;
+@media (max-width: 767px) {
+  .main-sidebar,
+  .left-side {
+    -webkit-transform: translate(-230px, 0);
+    -ms-transform: translate(-230px, 0);
+    -o-transform: translate(-230px, 0);
+    transform: translate(-230px, 0);
+  }
 }
-.border-radius-none {
-  -webkit-border-radius: 0 !important;
-  -moz-border-radius: 0 !important;
-  border-radius: 0 !important;
+@media (min-width: 768px) {
+  .sidebar-collapse .main-sidebar,
+  .sidebar-collapse .left-side {
+    -webkit-transform: translate(-230px, 0);
+    -ms-transform: translate(-230px, 0);
+    -o-transform: translate(-230px, 0);
+    transform: translate(-230px, 0);
+  }
 }
-/* _fix for sparkline tooltip */
-.jqstooltip {
-  padding: 5px!important;
-  width: auto!important;
-  height: auto!important;
+@media (max-width: 767px) {
+  .sidebar-open .main-sidebar,
+  .sidebar-open .left-side {
+    -webkit-transform: translate(0, 0);
+    -ms-transform: translate(0, 0);
+    -o-transform: translate(0, 0);
+    transform: translate(0, 0);
+  }
 }
-/*
-Gradient Background colors
-*/
-.bg-teal-gradient {
-  background: #39cccc !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #39cccc), color-stop(1, #7adddd)) !important;
-  background: -ms-linear-gradient(bottom, #39cccc, #7adddd) !important;
-  background: -moz-linear-gradient(center bottom, #39cccc 0%, #7adddd 100%) !important;
-  background: -o-linear-gradient(#7adddd, #39cccc) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#7adddd', endColorstr='#39cccc', GradientType=0) !important;
-  color: #fff;
+.sidebar {
+  padding-bottom: 10px;
 }
-.bg-light-blue-gradient {
-  background: #3c8dbc !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #3c8dbc), color-stop(1, #67a8ce)) !important;
-  background: -ms-linear-gradient(bottom, #3c8dbc, #67a8ce) !important;
-  background: -moz-linear-gradient(center bottom, #3c8dbc 0%, #67a8ce 100%) !important;
-  background: -o-linear-gradient(#67a8ce, #3c8dbc) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#67a8ce', endColorstr='#3c8dbc', GradientType=0) !important;
-  color: #fff;
+.sidebar-form input:focus {
+  border-color: transparent!important;
 }
-.bg-blue-gradient {
-  background: #0073b7 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #0073b7), color-stop(1, #0089db)) !important;
-  background: -ms-linear-gradient(bottom, #0073b7, #0089db) !important;
-  background: -moz-linear-gradient(center bottom, #0073b7 0%, #0089db 100%) !important;
-  background: -o-linear-gradient(#0089db, #0073b7) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0089db', endColorstr='#0073b7', GradientType=0) !important;
-  color: #fff;
+.user-panel {
+  position: relative;
+  width: 100%;
+  padding: 10px;
+  overflow: hidden;
 }
-.bg-aqua-gradient {
-  background: #00c0ef !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #00c0ef), color-stop(1, #14d1ff)) !important;
-  background: -ms-linear-gradient(bottom, #00c0ef, #14d1ff) !important;
-  background: -moz-linear-gradient(center bottom, #00c0ef 0%, #14d1ff 100%) !important;
-  background: -o-linear-gradient(#14d1ff, #00c0ef) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#14d1ff', endColorstr='#00c0ef', GradientType=0) !important;
-  color: #fff;
+.user-panel:before,
+.user-panel:after {
+  content: " ";
+  display: table;
 }
-.bg-yellow-gradient {
-  background: #f39c12 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #f39c12), color-stop(1, #f7bc60)) !important;
-  background: -ms-linear-gradient(bottom, #f39c12, #f7bc60) !important;
-  background: -moz-linear-gradient(center bottom, #f39c12 0%, #f7bc60 100%) !important;
-  background: -o-linear-gradient(#f7bc60, #f39c12) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7bc60', endColorstr='#f39c12', GradientType=0) !important;
-  color: #fff;
+.user-panel:after {
+  clear: both;
 }
-.bg-purple-gradient {
-  background: #932ab6 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #932ab6), color-stop(1, #b959d9)) !important;
-  background: -ms-linear-gradient(bottom, #932ab6, #b959d9) !important;
-  background: -moz-linear-gradient(center bottom, #932ab6 0%, #b959d9 100%) !important;
-  background: -o-linear-gradient(#b959d9, #932ab6) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b959d9', endColorstr='#932ab6', GradientType=0) !important;
-  color: #fff;
+.user-panel > .image > img {
+  width: 100%;
+  max-width: 45px;
+  height: auto;
 }
-.bg-green-gradient {
-  background: #00a65a !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #00a65a), color-stop(1, #00ca6d)) !important;
-  background: -ms-linear-gradient(bottom, #00a65a, #00ca6d) !important;
-  background: -moz-linear-gradient(center bottom, #00a65a 0%, #00ca6d 100%) !important;
-  background: -o-linear-gradient(#00ca6d, #00a65a) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ca6d', endColorstr='#00a65a', GradientType=0) !important;
-  color: #fff;
+.user-panel > .info {
+  padding: 5px 5px 5px 15px;
+  line-height: 1;
+  position: absolute;
+  left: 55px;
 }
-.bg-red-gradient {
-  background: #f56954 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #f56954), color-stop(1, #f89384)) !important;
-  background: -ms-linear-gradient(bottom, #f56954, #f89384) !important;
-  background: -moz-linear-gradient(center bottom, #f56954 0%, #f89384 100%) !important;
-  background: -o-linear-gradient(#f89384, #f56954) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f89384', endColorstr='#f56954', GradientType=0) !important;
-  color: #fff;
+.user-panel > .info > p {
+  font-weight: 600;
+  margin-bottom: 9px;
 }
-.bg-black-gradient {
-  background: #222222 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #222222), color-stop(1, #3c3c3c)) !important;
-  background: -ms-linear-gradient(bottom, #222222, #3c3c3c) !important;
-  background: -moz-linear-gradient(center bottom, #222222 0%, #3c3c3c 100%) !important;
-  background: -o-linear-gradient(#3c3c3c, #222222) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3c3c3c', endColorstr='#222222', GradientType=0) !important;
-  color: #fff;
+.user-panel > .info > a {
+  text-decoration: none;
+  padding-right: 5px;
+  margin-top: 3px;
+  font-size: 11px;
 }
-.bg-maroon-gradient {
-  background: #85144b !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #85144b), color-stop(1, #b11b64)) !important;
-  background: -ms-linear-gradient(bottom, #85144b, #b11b64) !important;
-  background: -moz-linear-gradient(center bottom, #85144b 0%, #b11b64 100%) !important;
-  background: -o-linear-gradient(#b11b64, #85144b) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b11b64', endColorstr='#85144b', GradientType=0) !important;
-  color: #fff;
+.user-panel > .info > a > .fa,
+.user-panel > .info > a > .ion,
+.user-panel > .info > a > .glyphicon {
+  margin-right: 3px;
 }
-.connectedSortable {
-  min-height: 100px;
+.sidebar-menu {
+  list-style: none;
+  margin: 0;
+  padding: 0;
 }
-/*---------------------------------------------------
-    LESS Elements 0.9
-  ---------------------------------------------------
-    A set of useful LESS mixins
-    More info at: http://lesselements.com
-  ---------------------------------------------------*/
-/*
-    Components: navbar, logo and content header
--------------------------------------------------
-*/
-body > .header {
+.sidebar-menu > li {
   position: relative;
-  max-height: 100px;
-  z-index: 1030;
-}
-body > .header .navbar {
-  height: 50px;
-  margin-bottom: 0;
-  margin-left: 220px;
-}
-body > .header .navbar .sidebar-toggle {
-  float: left;
-  padding: 9px 5px;
-  margin-top: 8px;
-  margin-right: 0;
-  margin-bottom: 8px;
-  margin-left: 5px;
-  background-color: transparent;
-  background-image: none;
-  border: 1px solid transparent;
-  -webkit-border-radius: 0 !important;
-  -moz-border-radius: 0 !important;
-  border-radius: 0 !important;
-}
-body > .header .navbar .sidebar-toggle:hover .icon-bar {
-  background: #f6f6f6;
+  margin: 0;
+  padding: 0;
 }
-body > .header .navbar .sidebar-toggle .icon-bar {
+.sidebar-menu > li > a {
+  padding: 12px 5px 12px 15px;
   display: block;
-  width: 22px;
-  height: 2px;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-}
-body > .header .navbar .sidebar-toggle .icon-bar + .icon-bar {
-  margin-top: 4px;
 }
-body > .header .navbar .nav > li.user > a {
-  font-weight: bold;
+.sidebar-menu > li > a > .fa,
+.sidebar-menu > li > a > .glyphicon,
+.sidebar-menu > li > a > .ion {
+  width: 20px;
 }
-body > .header .navbar .nav > li.user > a > .fa,
-body > .header .navbar .nav > li.user > a > .glyphicon,
-body > .header .navbar .nav > li.user > a > .ion {
+.sidebar-menu > li .label,
+.sidebar-menu > li .badge {
+  margin-top: 3px;
   margin-right: 5px;
 }
-body > .header .navbar .nav > li > a > .label {
-  -webkit-border-radius: 50%;
-  -moz-border-radius: 50%;
-  border-radius: 50%;
-  position: absolute;
-  top: 7px;
-  right: 2px;
-  font-size: 10px;
-  font-weight: normal;
-  width: 15px;
-  height: 15px;
-  line-height: 1.0em;
-  text-align: center;
-  padding: 2px;
-}
-body > .header .navbar .nav > li > a:hover > .label {
-  top: 3px;
-}
-body > .header .logo {
-  float: left;
-  font-size: 20px;
-  line-height: 50px;
-  text-align: center;
-  padding: 0 10px;
-  width: 220px;
-  font-family: 'Kaushan Script', cursive;
-  font-weight: 500;
-  height: 50px;
-  display: block;
+.sidebar-menu li.header {
+  padding: 10px 25px 10px 15px;
+  font-size: 12px;
 }
-body > .header .logo .icon {
+.sidebar-menu li > a > .fa-angle-left {
+  width: auto;
+  height: auto;
+  padding: 0;
   margin-right: 10px;
+  margin-top: 3px;
 }
-.right-side > .content-header {
-  position: relative;
-  padding: 15px 15px 10px 20px;
+.sidebar-menu li.active > a > .fa-angle-left {
+  -webkit-transform: rotate(-90deg);
+  -ms-transform: rotate(-90deg);
+  -o-transform: rotate(-90deg);
+  transform: rotate(-90deg);
+}
+.sidebar-menu li.active > .treeview-menu {
+  display: block;
 }
-.right-side > .content-header > h1 {
+.sidebar-menu .treeview-menu {
+  display: none;
+  list-style: none;
+  padding: 0;
   margin: 0;
-  font-size: 24px;
+  padding-left: 5px;
 }
-.right-side > .content-header > h1 > small {
-  font-size: 15px;
-  display: inline-block;
-  padding-left: 4px;
-  font-weight: 300;
+.sidebar-menu .treeview-menu .treeview-menu {
+  padding-left: 20px;
 }
-.right-side > .content-header > .breadcrumb {
-  float: right;
-  background: transparent;
-  margin-top: 0px;
-  margin-bottom: 0;
-  font-size: 12px;
-  padding: 7px 5px;
-  position: absolute;
-  top: 15px;
-  right: 10px;
-  -webkit-border-radius: 2px;
-  -moz-border-radius: 2px;
-  border-radius: 2px;
+.sidebar-menu .treeview-menu > li {
+  margin: 0;
 }
-.right-side > .content-header > .breadcrumb > li > a {
-  color: #444;
-  text-decoration: none;
+.sidebar-menu .treeview-menu > li > a {
+  padding: 5px 5px 5px 15px;
+  display: block;
+  font-size: 14px;
 }
-.right-side > .content-header > .breadcrumb > li > a > .fa,
-.right-side > .content-header > .breadcrumb > li > a > .glyphicon,
-.right-side > .content-header > .breadcrumb > li > a > .ion {
-  margin-right: 5px;
+.sidebar-menu .treeview-menu > li > a > .fa,
+.sidebar-menu .treeview-menu > li > a > .glyphicon,
+.sidebar-menu .treeview-menu > li > a > .ion {
+  width: 20px;
 }
-.right-side > .content-header > .breadcrumb > li + li:before {
-  content: '>\00a0';
+.sidebar-menu .treeview-menu > li > a > .fa-angle-left,
+.sidebar-menu .treeview-menu > li > a > .fa-angle-down {
+  width: auto;
 }
-@media screen and (max-width: 767px) {
-  .right-side > .content-header > .breadcrumb {
+/*
+ * Component: Sidebar Mini
+ */
+@media (min-width: 768px) {
+  .sidebar-mini.sidebar-collapse .content-wrapper,
+  .sidebar-mini.sidebar-collapse .right-side,
+  .sidebar-mini.sidebar-collapse .main-footer {
+    margin-left: 50px!important;
+    z-index: 840;
+  }
+  .sidebar-mini.sidebar-collapse .main-sidebar {
+    -webkit-transform: translate(0, 0);
+    -ms-transform: translate(0, 0);
+    -o-transform: translate(0, 0);
+    transform: translate(0, 0);
+    width: 50px!important;
+    z-index: 850;
+  }
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li {
     position: relative;
-    margin-top: 5px;
+  }
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li > a {
+    margin-right: 0;
+  }
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li > a > span {
+    border-top-right-radius: 4px;
+  }
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li:not(.treeview) > a > span {
+    border-bottom-right-radius: 4px;
+  }
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li > .treeview-menu {
+    padding-top: 5px;
+    padding-bottom: 5px;
+    border-bottom-right-radius: 4px;
+  }
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li:hover > a > span:not(.pull-right),
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li:hover > .treeview-menu {
+    display: block!important;
+    position: absolute;
+    width: 180px;
+    left: 50px;
+  }
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li:hover > a > span {
     top: 0;
-    right: 0;
-    float: none;
-    background: #efefef;
+    margin-left: -3px;
+    padding: 12px 5px 12px 20px;
+    background-color: inherit;
   }
-}
-
-@media screen and (max-width: 560px) {
-  body > .header {
-    position: relative;
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li:hover > .treeview-menu {
+    top: 44px;
+    margin-left: 0;
   }
-  body > .header .logo,
-  body > .header .navbar {
-    width: 100%;
-    float: none;
-    position: relative!important;
+  .sidebar-mini.sidebar-collapse .main-sidebar .user-panel > .info,
+  .sidebar-mini.sidebar-collapse .sidebar-form,
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li > a > span,
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li > .treeview-menu,
+  .sidebar-mini.sidebar-collapse .sidebar-menu > li > a > .pull-right,
+  .sidebar-mini.sidebar-collapse .sidebar-menu li.header {
+    display: none!important;
   }
-  body > .header .navbar {
-    margin: 0;
+  .sidebar-mini.sidebar-collapse .main-header .logo {
+    width: 50px;
   }
-  body.fixed > .header {
-    position: fixed;
+  .sidebar-mini.sidebar-collapse .main-header .logo > .logo-mini {
+    display: block;
+    margin-left: -15px;
+    margin-right: -15px;
+    font-size: 18px;
   }
-  body.fixed > .wrapper,
-  body.fixed .sidebar-offcanvas {
-    margin-top: 100px!important;
+  .sidebar-mini.sidebar-collapse .main-header .logo > .logo-lg {
+    display: none;
+  }
+  .sidebar-mini.sidebar-collapse .main-header .navbar {
+    margin-left: 50px;
   }
 }
-/*
-    Component: Sidebar
---------------------------
-*/
-.sidebar {
-  margin-bottom: 5px;
-}
-.sidebar .sidebar-form input:focus {
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  border-color: transparent!important;
+.sidebar-menu,
+.main-sidebar .user-panel,
+.sidebar-menu > li.header {
+  white-space: nowrap!important;
+  overflow: hidden;
 }
-.sidebar .sidebar-menu {
-  list-style: none;
-  margin: 0;
-  padding: 0;
+.sidebar-menu:hover {
+  overflow: visible;
 }
-.sidebar .sidebar-menu > li {
-  margin: 0;
-  padding: 0;
+.sidebar-form,
+.sidebar-menu > li.header {
+  overflow: hidden;
+  text-overflow: clip;
 }
-.sidebar .sidebar-menu > li > a {
-  padding: 12px 5px 12px 15px;
-  display: block;
+.sidebar-menu li > a {
+  position: relative;
 }
-.sidebar .sidebar-menu > li > a > .fa,
-.sidebar .sidebar-menu > li > a > .glyphicon,
-.sidebar .sidebar-menu > li > a > .ion {
-  width: 20px;
+.sidebar-menu li > a > .pull-right {
+  position: absolute;
+  top: 50%;
+  right: 10px;
+  margin-top: -7px;
 }
-.sidebar .sidebar-menu .treeview-menu {
-  display: none;
-  list-style: none;
-  padding: 0;
-  margin: 0;
+/*
+ * Component: Control sidebar. By default, this is the right sidebar.
+ */
+.control-sidebar-bg {
+  position: fixed;
+  z-index: 1000;
+  bottom: 0;
 }
-.sidebar .sidebar-menu .treeview-menu > li {
-  margin: 0;
+.control-sidebar-bg,
+.control-sidebar {
+  top: 0;
+  right: -230px;
+  width: 230px;
+  -webkit-transition: right 0.3s ease-in-out;
+  -o-transition: right 0.3s ease-in-out;
+  transition: right 0.3s ease-in-out;
 }
-.sidebar .sidebar-menu .treeview-menu > li > a {
-  padding: 5px 5px 5px 15px;
+.control-sidebar {
+  position: absolute;
+  padding-top: 50px;
+  z-index: 1010;
+}
+@media (max-width: 768px) {
+  .control-sidebar {
+    padding-top: 100px;
+  }
+}
+.control-sidebar > .tab-content {
+  padding: 10px 15px;
+}
+.control-sidebar.control-sidebar-open,
+.control-sidebar.control-sidebar-open + .control-sidebar-bg {
+  right: 0;
+}
+.control-sidebar-open .control-sidebar-bg,
+.control-sidebar-open .control-sidebar {
+  right: 0;
+}
+@media (min-width: 768px) {
+  .control-sidebar-open .content-wrapper,
+  .control-sidebar-open .right-side,
+  .control-sidebar-open .main-footer {
+    margin-right: 230px;
+  }
+}
+.control-sidebar-tabs > li:first-of-type > a {
+  margin-left: 1px;
+}
+.control-sidebar-tabs > li:first-of-type > a,
+.control-sidebar-tabs > li:first-of-type > a:hover {
+  border-left-width: 0!important;
+}
+.control-sidebar-tabs > li > a {
+  border-radius: 0 !important;
+}
+.control-sidebar-tabs > li > a,
+.control-sidebar-tabs > li > a:hover {
+  border-top: none;
+  border-right: none;
+  border-left: 1px solid transparent!important;
+  border-bottom: 1px solid transparent!important;
+}
+.control-sidebar-tabs > li > a .icon {
+  font-size: 16px;
+}
+.control-sidebar-tabs > li.active > a,
+.control-sidebar-tabs > li.active > a:hover,
+.control-sidebar-tabs > li.active > a:focus,
+.control-sidebar-tabs > li.active > a:active {
+  border-top: none!important;
+  border-right: none!important;
+  border-bottom: none!important;
+}
+@media (max-width: 768px) {
+  .control-sidebar-tabs {
+    display: table;
+  }
+  .control-sidebar-tabs > li {
+    display: table-cell !important;
+  }
+}
+.control-sidebar-heading {
+  font-weight: 400;
+  font-size: 16px;
+  padding: 10px 0;
+  margin-bottom: 10px;
+}
+.control-sidebar-subheading {
   display: block;
+  font-weight: 400;
   font-size: 14px;
-  margin: 0px 0px;
 }
-.sidebar .sidebar-menu .treeview-menu > li > a > .fa,
-.sidebar .sidebar-menu .treeview-menu > li > a > .glyphicon,
-.sidebar .sidebar-menu .treeview-menu > li > a > .ion {
-  width: 20px;
+.control-sidebar-menu {
+  list-style: none;
+  padding: 0;
+  margin: 0 -15px;
 }
-.user-panel {
-  padding: 10px;
+.control-sidebar-menu > li > a {
+  display: block;
+  padding: 10px 15px;
 }
-.user-panel:before,
-.user-panel:after {
-  display: table;
+.control-sidebar-menu > li > a:before,
+.control-sidebar-menu > li > a:after {
   content: " ";
+  display: table;
 }
-.user-panel:after {
+.control-sidebar-menu > li > a:after {
   clear: both;
 }
-.user-panel > .image > img {
-  width: 45px;
-  height: 45px;
-}
-.user-panel > .info {
-  font-weight: 600;
-  padding: 5px 5px 5px 15px;
-  font-size: 14px;
-  line-height: 1;
+.control-sidebar-menu > li > a > .control-sidebar-subheading {
+  margin-top: 0;
 }
-.user-panel > .info > p {
-  margin-bottom: 9px;
+.control-sidebar-menu .menu-icon {
+  float: left;
+  width: 35px;
+  height: 35px;
+  border-radius: 50%;
+  text-align: center;
+  line-height: 35px;
 }
-.user-panel > .info > a {
-  text-decoration: none;
-  padding-right: 5px;
+.control-sidebar-menu .menu-info {
+  margin-left: 45px;
   margin-top: 3px;
+}
+.control-sidebar-menu .menu-info > .control-sidebar-subheading {
+  margin: 0;
+}
+.control-sidebar-menu .menu-info > p {
+  margin: 0;
   font-size: 11px;
-  font-weight: normal;
 }
-.user-panel > .info > a > .fa,
-.user-panel > .info > a > .ion,
-.user-panel > .info > a > .glyphicon {
-  margin-right: 3px;
+.control-sidebar-menu .progress {
+  margin: 0;
 }
-/*
- * Off Canvas
- * --------------------------------------------------
- *  Gives us the push menu effect
- */
-@media screen and (max-width: 992px) {
-  .relative {
-    position: relative;
-  }
-  .row-offcanvas-right .sidebar-offcanvas {
-    right: -220px;
-  }
-  .row-offcanvas-left .sidebar-offcanvas {
-    left: -220px;
-  }
-  .row-offcanvas-right.active {
-    right: 220px;
-  }
-  .row-offcanvas-left.active {
-    left: 220px;
-  }
-  .sidebar-offcanvas {
-    left: 0;
-  }
-  body.fixed .sidebar-offcanvas {
-    margin-top: 50px;
-    left: -220px;
-  }
-  body.fixed .row-offcanvas-left.active .navbar {
-    left: 220px !important;
-    right: 0;
-  }
-  body.fixed .row-offcanvas-left.active .sidebar-offcanvas {
-    left: 0px;
-  }
+.control-sidebar-dark {
+  color: #b8c7ce;
+}
+.control-sidebar-dark,
+.control-sidebar-dark + .control-sidebar-bg {
+  background: #222d32;
+}
+.control-sidebar-dark .control-sidebar-tabs {
+  border-bottom: #1c2529;
+}
+.control-sidebar-dark .control-sidebar-tabs > li > a {
+  background: #181f23;
+  color: #b8c7ce;
+}
+.control-sidebar-dark .control-sidebar-tabs > li > a,
+.control-sidebar-dark .control-sidebar-tabs > li > a:hover {
+  border-left-color: #141a1d !important;
+  border-bottom-color: #141a1d !important;
+}
+.control-sidebar-dark .control-sidebar-tabs > li > a:hover,
+.control-sidebar-dark .control-sidebar-tabs > li > a:focus,
+.control-sidebar-dark .control-sidebar-tabs > li > a:active {
+  background: #1c2529;
+}
+.control-sidebar-dark .control-sidebar-tabs > li.active > a,
+.control-sidebar-dark .control-sidebar-tabs > li.active > a:hover,
+.control-sidebar-dark .control-sidebar-tabs > li.active > a:focus,
+.control-sidebar-dark .control-sidebar-tabs > li.active > a:active {
+  background: #222d32;
+  color: #fff;
+}
+.control-sidebar-dark .control-sidebar-heading,
+.control-sidebar-dark .control-sidebar-subheading {
+  color: #fff;
+}
+.control-sidebar-dark .control-sidebar-menu > li > a:hover {
+  background: #1e282c;
+}
+.control-sidebar-dark .control-sidebar-menu > li > a .menu-info > p {
+  color: #b8c7ce;
+}
+.control-sidebar-light {
+  color: #5e5e5e;
+}
+.control-sidebar-light,
+.control-sidebar-light + .control-sidebar-bg {
+  background: #f9fafc;
+  border-left: 1px solid #d2d6de;
+}
+.control-sidebar-light .control-sidebar-tabs {
+  border-bottom: #d2d6de;
+}
+.control-sidebar-light .control-sidebar-tabs > li > a {
+  background: #e8ecf4;
+  color: #444444;
+}
+.control-sidebar-light .control-sidebar-tabs > li > a,
+.control-sidebar-light .control-sidebar-tabs > li > a:hover {
+  border-left-color: #d2d6de !important;
+  border-bottom-color: #d2d6de !important;
+}
+.control-sidebar-light .control-sidebar-tabs > li > a:hover,
+.control-sidebar-light .control-sidebar-tabs > li > a:focus,
+.control-sidebar-light .control-sidebar-tabs > li > a:active {
+  background: #eff1f7;
+}
+.control-sidebar-light .control-sidebar-tabs > li.active > a,
+.control-sidebar-light .control-sidebar-tabs > li.active > a:hover,
+.control-sidebar-light .control-sidebar-tabs > li.active > a:focus,
+.control-sidebar-light .control-sidebar-tabs > li.active > a:active {
+  background: #f9fafc;
+  color: #111;
+}
+.control-sidebar-light .control-sidebar-heading,
+.control-sidebar-light .control-sidebar-subheading {
+  color: #111;
+}
+.control-sidebar-light .control-sidebar-menu {
+  margin-left: -14px;
+}
+.control-sidebar-light .control-sidebar-menu > li > a:hover {
+  background: #f4f4f5;
+}
+.control-sidebar-light .control-sidebar-menu > li > a .menu-info > p {
+  color: #5e5e5e;
 }
 /*
-    Dropdown menus
-----------------------------
-*/
+ * Component: Dropdown menus
+ * -------------------------
+ */
 /*Dropdowns in general*/
 .dropdown-menu {
-  -webkit-box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1);
-  -moz-box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1);
-  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1);
-  z-index: 2300;
+  box-shadow: none;
+  border-color: #eee;
+}
+.dropdown-menu > li > a {
+  color: #777;
 }
 .dropdown-menu > li > a > .glyphicon,
 .dropdown-menu > li > a > .fa,
@@ -734,17 +901,21 @@ body > .header .logo .icon {
   margin-right: 10px;
 }
 .dropdown-menu > li > a:hover {
-  background-color: #3c8dbc;
-  color: #f9f9f9;
+  background-color: #e1e3e9;
+  color: #333;
 }
-/*Drodown in navbars*/
-.skin-blue .navbar .dropdown-menu > li > a {
-  color: #444444;
+.dropdown-menu > .divider {
+  background-color: #eee;
+}
+.navbar-nav .dropdown-menu {
+  -webkit-box-shadow: none !important;
+  box-shadow: none !important;
+}
+.navbar-nav > .notifications-menu,
+.navbar-nav > .messages-menu,
+.navbar-nav > .tasks-menu {
+  position: relative;
 }
-/*
-    Navbar custom dropdown menu
-------------------------------------
-*/
 .navbar-nav > .notifications-menu > .dropdown-menu,
 .navbar-nav > .messages-menu > .dropdown-menu,
 .navbar-nav > .tasks-menu > .dropdown-menu {
@@ -752,22 +923,15 @@ body > .header .logo .icon {
   padding: 0 0 0 0!important;
   margin: 0!important;
   top: 100%;
-  border: 1px solid #dfdfdf;
-  -webkit-border-radius: 4px !important;
-  -moz-border-radius: 4px !important;
-  border-radius: 4px !important;
+}
+.navbar-nav > .notifications-menu > .dropdown-menu > li,
+.navbar-nav > .messages-menu > .dropdown-menu > li,
+.navbar-nav > .tasks-menu > .dropdown-menu > li {
+  position: relative;
 }
 .navbar-nav > .notifications-menu > .dropdown-menu > li.header,
 .navbar-nav > .messages-menu > .dropdown-menu > li.header,
 .navbar-nav > .tasks-menu > .dropdown-menu > li.header {
-  -webkit-border-top-left-radius: 4px;
-  -webkit-border-top-right-radius: 4px;
-  -webkit-border-bottom-right-radius: 0;
-  -webkit-border-bottom-left-radius: 0;
-  -moz-border-radius-topleft: 4px;
-  -moz-border-radius-topright: 4px;
-  -moz-border-radius-bottomright: 0;
-  -moz-border-radius-bottomleft: 0;
   border-top-left-radius: 4px;
   border-top-right-radius: 4px;
   border-bottom-right-radius: 0;
@@ -778,54 +942,38 @@ body > .header .logo .icon {
   color: #444444;
   font-size: 14px;
 }
-.navbar-nav > .notifications-menu > .dropdown-menu > li.header:after,
-.navbar-nav > .messages-menu > .dropdown-menu > li.header:after,
-.navbar-nav > .tasks-menu > .dropdown-menu > li.header:after {
-  bottom: 100%;
-  left: 92%;
-  border: solid transparent;
-  content: " ";
-  height: 0;
-  width: 0;
-  position: absolute;
-  pointer-events: none;
-  border-color: rgba(255, 255, 255, 0);
-  border-bottom-color: #ffffff;
-  border-width: 7px;
-  margin-left: -7px;
-}
 .navbar-nav > .notifications-menu > .dropdown-menu > li.footer > a,
 .navbar-nav > .messages-menu > .dropdown-menu > li.footer > a,
 .navbar-nav > .tasks-menu > .dropdown-menu > li.footer > a {
-  -webkit-border-top-left-radius: 0px;
-  -webkit-border-top-right-radius: 0px;
-  -webkit-border-bottom-right-radius: 4px;
-  -webkit-border-bottom-left-radius: 4px;
-  -moz-border-radius-topleft: 0px;
-  -moz-border-radius-topright: 0px;
-  -moz-border-radius-bottomright: 4px;
-  -moz-border-radius-bottomleft: 4px;
   border-top-left-radius: 0px;
   border-top-right-radius: 0px;
   border-bottom-right-radius: 4px;
   border-bottom-left-radius: 4px;
   font-size: 12px;
-  background-color: #f4f4f4;
+  background-color: #fff;
   padding: 7px 10px;
   border-bottom: 1px solid #eeeeee;
-  color: #444444;
+  color: #444!important;
   text-align: center;
 }
+@media (max-width: 991px) {
+  .navbar-nav > .notifications-menu > .dropdown-menu > li.footer > a,
+  .navbar-nav > .messages-menu > .dropdown-menu > li.footer > a,
+  .navbar-nav > .tasks-menu > .dropdown-menu > li.footer > a {
+    background: #fff!important;
+    color: #444!important;
+  }
+}
 .navbar-nav > .notifications-menu > .dropdown-menu > li.footer > a:hover,
 .navbar-nav > .messages-menu > .dropdown-menu > li.footer > a:hover,
 .navbar-nav > .tasks-menu > .dropdown-menu > li.footer > a:hover {
-  background: #f4f4f4;
   text-decoration: none;
   font-weight: normal;
 }
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu,
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu,
 .navbar-nav > .tasks-menu > .dropdown-menu > li .menu {
+  max-height: 200px;
   margin: 0;
   padding: 0;
   list-style: none;
@@ -842,71 +990,43 @@ body > .header .logo .icon {
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a:hover,
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a:hover,
 .navbar-nav > .tasks-menu > .dropdown-menu > li .menu > li > a:hover {
-  background: #f6f6f6;
+  background: #f4f4f4;
   text-decoration: none;
 }
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a {
-  font-size: 12px;
   color: #444444;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  padding: 10px;
 }
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon,
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa,
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion {
-  font-size: 20px;
-  width: 50px;
-  text-align: center;
-  padding: 15px 0px;
-  margin-right: 5px;
-  /* Default background and font colors */
-  background: #00c0ef;
-  color: #f9f9f9;
-  /* Fallback for browsers that doesn't support rgba */
-  color: rgba(255, 255, 255, 0.7);
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon.danger,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa.danger,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion.danger {
-  background: #f56954;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon.warning,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa.warning,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion.warning {
-  background: #f39c12;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon.success,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa.success,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion.success {
-  background: #00a65a;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon.info,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa.info,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion.info {
-  background: #00c0ef;
+  width: 20px;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a {
   margin: 0px;
-  line-height: 20px;
-  padding: 10px 5px 10px 5px;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
+  padding: 10px 10px;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a > div > img {
   margin: auto 10px auto auto;
   width: 40px;
   height: 40px;
-  border: 1px solid #dddddd;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a > h4 {
   padding: 0;
   margin: 0 0 0 45px;
   color: #444444;
   font-size: 15px;
+  position: relative;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a > h4 > small {
   color: #999999;
   font-size: 10px;
-  float: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a > p {
   margin: 0 0 0 45px;
@@ -915,8 +1035,8 @@ body > .header .logo .icon {
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a:before,
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a:after {
-  display: table;
   content: " ";
+  display: table;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a:after {
   clear: both;
@@ -935,180 +1055,196 @@ body > .header .logo .icon {
   margin: 0;
 }
 .navbar-nav > .user-menu > .dropdown-menu {
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  border-radius: 0;
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
   padding: 1px 0 0 0;
   border-top-width: 0;
   width: 280px;
 }
-.navbar-nav > .user-menu > .dropdown-menu:after {
-  bottom: 100%;
-  right: 10px;
-  border: solid transparent;
-  content: " ";
-  height: 0;
-  width: 0;
-  position: absolute;
-  pointer-events: none;
-  border-color: rgba(255, 255, 255, 0);
-  border-bottom-color: #ffffff;
-  border-width: 10px;
-  margin-left: -10px;
+.navbar-nav > .user-menu > .dropdown-menu,
+.navbar-nav > .user-menu > .dropdown-menu > .user-body {
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
 }
 .navbar-nav > .user-menu > .dropdown-menu > li.user-header {
   height: 175px;
   padding: 10px;
-  background: #3c8dbc;
   text-align: center;
 }
 .navbar-nav > .user-menu > .dropdown-menu > li.user-header > img {
   z-index: 5;
   height: 90px;
   width: 90px;
-  border: 8px solid;
+  border: 3px solid;
   border-color: transparent;
   border-color: rgba(255, 255, 255, 0.2);
 }
 .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p {
   z-index: 5;
-  color: #f9f9f9;
+  color: #fff;
   color: rgba(255, 255, 255, 0.8);
   font-size: 17px;
-  text-shadow: 2px 2px 3px #333333;
   margin-top: 10px;
 }
 .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p > small {
   display: block;
   font-size: 12px;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body {
+.navbar-nav > .user-menu > .dropdown-menu > .user-body {
   padding: 15px;
   border-bottom: 1px solid #f4f4f4;
   border-top: 1px solid #dddddd;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body:before,
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body:after {
-  display: table;
+.navbar-nav > .user-menu > .dropdown-menu > .user-body:before,
+.navbar-nav > .user-menu > .dropdown-menu > .user-body:after {
   content: " ";
+  display: table;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body:after {
+.navbar-nav > .user-menu > .dropdown-menu > .user-body:after {
   clear: both;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body > div > a {
-  color: #0073b7;
+.navbar-nav > .user-menu > .dropdown-menu > .user-body a {
+  color: #444 !important;
+}
+@media (max-width: 991px) {
+  .navbar-nav > .user-menu > .dropdown-menu > .user-body a {
+    background: #fff !important;
+    color: #444 !important;
+  }
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer {
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer {
   background-color: #f9f9f9;
   padding: 10px;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer:before,
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer:after {
-  display: table;
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer:before,
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer:after {
   content: " ";
+  display: table;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer:after {
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer:after {
   clear: both;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer .btn-default {
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default {
   color: #666666;
 }
-/* Add fade animation to dropdown menus */
-.open > .dropdown-menu {
-  animation-name: fadeAnimation;
-  animation-duration: .7s;
-  animation-iteration-count: 1;
-  animation-timing-function: ease;
-  animation-fill-mode: forwards;
-  -webkit-animation-name: fadeAnimation;
-  -webkit-animation-duration: .7s;
-  -webkit-animation-iteration-count: 1;
-  -webkit-animation-timing-function: ease;
-  -webkit-animation-fill-mode: forwards;
-  -moz-animation-name: fadeAnimation;
-  -moz-animation-duration: .7s;
-  -moz-animation-iteration-count: 1;
-  -moz-animation-timing-function: ease;
-  -moz-animation-fill-mode: forwards;
-}
-@keyframes fadeAnimation {
-  from {
+.navbar-nav > .user-menu .user-image {
+  float: left;
+  width: 25px;
+  height: 25px;
+  border-radius: 50%;
+  margin-right: 10px;
+  margin-top: -2px;
+}
+@media (max-width: 767px) {
+  .navbar-nav > .user-menu .user-image {
+    float: none;
+    margin-right: 0;
+    margin-top: -8px;
+    line-height: 10px;
+  }
+}
+/* Add fade animation to dropdown menus by appending
+ the class .animated-dropdown-menu to the .dropdown-menu ul (or ol)*/
+.open:not(.dropup) > .animated-dropdown-menu {
+  backface-visibility: visible !important;
+  -webkit-animation: flipInX 0.7s both;
+  -o-animation: flipInX 0.7s both;
+  animation: flipInX 0.7s both;
+}
+@keyframes flipInX {
+  0% {
+    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    transition-timing-function: ease-in;
     opacity: 0;
-    top: 120%;
   }
-  to {
+  40% {
+    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    transition-timing-function: ease-in;
+  }
+  60% {
+    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
     opacity: 1;
-    top: 100%;
+  }
+  80% {
+    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+  }
+  100% {
+    transform: perspective(400px);
   }
 }
-@-webkit-keyframes fadeAnimation {
-  from {
+@-webkit-keyframes flipInX {
+  0% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    -webkit-transition-timing-function: ease-in;
     opacity: 0;
-    top: 120%;
   }
-  to {
-    opacity: 1;
-    top: 100%;
+  40% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    -webkit-transition-timing-function: ease-in;
   }
-}
-/* Fix dropdown menu for small screens to display correctly on small screens */
-@media screen and (max-width: 767px) {
-  .navbar-nav > .notifications-menu > .dropdown-menu,
-  .navbar-nav > .user-menu > .dropdown-menu,
-  .navbar-nav > .tasks-menu > .dropdown-menu,
-  .navbar-nav > .messages-menu > .dropdown-menu {
-    position: absolute;
-    top: 100%;
-    right: 0;
-    left: auto;
-    border-right: 1px solid #dddddd;
-    border-bottom: 1px solid #dddddd;
-    border-left: 1px solid #dddddd;
-    background: #ffffff;
+  60% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+    opacity: 1;
   }
-}
-/* Fix menu positions on xs screens to appear correctly and fully */
-@media screen and (max-width: 480px) {
-  .navbar-nav > .notifications-menu > .dropdown-menu > li.header,
-  .navbar-nav > .tasks-menu > .dropdown-menu > li.header,
-  .navbar-nav > .messages-menu > .dropdown-menu > li.header {
-    /* Remove arrow from the top */
+  80% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
   }
-  .navbar-nav > .notifications-menu > .dropdown-menu > li.header:after,
-  .navbar-nav > .tasks-menu > .dropdown-menu > li.header:after,
-  .navbar-nav > .messages-menu > .dropdown-menu > li.header:after {
-    border-width: 0px!important;
+  100% {
+    -webkit-transform: perspective(400px);
   }
-  .navbar-nav > .tasks-menu > .dropdown-menu {
-    position: absolute;
-    right: -120px;
-    left: auto;
+}
+/* Fix dropdown menu in navbars */
+.navbar-custom-menu > .navbar-nav > li {
+  position: relative;
+}
+.navbar-custom-menu > .navbar-nav > li > .dropdown-menu {
+  position: absolute;
+  right: 0;
+  left: auto;
+}
+@media (max-width: 991px) {
+  .navbar-custom-menu > .navbar-nav {
+    float: right;
   }
-  .navbar-nav > .notifications-menu > .dropdown-menu {
-    position: absolute;
-    right: -170px;
-    left: auto;
+  .navbar-custom-menu > .navbar-nav > li {
+    position: static;
   }
-  .navbar-nav > .messages-menu > .dropdown-menu {
+  .navbar-custom-menu > .navbar-nav > li > .dropdown-menu {
     position: absolute;
-    right: -210px;
+    right: 5%;
     left: auto;
+    border: 1px solid #ddd;
+    background: #fff;
   }
 }
 /*
-   All form elements including input, select, textarea etc.
------------------------------------------------------------------
-*/
+ * Component: Form
+ * ---------------
+ */
 .form-control {
-  -webkit-border-radius: 0px !important;
-  -moz-border-radius: 0px !important;
   border-radius: 0px !important;
   box-shadow: none;
+  border-color: #d2d6de;
 }
 .form-control:focus {
   border-color: #3c8dbc !important;
   box-shadow: none;
 }
+.form-control::-moz-placeholder {
+  color: #bbb;
+  opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+  color: #bbb;
+}
+.form-control::-webkit-input-placeholder {
+  color: #bbb;
+}
+.form-control:not(select) {
+  -webkit-appearance: none;
+  -moz-appearance: none;
+  appearance: none;
+}
 .form-group.has-success label {
   color: #00a65a;
 }
@@ -1124,38 +1260,72 @@ body > .header .logo .icon {
   box-shadow: none;
 }
 .form-group.has-error label {
-  color: #f56954;
+  color: #dd4b39;
 }
 .form-group.has-error .form-control {
-  border-color: #f56954 !important;
+  border-color: #dd4b39 !important;
   box-shadow: none;
 }
 /* Input group */
 .input-group .input-group-addon {
-  border-radius: 0;
-  background-color: #f4f4f4;
+  border-radius: 0px;
+  border-color: #d2d6de;
+  background-color: #fff;
 }
 /* button groups */
 .btn-group-vertical .btn.btn-flat:first-of-type,
 .btn-group-vertical .btn.btn-flat:last-of-type {
   border-radius: 0;
 }
-/* Checkbox and radio inputs */
-.checkbox,
-.radio {
+.icheck > label {
   padding-left: 0;
 }
 /*
-    Compenent: Progress bars
---------------------------------
-*/
+ * Component: Progress Bar
+ * -----------------------
+ */
+.progress,
+.progress > .progress-bar {
+  -webkit-box-shadow: none;
+  box-shadow: none;
+}
+.progress,
+.progress > .progress-bar,
+.progress .progress-bar,
+.progress > .progress-bar .progress-bar {
+  border-radius: 1px;
+}
 /* size variation */
-.progress.sm {
+.progress.sm,
+.progress-sm {
   height: 10px;
 }
-.progress.xs {
+.progress.sm,
+.progress-sm,
+.progress.sm .progress-bar,
+.progress-sm .progress-bar {
+  border-radius: 1px;
+}
+.progress.xs,
+.progress-xs {
   height: 7px;
 }
+.progress.xs,
+.progress-xs,
+.progress.xs .progress-bar,
+.progress-xs .progress-bar {
+  border-radius: 1px;
+}
+.progress.xxs,
+.progress-xxs {
+  height: 3px;
+}
+.progress.xxs,
+.progress-xxs,
+.progress.xxs .progress-bar,
+.progress-xxs .progress-bar {
+  border-radius: 1px;
+}
 /* Vertical bars */
 .progress.vertical {
   position: relative;
@@ -1169,12 +1339,24 @@ body > .header .logo .icon {
   position: absolute;
   bottom: 0;
 }
-.progress.vertical.sm {
+.progress.vertical.sm,
+.progress.vertical.progress-sm {
   width: 20px;
 }
-.progress.vertical.xs {
+.progress.vertical.xs,
+.progress.vertical.progress-xs {
   width: 10px;
 }
+.progress.vertical.xxs,
+.progress.vertical.progress-xxs {
+  width: 3px;
+}
+.progress-group .progress-text {
+  font-weight: 600;
+}
+.progress-group .progress-number {
+  float: right;
+}
 /* Remove margins from progress bars when put in a table */
 .table tr > td .progress {
   margin: 0;
@@ -1185,9 +1367,8 @@ body > .header .logo .icon {
 }
 .progress-striped .progress-bar-light-blue,
 .progress-striped .progress-bar-primary {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 .progress-bar-green,
@@ -1196,9 +1377,8 @@ body > .header .logo .icon {
 }
 .progress-striped .progress-bar-green,
 .progress-striped .progress-bar-success {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 .progress-bar-aqua,
@@ -1207,9 +1387,8 @@ body > .header .logo .icon {
 }
 .progress-striped .progress-bar-aqua,
 .progress-striped .progress-bar-info {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 .progress-bar-yellow,
@@ -1218,32 +1397,30 @@ body > .header .logo .icon {
 }
 .progress-striped .progress-bar-yellow,
 .progress-striped .progress-bar-warning {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 .progress-bar-red,
 .progress-bar-danger {
-  background-color: #f56954;
+  background-color: #dd4b39;
 }
 .progress-striped .progress-bar-red,
 .progress-striped .progress-bar-danger {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 /*
-    Component: Small boxes
-*/
+ * Component: Small Box
+ * --------------------
+ */
 .small-box {
+  border-radius: 2px;
   position: relative;
   display: block;
-  -webkit-border-radius: 2px;
-  -moz-border-radius: 2px;
-  border-radius: 2px;
-  margin-bottom: 15px;
+  margin-bottom: 20px;
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
 }
 .small-box > .inner {
   padding: 10px;
@@ -1284,10 +1461,12 @@ body > .header .logo .icon {
   z-index: 5px;
 }
 .small-box .icon {
+  -webkit-transition: all 0.3s linear;
+  -o-transition: all 0.3s linear;
+  transition: all 0.3s linear;
   position: absolute;
-  top: auto;
-  bottom: 5px;
-  right: 5px;
+  top: -10px;
+  right: 10px;
   z-index: 0;
   font-size: 90px;
   color: rgba(0, 0, 0, 0.15);
@@ -1297,39 +1476,9 @@ body > .header .logo .icon {
   color: #f9f9f9;
 }
 .small-box:hover .icon {
-  animation-name: tansformAnimation;
-  animation-duration: .5s;
-  animation-iteration-count: 1;
-  animation-timing-function: ease;
-  animation-fill-mode: forwards;
-  -webkit-animation-name: tansformAnimation;
-  -webkit-animation-duration: .5s;
-  -webkit-animation-iteration-count: 1;
-  -webkit-animation-timing-function: ease;
-  -webkit-animation-fill-mode: forwards;
-  -moz-animation-name: tansformAnimation;
-  -moz-animation-duration: .5s;
-  -moz-animation-iteration-count: 1;
-  -moz-animation-timing-function: ease;
-  -moz-animation-fill-mode: forwards;
-}
-@keyframes tansformAnimation {
-  from {
-    font-size: 90px;
-  }
-  to {
-    font-size: 100px;
-  }
-}
-@-webkit-keyframes tansformAnimation {
-  from {
-    font-size: 90px;
-  }
-  to {
-    font-size: 100px;
-  }
-}
-@media screen and (max-width: 480px) {
+  font-size: 95px;
+}
+@media (max-width: 767px) {
   .small-box {
     text-align: center;
   }
@@ -1341,19 +1490,17 @@ body > .header .logo .icon {
   }
 }
 /*
-    component: Boxes
--------------------------
-*/
+ * Component: Box
+ * --------------
+ */
 .box {
   position: relative;
+  border-radius: 3px;
   background: #ffffff;
-  border-top: 2px solid #c1c1c1;
+  border-top: 3px solid #d2d6de;
   margin-bottom: 20px;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
   width: 100%;
-  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
 }
 .box.box-primary {
   border-top-color: #3c8dbc;
@@ -1362,7 +1509,7 @@ body > .header .logo .icon {
   border-top-color: #00c0ef;
 }
 .box.box-danger {
-  border-top-color: #f56954;
+  border-top-color: #dd4b39;
 }
 .box.box-warning {
   border-top-color: #f39c12;
@@ -1370,201 +1517,116 @@ body > .header .logo .icon {
 .box.box-success {
   border-top-color: #00a65a;
 }
-.box.height-control .box-body {
-  max-height: 300px;
-  overflow: auto;
-}
-.box .box-header {
-  position: relative;
-  -webkit-border-top-left-radius: 3px;
-  -webkit-border-top-right-radius: 3px;
-  -webkit-border-bottom-right-radius: 0;
-  -webkit-border-bottom-left-radius: 0;
-  -moz-border-radius-topleft: 3px;
-  -moz-border-radius-topright: 3px;
-  -moz-border-radius-bottomright: 0;
-  -moz-border-radius-bottomleft: 0;
-  border-top-left-radius: 3px;
-  border-top-right-radius: 3px;
-  border-bottom-right-radius: 0;
-  border-bottom-left-radius: 0;
-  border-bottom: 0px solid #f4f4f4;
-  color: #444;
-}
-.box .box-header:before,
-.box .box-header:after {
-  display: table;
-  content: " ";
+.box.box-default {
+  border-top-color: #d2d6de;
 }
-.box .box-header:after {
-  clear: both;
+.box.collapsed-box .box-body,
+.box.collapsed-box .box-footer {
+  display: none;
 }
-.box .box-header > .fa,
-.box .box-header > .glyphicon,
-.box .box-header > .ion,
-.box .box-header .box-title {
-  display: inline-block;
-  padding: 10px 10px 10px 10px;
+.box .nav-stacked > li {
+  border-bottom: 1px solid #f4f4f4;
   margin: 0;
-  font-size: 20px;
-  font-weight: 400;
-  float: left;
-  cursor: default;
-}
-.box .box-header a {
-  color: #444;
-}
-.box .box-header > .box-tools {
-  padding: 5px 10px 5px 5px;
-}
-.box .box-body {
-  padding: 10px;
-  -webkit-border-top-left-radius: 0;
-  -webkit-border-top-right-radius: 0;
-  -webkit-border-bottom-right-radius: 3px;
-  -webkit-border-bottom-left-radius: 3px;
-  -moz-border-radius-topleft: 0;
-  -moz-border-radius-topright: 0;
-  -moz-border-radius-bottomright: 3px;
-  -moz-border-radius-bottomleft: 3px;
-  border-top-left-radius: 0;
-  border-top-right-radius: 0;
-  border-bottom-right-radius: 3px;
-  border-bottom-left-radius: 3px;
-}
-.box .box-body > table,
-.box .box-body > .table {
-  margin-bottom: 0;
-}
-.box .box-body.chart-responsive {
-  width: 100%;
-  overflow: hidden;
-}
-.box .box-body > .chart {
-  position: relative;
-  overflow: hidden;
-  width: 100%;
-}
-.box .box-body > .chart svg,
-.box .box-body > .chart canvas {
-  width: 100%!important;
-}
-.box .box-body .fc {
-  margin-top: 5px;
-}
-.box .box-body .fc-header-title h2 {
-  font-size: 15px;
-  line-height: 1.6em;
-  color: #666;
-  margin-left: 10px;
-}
-.box .box-body .fc-header-right {
-  padding-right: 10px;
-}
-.box .box-body .fc-header-left {
-  padding-left: 10px;
 }
-.box .box-body .fc-widget-header {
-  background: #fafafa;
-  box-shadow: inset 0px -3px 1px rgba(0, 0, 0, 0.02);
+.box .nav-stacked > li:last-of-type {
+  border-bottom: none;
 }
-.box .box-body .fc-grid {
-  width: 100%;
-  border: 0;
+.box.height-control .box-body {
+  max-height: 300px;
+  overflow: auto;
 }
-.box .box-body .fc-widget-header:first-of-type,
-.box .box-body .fc-widget-content:first-of-type {
-  border-left: 0;
-  border-right: 0;
+.box .border-right {
+  border-right: 1px solid #f4f4f4;
 }
-.box .box-body .fc-widget-header:last-of-type,
-.box .box-body .fc-widget-content:last-of-type {
-  border-right: 0;
+.box .border-left {
+  border-left: 1px solid #f4f4f4;
 }
-.box .box-body .table {
-  margin-bottom: 0;
+.box.box-solid {
+  border-top: 0px;
 }
-.box .box-body .full-width-chart {
-  margin: -19px;
+.box.box-solid > .box-header .btn.btn-default {
+  background: transparent;
 }
-.box .box-body.no-padding .full-width-chart {
-  margin: -9px;
+.box.box-solid > .box-header .btn:hover,
+.box.box-solid > .box-header a:hover {
+  background: rgba(0, 0, 0, 0.1) !important;
 }
-.box .box-footer {
-  border-top: 1px solid #f4f4f4;
-  -webkit-border-top-left-radius: 0;
-  -webkit-border-top-right-radius: 0;
-  -webkit-border-bottom-right-radius: 3px;
-  -webkit-border-bottom-left-radius: 3px;
-  -moz-border-radius-topleft: 0;
-  -moz-border-radius-topright: 0;
-  -moz-border-radius-bottomright: 3px;
-  -moz-border-radius-bottomleft: 3px;
-  border-top-left-radius: 0;
-  border-top-right-radius: 0;
-  border-bottom-right-radius: 3px;
-  border-bottom-left-radius: 3px;
-  padding: 10px;
-  background-color: #ffffff;
+.box.box-solid.box-default {
+  border: 1px solid #d2d6de;
 }
-.box.box-solid {
-  border-top: 0px;
+.box.box-solid.box-default > .box-header {
+  color: #444444;
+  background: #d2d6de;
+  background-color: #d2d6de;
 }
-.box.box-solid > .box-header {
-  padding-bottom: 0px!important;
+.box.box-solid.box-default > .box-header a,
+.box.box-solid.box-default > .box-header .btn {
+  color: #444444;
 }
-.box.box-solid > .box-header .btn.btn-default {
-  background: transparent;
+.box.box-solid.box-primary {
+  border: 1px solid #3c8dbc;
 }
 .box.box-solid.box-primary > .box-header {
-  color: #fff;
+  color: #ffffff;
   background: #3c8dbc;
   background-color: #3c8dbc;
 }
-.box.box-solid.box-primary > .box-header a {
-  color: #444;
+.box.box-solid.box-primary > .box-header a,
+.box.box-solid.box-primary > .box-header .btn {
+  color: #ffffff;
+}
+.box.box-solid.box-info {
+  border: 1px solid #00c0ef;
 }
 .box.box-solid.box-info > .box-header {
-  color: #fff;
+  color: #ffffff;
   background: #00c0ef;
   background-color: #00c0ef;
 }
-.box.box-solid.box-info > .box-header a {
-  color: #444;
+.box.box-solid.box-info > .box-header a,
+.box.box-solid.box-info > .box-header .btn {
+  color: #ffffff;
+}
+.box.box-solid.box-danger {
+  border: 1px solid #dd4b39;
 }
 .box.box-solid.box-danger > .box-header {
-  color: #fff;
-  background: #f56954;
-  background-color: #f56954;
+  color: #ffffff;
+  background: #dd4b39;
+  background-color: #dd4b39;
 }
-.box.box-solid.box-danger > .box-header a {
-  color: #444;
+.box.box-solid.box-danger > .box-header a,
+.box.box-solid.box-danger > .box-header .btn {
+  color: #ffffff;
+}
+.box.box-solid.box-warning {
+  border: 1px solid #f39c12;
 }
 .box.box-solid.box-warning > .box-header {
-  color: #fff;
+  color: #ffffff;
   background: #f39c12;
   background-color: #f39c12;
 }
-.box.box-solid.box-warning > .box-header a {
-  color: #444;
+.box.box-solid.box-warning > .box-header a,
+.box.box-solid.box-warning > .box-header .btn {
+  color: #ffffff;
+}
+.box.box-solid.box-success {
+  border: 1px solid #00a65a;
 }
 .box.box-solid.box-success > .box-header {
-  color: #fff;
+  color: #ffffff;
   background: #00a65a;
   background-color: #00a65a;
 }
-.box.box-solid.box-success > .box-header a {
-  color: #444;
+.box.box-solid.box-success > .box-header a,
+.box.box-solid.box-success > .box-header .btn {
+  color: #ffffff;
 }
 .box.box-solid > .box-header > .box-tools .btn {
   border: 0;
   box-shadow: none;
 }
-.box.box-solid.collapsed-box .box-header {
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-}
 .box.box-solid[class*='bg'] > .box-header {
   color: #fff;
 }
@@ -1578,168 +1640,369 @@ body > .header .logo .icon {
   font-size: 12px;
   margin-bottom: 0.3em;
 }
-.box .todo-list {
+.box > .overlay,
+.overlay-wrapper > .overlay,
+.box > .loading-img,
+.overlay-wrapper > .loading-img {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+.box .overlay,
+.overlay-wrapper .overlay {
+  z-index: 50;
+  background: rgba(255, 255, 255, 0.7);
+  border-radius: 3px;
+}
+.box .overlay > .fa,
+.overlay-wrapper .overlay > .fa {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  margin-left: -15px;
+  margin-top: -15px;
+  color: #000;
+  font-size: 30px;
+}
+.box .overlay.dark,
+.overlay-wrapper .overlay.dark {
+  background: rgba(0, 0, 0, 0.5);
+}
+.box-header:before,
+.box-body:before,
+.box-footer:before,
+.box-header:after,
+.box-body:after,
+.box-footer:after {
+  content: " ";
+  display: table;
+}
+.box-header:after,
+.box-body:after,
+.box-footer:after {
+  clear: both;
+}
+.box-header {
+  color: #444;
+  display: block;
+  padding: 10px;
+  position: relative;
+}
+.box-header.with-border {
+  border-bottom: 1px solid #f4f4f4;
+}
+.collapsed-box .box-header.with-border {
+  border-bottom: none;
+}
+.box-header > .fa,
+.box-header > .glyphicon,
+.box-header > .ion,
+.box-header .box-title {
+  display: inline-block;
+  font-size: 18px;
+  margin: 0;
+  line-height: 1;
+}
+.box-header > .fa,
+.box-header > .glyphicon,
+.box-header > .ion {
+  margin-right: 5px;
+}
+.box-header > .box-tools {
+  position: absolute;
+  right: 10px;
+  top: 5px;
+}
+.box-header > .box-tools [data-toggle="tooltip"] {
+  position: relative;
+}
+.box-header > .box-tools.pull-right .dropdown-menu {
+  right: 0;
+  left: auto;
+}
+.btn-box-tool {
+  padding: 5px;
+  font-size: 12px;
+  background: transparent;
+  box-shadow: none!important;
+  color: #97a0b3;
+}
+.open .btn-box-tool,
+.btn-box-tool:hover {
+  color: #606c84;
+}
+.btn-box-tool:active {
+  outline: none!important;
+}
+.box-body {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+  padding: 10px;
+}
+.no-header .box-body {
+  border-top-right-radius: 3px;
+  border-top-left-radius: 3px;
+}
+.box-body > .table {
+  margin-bottom: 0;
+}
+.box-body .fc {
+  margin-top: 5px;
+}
+.box-body .full-width-chart {
+  margin: -19px;
+}
+.box-body.no-padding .full-width-chart {
+  margin: -9px;
+}
+.box-body .box-pane {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 3px;
+}
+.box-body .box-pane-right {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 0;
+}
+.box-footer {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+  border-top: 1px solid #f4f4f4;
+  padding: 10px;
+  background-color: #ffffff;
+}
+.chart-legend {
+  margin: 10px 0;
+}
+@media (max-width: 991px) {
+  .chart-legend > li {
+    float: left;
+    margin-right: 10px;
+  }
+}
+/* Widget: TODO LIST */
+.todo-list {
   margin: 0;
   padding: 0px 0px;
   list-style: none;
+  overflow: auto;
 }
-.box .todo-list > li {
-  -webkit-border-radius: 2px;
-  -moz-border-radius: 2px;
+.todo-list > li {
   border-radius: 2px;
   padding: 10px;
-  background: #f3f4f5;
+  background: #f4f4f4;
   margin-bottom: 2px;
   border-left: 2px solid #e6e7e8;
   color: #444;
 }
-.box .todo-list > li:last-of-type {
+.todo-list > li:last-of-type {
   margin-bottom: 0;
 }
-.box .todo-list > li.danger {
-  border-left-color: #f56954;
+.todo-list > li.danger {
+  border-left-color: #dd4b39;
 }
-.box .todo-list > li.warning {
+.todo-list > li.warning {
   border-left-color: #f39c12;
 }
-.box .todo-list > li.info {
+.todo-list > li.info {
   border-left-color: #00c0ef;
 }
-.box .todo-list > li.success {
+.todo-list > li.success {
   border-left-color: #00a65a;
 }
-.box .todo-list > li.primary {
+.todo-list > li.primary {
   border-left-color: #3c8dbc;
 }
-.box .todo-list > li > input[type='checkbox'] {
+.todo-list > li > input[type='checkbox'] {
   margin: 0 10px 0 5px;
 }
-.box .todo-list > li .text {
+.todo-list > li .text {
   display: inline-block;
   margin-left: 5px;
   font-weight: 600;
 }
-.box .todo-list > li .label {
+.todo-list > li .label {
   margin-left: 10px;
   font-size: 9px;
 }
-.box .todo-list > li .tools {
+.todo-list > li .tools {
   display: none;
   float: right;
-  color: #f56954;
+  color: #dd4b39;
 }
-.box .todo-list > li .tools > .fa,
-.box .todo-list > li .tools > .glyphicon,
-.box .todo-list > li .tools > .ion {
+.todo-list > li .tools > .fa,
+.todo-list > li .tools > .glyphicon,
+.todo-list > li .tools > .ion {
   margin-right: 5px;
   cursor: pointer;
 }
-.box .todo-list > li:hover .tools {
+.todo-list > li:hover .tools {
   display: inline-block;
 }
-.box .todo-list > li.done {
+.todo-list > li.done {
   color: #999;
 }
-.box .todo-list > li.done .text {
+.todo-list > li.done .text {
   text-decoration: line-through;
   font-weight: 500;
 }
-.box .todo-list > li.done .label {
-  background: #eaeaec !important;
+.todo-list > li.done .label {
+  background: #d2d6de !important;
 }
-.box .todo-list .handle {
+.todo-list .handle {
   display: inline-block;
   cursor: move;
   margin: 0 5px;
 }
-.box .chat {
+/* Chat widget (DEPRECATED - this will be removed in the next major release. Use Direct Chat instead)*/
+.chat {
   padding: 5px 20px 5px 10px;
 }
-.box .chat .item {
+.chat .item {
   margin-bottom: 10px;
 }
-.box .chat .item:before,
-.box .chat .item:after {
-  display: table;
+.chat .item:before,
+.chat .item:after {
   content: " ";
+  display: table;
 }
-.box .chat .item:after {
+.chat .item:after {
   clear: both;
 }
-.box .chat .item > img {
+.chat .item > img {
   width: 40px;
   height: 40px;
   border: 2px solid transparent;
-  -webkit-border-radius: 50% !important;
-  -moz-border-radius: 50% !important;
   border-radius: 50% !important;
 }
-.box .chat .item > img.online {
+.chat .item > img.online {
   border: 2px solid #00a65a;
 }
-.box .chat .item > img.offline {
-  border: 2px solid #f56954;
+.chat .item > img.offline {
+  border: 2px solid #dd4b39;
 }
-.box .chat .item > .message {
+.chat .item > .message {
   margin-left: 55px;
   margin-top: -40px;
 }
-.box .chat .item > .message > .name {
+.chat .item > .message > .name {
   display: block;
   font-weight: 600;
 }
-.box .chat .item > .attachment {
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
+.chat .item > .attachment {
   border-radius: 3px;
-  background: #f0f0f0;
+  background: #f4f4f4;
   margin-left: 65px;
   margin-right: 15px;
   padding: 10px;
 }
-.box .chat .item > .attachment > h4 {
+.chat .item > .attachment > h4 {
   margin: 0 0 5px 0;
   font-weight: 600;
   font-size: 14px;
 }
-.box .chat .item > .attachment > p,
-.box .chat .item > .attachment > .filename {
+.chat .item > .attachment > p,
+.chat .item > .attachment > .filename {
   font-weight: 600;
   font-size: 13px;
   font-style: italic;
   margin: 0;
 }
-.box .chat .item > .attachment:before,
-.box .chat .item > .attachment:after {
-  display: table;
+.chat .item > .attachment:before,
+.chat .item > .attachment:after {
   content: " ";
+  display: table;
 }
-.box .chat .item > .attachment:after {
+.chat .item > .attachment:after {
   clear: both;
 }
-.box > .overlay,
-.box > .loading-img {
-  position: absolute;
-  top: 0;
-  left: 0;
+.box-input {
+  max-width: 200px;
+}
+.modal .panel-body {
+  color: #444;
+}
+/*
+ * Component: Info Box
+ * -------------------
+ */
+.info-box {
+  display: block;
+  min-height: 90px;
+  background: #fff;
   width: 100%;
-  height: 100%;
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+  border-radius: 2px;
+  margin-bottom: 15px;
 }
-.box > .overlay {
-  z-index: 1010;
-  background: rgba(255, 255, 255, 0.7);
+.info-box small {
+  font-size: 14px;
 }
-.box > .overlay.dark {
-  background: rgba(0, 0, 0, 0.5);
+.info-box .progress {
+  background: rgba(0, 0, 0, 0.2);
+  margin: 5px -10px 5px -10px;
+  height: 2px;
+}
+.info-box .progress,
+.info-box .progress .progress-bar {
+  border-radius: 0;
+}
+.info-box .progress .progress-bar {
+  background: #fff;
+}
+.info-box-icon {
+  border-top-left-radius: 2px;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 2px;
+  display: block;
+  float: left;
+  height: 90px;
+  width: 90px;
+  text-align: center;
+  font-size: 45px;
+  line-height: 90px;
+  background: rgba(0, 0, 0, 0.2);
+}
+.info-box-content {
+  padding: 5px 10px;
+  margin-left: 90px;
+}
+.info-box-number {
+  display: block;
+  font-weight: bold;
+  font-size: 18px;
 }
-.box > .loading-img {
-  z-index: 1020;
-  background: transparent url('../img/ajax-loader1.gif') 50% 50% no-repeat;
+.progress-description,
+.info-box-text {
+  display: block;
+  font-size: 14px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.info-box-text {
+  text-transform: uppercase;
+}
+.info-box-more {
+  display: block;
+}
+.progress-description {
+  margin: 0;
 }
 /*
-Component: timeline
---------------------
-*/
+ * Component: Timeline
+ * -------------------
+ */
 .timeline {
   position: relative;
   margin: 0 0 30px 0;
@@ -1751,13 +2014,10 @@ Component: timeline
   position: absolute;
   top: 0px;
   bottom: 0;
-  width: 5px;
+  width: 4px;
   background: #ddd;
-  left: 30px;
-  border: 1px solid #eee;
+  left: 31px;
   margin: 0;
-  -webkit-border-radius: 2px;
-  -moz-border-radius: 2px;
   border-radius: 2px;
 }
 .timeline > li {
@@ -1767,33 +2027,35 @@ Component: timeline
 }
 .timeline > li:before,
 .timeline > li:after {
-  display: table;
   content: " ";
+  display: table;
 }
 .timeline > li:after {
   clear: both;
 }
 .timeline > li > .timeline-item {
-  margin-top: 10px;
-  border: 0px solid #dfdfdf;
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+  border-radius: 3px;
+  margin-top: 0px;
   background: #fff;
-  color: #555;
+  color: #444;
   margin-left: 60px;
   margin-right: 15px;
-  padding: 5px;
+  padding: 0;
   position: relative;
-  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
 }
 .timeline > li > .timeline-item > .time {
   color: #999;
   float: right;
-  margin: 2px 0 0 0;
+  padding: 10px;
+  font-size: 12px;
 }
 .timeline > li > .timeline-item > .timeline-header {
   margin: 0;
   color: #555;
   border-bottom: 1px solid #f4f4f4;
-  padding: 5px;
+  padding: 10px;
   font-size: 16px;
   line-height: 1.1;
 }
@@ -1809,214 +2071,201 @@ Component: timeline
   padding: 5px;
   display: inline-block;
   background-color: #fff;
-  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
   border-radius: 4px;
 }
 .timeline > li > .fa,
 .timeline > li > .glyphicon,
 .timeline > li > .ion {
-  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
   width: 30px;
   height: 30px;
   font-size: 15px;
   line-height: 30px;
   position: absolute;
   color: #666;
-  background: #eee;
+  background: #d2d6de;
   border-radius: 50%;
   text-align: center;
   left: 18px;
   top: 0;
 }
 /*
-    Component: Buttons
--------------------------
-*/
+ * Component: Button
+ * -----------------
+ */
 .btn {
-  font-weight: 500;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
   border-radius: 3px;
+  -webkit-box-shadow: none;
+  box-shadow: none;
   border: 1px solid transparent;
-  -webkit-box-shadow: inset 0px -2px 0px 0px rgba(0, 0, 0, 0.09);
-  -moz-box-shadow: inset 0px -2px 0px 0px rgba(0, 0, 0, 0.09);
-  box-shadow: inset 0px -1px 0px 0px rgba(0, 0, 0, 0.09);
 }
-.btn.btn-default {
-  background-color: #fafafa;
-  color: #666;
-  border-color: #ddd;
-  border-bottom-color: #ddd;
+.btn.uppercase {
+  text-transform: uppercase;
+}
+.btn.btn-flat {
+  border-radius: 0;
+  -webkit-box-shadow: none;
+  -moz-box-shadow: none;
+  box-shadow: none;
+  border-width: 1px;
+}
+.btn:active {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+  -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn:focus {
+  outline: none;
+}
+.btn.btn-file {
+  position: relative;
+  overflow: hidden;
+}
+.btn.btn-file > input[type='file'] {
+  position: absolute;
+  top: 0;
+  right: 0;
+  min-width: 100%;
+  min-height: 100%;
+  font-size: 100px;
+  text-align: right;
+  opacity: 0;
+  filter: alpha(opacity=0);
+  outline: none;
+  background: white;
+  cursor: inherit;
+  display: block;
 }
-.btn.btn-default:hover,
-.btn.btn-default:active,
-.btn.btn-default.hover {
-  background-color: #f4f4f4!important;
+.btn-default {
+  background-color: #f4f4f4;
+  color: #444;
+  border-color: #ddd;
 }
-.btn.btn-default.btn-flat {
-  border-bottom-color: #d9dadc;
+.btn-default:hover,
+.btn-default:active,
+.btn-default.hover {
+  background-color: #e7e7e7 !important;
 }
-.btn.btn-primary {
+.btn-primary {
   background-color: #3c8dbc;
   border-color: #367fa9;
 }
-.btn.btn-primary:hover,
-.btn.btn-primary:active,
-.btn.btn-primary.hover {
+.btn-primary:hover,
+.btn-primary:active,
+.btn-primary.hover {
   background-color: #367fa9;
 }
-.btn.btn-success {
+.btn-success {
   background-color: #00a65a;
   border-color: #008d4c;
 }
-.btn.btn-success:hover,
-.btn.btn-success:active,
-.btn.btn-success.hover {
+.btn-success:hover,
+.btn-success:active,
+.btn-success.hover {
   background-color: #008d4c;
 }
-.btn.btn-info {
+.btn-info {
   background-color: #00c0ef;
   border-color: #00acd6;
 }
-.btn.btn-info:hover,
-.btn.btn-info:active,
-.btn.btn-info.hover {
+.btn-info:hover,
+.btn-info:active,
+.btn-info.hover {
   background-color: #00acd6;
 }
-.btn.btn-danger {
-  background-color: #f56954;
-  border-color: #f4543c;
+.btn-danger {
+  background-color: #dd4b39;
+  border-color: #d73925;
 }
-.btn.btn-danger:hover,
-.btn.btn-danger:active,
-.btn.btn-danger.hover {
-  background-color: #f4543c;
+.btn-danger:hover,
+.btn-danger:active,
+.btn-danger.hover {
+  background-color: #d73925;
 }
-.btn.btn-warning {
+.btn-warning {
   background-color: #f39c12;
   border-color: #e08e0b;
 }
-.btn.btn-warning:hover,
-.btn.btn-warning:active,
-.btn.btn-warning.hover {
+.btn-warning:hover,
+.btn-warning:active,
+.btn-warning.hover {
   background-color: #e08e0b;
 }
-.btn.btn-flat {
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  border-radius: 0;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  border-width: 1px;
-}
-.btn:active {
-  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-  -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+.btn-outline {
+  border: 1px solid #fff;
+  background: transparent;
+  color: #fff;
 }
-.btn:focus {
-  outline: none;
+.btn-outline:hover,
+.btn-outline:focus,
+.btn-outline:active {
+  color: rgba(255, 255, 255, 0.7);
+  border-color: rgba(255, 255, 255, 0.7);
 }
-.btn.btn-file {
-  position: relative;
-  width: 120px;
-  height: 35px;
-  overflow: hidden;
+.btn-link {
+  -webkit-box-shadow: none;
+  box-shadow: none;
 }
-.btn.btn-file > input[type='file'] {
-  display: block !important;
-  width: 100% !important;
-  height: 35px !important;
-  opacity: 0 !important;
-  position: absolute;
-  top: -10px;
-  cursor: pointer;
+.btn[class*='bg-']:hover {
+  -webkit-box-shadow: inset 0 0 100px rgba(0, 0, 0, 0.2);
+  box-shadow: inset 0 0 100px rgba(0, 0, 0, 0.2);
 }
-.btn.btn-app {
+.btn-app {
+  border-radius: 3px;
   position: relative;
   padding: 15px 5px;
   margin: 0 0 10px 10px;
   min-width: 80px;
   height: 60px;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  border-radius: 0;
   text-align: center;
   color: #666;

<TRUNCATED>


[3/4] incubator-kylin git commit: KYLIN-792 ,add performance module

Posted by zh...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/server/src/main/java/org/apache/kylin/rest/service/PerformService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/PerformService.java b/server/src/main/java/org/apache/kylin/rest/service/PerformService.java
new file mode 100644
index 0000000..35b1207
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/service/PerformService.java
@@ -0,0 +1,123 @@
+/*
+ * 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.
+*/
+
+package org.apache.kylin.rest.service;
+
+import au.com.bytecode.opencsv.CSVReader;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FSDataInputStream;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.kylin.common.KylinConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.*;
+
+/**
+ * @author jiazhong
+ */
+@Component("performService")
+public class PerformService extends BasicService {
+
+    private static final Logger logger = LoggerFactory.getLogger(PerformService.class);
+
+    /*
+     * @return all query user
+     */
+    public  List<String[]> getTotalQueryUser() throws IOException {
+        String filePath = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory()+"/performance/metadata/total_query_user.csv";
+        List<String[]> res = readHdfsFile(filePath);
+        logger.info("Total Query User:"+res.get(0)[0]);
+       return  res;
+    }
+
+     /*
+     * @return last 30 daily query num
+     */
+    public  List<String[]> dailyQueryCount() throws IOException {
+        String filePath = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory()+"/performance/metadata/last_30_daily_query_count.csv";
+        List<String[]> res = readHdfsFile(filePath);
+       return  res;
+    }
+
+    /*
+     * @return average query count every day
+     */
+    public  List<String[]> avgDayQuery() throws IOException {
+        String filePath = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory()+"/performance/metadata/avg_day_query.csv";
+        List<String[]> res = readHdfsFile(filePath);
+        logger.info("Avg Day Query:"+res.get(0)[0]);
+        return  res;
+    }
+
+    /*
+     *@return average latency every day
+     */
+    public List<String[]> last30DayPercentile() throws IOException {
+        String filePath = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory()+"/performance/metadata/last_30_day_90_percentile_latency.csv";
+        List<String[]> res = readHdfsFile(filePath);
+        return res;
+    }
+
+    /*
+     *@return average latency for every cube
+     */
+    public List<String[]> eachDayPercentile() throws IOException {
+        String filePath = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory()+"/performance/metadata/each_day_90_95_percentile_latency.csv";
+        List<String[]> res = readHdfsFile(filePath);
+        return res;
+    }
+
+    /*
+     *@return average latency for every cube
+     */
+    public List<String[]> projectPercentile() throws IOException {
+        String filePath = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory()+"/performance/metadata/project_90_95_percentile_latency.csv";
+        List<String[]> res = readHdfsFile(filePath);
+        return res;
+    }
+
+
+    private List<String[]> readHdfsFile(String filePath) throws IOException {
+        List<String[]> allRows = null;
+        CSVReader reader = null;
+        FileSystem fs = null;
+        Configuration conf = new Configuration();
+
+        try {
+            fs = FileSystem.newInstance(conf);
+            FSDataInputStream inputStream = fs.open(new Path(filePath));
+            reader = new CSVReader(new InputStreamReader (inputStream),'|');
+
+            //Read all rows at once
+            allRows = reader.readAll();
+
+
+        } catch (IOException e) {
+            logger.info("failed to read hdfs file:",e);
+        }
+        finally {
+            fs.close();
+        }
+        return allRows;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/server/src/main/resources/kylinSecurity.xml
----------------------------------------------------------------------
diff --git a/server/src/main/resources/kylinSecurity.xml b/server/src/main/resources/kylinSecurity.xml
index d372240..22eea4c 100644
--- a/server/src/main/resources/kylinSecurity.xml
+++ b/server/src/main/resources/kylinSecurity.xml
@@ -34,6 +34,7 @@
 		<scr:intercept-url pattern="/api/cubes/src/tables" access="hasAnyRole('ROLE_ANALYST')" />
 		<scr:intercept-url pattern="/api/cubes*/**" access="isAuthenticated()" />
 		<scr:intercept-url pattern="/api/job*/**" access="isAuthenticated()" />
+		<scr:intercept-url pattern="/api/performance*/**" access="isAuthenticated()" />
 		<scr:intercept-url pattern="/api/admin/config" access="permitAll" />
 		<scr:intercept-url pattern="/api/projects" access="permitAll" />
 		<scr:intercept-url pattern="/api/admin*/**" access="hasRole('ROLE_ADMIN')" />

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a935c7ba/server/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/server/src/main/webapp/WEB-INF/web.xml b/server/src/main/webapp/WEB-INF/web.xml
index d12f81a..703c815 100644
--- a/server/src/main/webapp/WEB-INF/web.xml
+++ b/server/src/main/webapp/WEB-INF/web.xml
@@ -14,10 +14,10 @@ limitations under the License. See accompanying LICENSE file.
 -->
 
 <web-app xmlns="http://java.sun.com/xml/ns/javaee"
-           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
 		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
-           version="2.5">
+         version="2.5">
 
     <display-name>Kylin RESt Service</display-name>
 
@@ -37,10 +37,10 @@ limitations under the License. See accompanying LICENSE file.
     <context-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>
-        	classpath:applicationContext.xml
-			classpath:kylinSecurity.xml
-			classpath*:kylin-*-plugin.xml
-		</param-value>
+            classpath:applicationContext.xml
+            classpath:kylinSecurity.xml
+            classpath*:kylin-*-plugin.xml
+        </param-value>
     </context-param>
 
     <listener>
@@ -50,46 +50,58 @@ limitations under the License. See accompanying LICENSE file.
     <listener>
         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
     </listener>
-    
+
+    <listener>
+        <listener-class>com.ryantenney.metrics.spring.servlets.MetricsServletsContextListener</listener-class>
+    </listener>
     <listener>
-    	<listener-class>com.ryantenney.metrics.spring.servlets.MetricsServletsContextListener</listener-class>
+        <listener-class>org.apache.kylin.rest.metrics.KylinInstrumentedFilterContextListener</listener-class>
     </listener>
+
     <listener>
-    	<listener-class>org.apache.kylin.rest.metrics.KylinInstrumentedFilterContextListener</listener-class>
+        <listener-class>
+            org.springframework.security.web.session.HttpSessionEventPublisher
+        </listener-class>
     </listener>
 
-	<listener>
-		<listener-class>
-			org.springframework.security.web.session.HttpSessionEventPublisher
-		</listener-class>
-	</listener>
-	
-<filter>
-   <filter-name>CORS</filter-name>
-   <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>       
-   <init-param>
-      <param-name>cors.supportedHeaders</param-name>
-      <param-value>Authorization,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Accept</param-value>
-   </init-param>   
-  <init-param>
-      <param-name>cors.supportedMethods</param-name>
-      <param-value>GET, POST, PUT, DELETE, OPTIONS</param-value>
-   </init-param>     
-  <init-param>
-      <param-name>cors.supportsCredentials </param-name>
-      <param-value>true</param-value>
-   </init-param>    
-</filter>
-
-<filter-mapping>
-   <filter-name>CORS</filter-name>
-   <url-pattern>/*</url-pattern>
-</filter-mapping>
-	
-	<!--
-		Apply Spring Security Filter to all Requests 
-	 -->
-	<filter>
+    <filter>
+        <filter-name>CORS</filter-name>
+        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
+        <init-param>
+            <param-name>cors.supportedHeaders</param-name>
+            <param-value>Authorization,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified,
+                Cache-Control, Expires, Content-Type, X-E4M-With, Accept
+            </param-value>
+        </init-param>
+        <init-param>
+            <param-name>cors.supportedMethods</param-name>
+            <param-value>GET, POST, PUT, DELETE, OPTIONS</param-value>
+        </init-param>
+        <init-param>
+            <param-name>cors.supportsCredentials</param-name>
+            <param-value>true</param-value>
+        </init-param>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>CORS</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+    <filter>
+        <filter-name>loggingFilter</filter-name>
+        <filter-class>org.apache.kylin.rest.filter.KylinApiFilter</filter-class>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>loggingFilter</filter-name>
+        <url-pattern>/api/*</url-pattern>
+    </filter-mapping>
+
+    <!--
+        Apply Spring Security Filter to all Requests
+     -->
+    <filter>
         <filter-name>springSecurityFilterChain</filter-name>
         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
     </filter>
@@ -98,15 +110,15 @@ limitations under the License. See accompanying LICENSE file.
         <url-pattern>/*</url-pattern>
     </filter-mapping>
 
-	<filter>
-	    <filter-name>instrumentedFilter</filter-name>
-	    <filter-class>com.codahale.metrics.servlet.InstrumentedFilter</filter-class>
-	</filter>
-	<filter-mapping>
-	    <filter-name>instrumentedFilter</filter-name>
-	    <url-pattern>/*</url-pattern>
-	</filter-mapping>
-	
+    <filter>
+        <filter-name>instrumentedFilter</filter-name>
+        <filter-class>com.codahale.metrics.servlet.InstrumentedFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>instrumentedFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
     <servlet>
         <servlet-name>kylin</servlet-name>
         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
@@ -125,7 +137,7 @@ limitations under the License. See accompanying LICENSE file.
         <servlet-name>metricsservlet</servlet-name>
         <url-pattern>/metrics/*</url-pattern>
     </servlet-mapping>
-    
+
     <servlet>
         <servlet-name>metricsadminservlet</servlet-name>
         <servlet-class>com.codahale.metrics.servlets.AdminServlet</servlet-class>
@@ -135,9 +147,9 @@ limitations under the License. See accompanying LICENSE file.
         <servlet-name>metricsadminservlet</servlet-name>
         <url-pattern>/metricsadmin/*</url-pattern>
     </servlet-mapping>
-    
-	<!-- 
-	<servlet>
+
+    <!--
+    <servlet>
         <servlet-name>matricsadmin</servlet-name>
         <servlet-class>com.codahale.metrics.servlets.MetricsServlet</servlet-class>
         <load-on-startup>1</load-on-startup>