Repository: eagle
Updated Branches:
  refs/heads/master 18424b9f5 -> 0d4f109fa


[EAGLE-855] support metric check

Add metric/preview for metric checking

Author: zombieJ <[email protected]>

Closes #770 from zombieJ/EAGLE-855.


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

Branch: refs/heads/master
Commit: 0d4f109fa51d2f1c409e8335f8c4e5d48a66a87b
Parents: 18424b9
Author: zombieJ <[email protected]>
Authored: Wed Jan 11 10:52:54 2017 +0800
Committer: Hao Chen <[email protected]>
Committed: Wed Jan 11 10:52:54 2017 +0800

----------------------------------------------------------------------
 eagle-server/src/main/webapp/app/dev/index.html |   2 +
 .../webapp/app/dev/partials/metric/preview.html |  68 +++++++++
 .../src/main/webapp/app/dev/public/js/app.js    |   9 ++
 .../app/dev/public/js/components/chart.js       |  38 ++++-
 .../app/dev/public/js/ctrls/metricCtrl.js       |  77 ++++++++++
 .../public/js/services/compatibleEntitySrv.js   | 142 +++++++++++++++++--
 eagle-server/src/main/webapp/app/package.json   |   2 +-
 7 files changed, 326 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/eagle/blob/0d4f109f/eagle-server/src/main/webapp/app/dev/index.html
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/index.html 
b/eagle-server/src/main/webapp/app/dev/index.html
index ec0a76a..74d5c57 100644
--- a/eagle-server/src/main/webapp/app/dev/index.html
+++ b/eagle-server/src/main/webapp/app/dev/index.html
@@ -116,6 +116,7 @@
                                                                        
<li><a>How to install application</a></li>
                                                                        
<li><a>How to manage application</a></li>
                                                                        
<li><a>How to develop application</a></li>
+                                                                       <li><a 
ui-sref="metricPreview()">Preview eagle metric</a></li>
                                                                </ul>
                                                        </li>
                                                </ul>
@@ -293,6 +294,7 @@
                <script src="public/js/ctrls/alertEditCtrl.js" 
type="text/javascript" charset="utf-8"></script>
                <script src="public/js/ctrls/integrationCtrl.js" 
type="text/javascript" charset="utf-8"></script>
                <script src="public/js/ctrls/siteCtrl.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/ctrls/metricCtrl.js" 
type="text/javascript" charset="utf-8"></script>
                <!-- endref -->
        </body>
 </html>

http://git-wip-us.apache.org/repos/asf/eagle/blob/0d4f109f/eagle-server/src/main/webapp/app/dev/partials/metric/preview.html
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/partials/metric/preview.html 
b/eagle-server/src/main/webapp/app/dev/partials/metric/preview.html
new file mode 100644
index 0000000..0c16ec0
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/metric/preview.html
@@ -0,0 +1,68 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="row">
+       <div class="col-sm-12 col-md-5 col-lg-3">
+               <div class="box box-primary">
+                       <div class="box-header with-border">
+                               <h3 class="box-title">Configure</h3>
+                       </div>
+                       <div class="box-body">
+                               <div class="form-group">
+                                       <label>Site</label>
+                                       <select class="form-control" 
ng-model="site">
+                                               <option ng-repeat="site in 
Site.list track by $index" value="{{site.siteId}}">
+                                                       {{site.siteName || 
site.siteId}}
+                                               </option>
+                                       </select>
+                               </div>
+                               <div class="form-group">
+                                       <label>Metric Name</label>
+                                       <select class="form-control" 
ng-model="metricName">
+                                               <option ng-repeat="metric in 
metricList track by metric">{{metric}}</option>
+                                       </select>
+                               </div>
+                               <div class="form-group">
+                                       <label>Groups</label>
+                                       <input type="text" class="form-control" 
ng-model="groups" placeholder="e.g. 'site'" />
+                               </div>
+                               <div class="form-group">
+                                       <label>Fields</label>
+                                       <input type="text" class="form-control" 
ng-model="fields" placeholder="e.g. 'avg(value), sum(value) desc'" />
+                               </div>
+                               <!--div class="form-group">
+                                       <label>Interval Minutes</label>
+                                       <input type="text" class="form-control" 
ng-model="intervalmin" />
+                               </div-->
+                       </div>
+                       <div class="box-footer text-right">
+                               <button class="btn btn-primary" 
ng-click="loadSeries()">Apply</button>
+                       </div>
+               </div>
+       </div>
+       <div class="col-sm-12 col-md-7 col-lg-9">
+               <div class="box box-primary">
+                       <div class="box-header with-border">
+                               <h3 class="box-title">Preview</h3>
+                       </div>
+                       <div class="box-body">
+                               <div chart style="height: 400px;" 
series="series" option="commonOption"></div>
+                       </div>
+               </div>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/0d4f109f/eagle-server/src/main/webapp/app/dev/public/js/app.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/app.js 
b/eagle-server/src/main/webapp/app/dev/public/js/app.js
index e1f5b77..79c2df5 100644
--- a/eagle-server/src/main/webapp/app/dev/public/js/app.js
+++ b/eagle-server/src/main/webapp/app/dev/public/js/app.js
@@ -192,6 +192,15 @@ var app = {};
                                        resolve: routeResolve({ application: 
false })
                                })
 
+                               // ================================= Metric 
=================================
+                               .state('metricPreview', {
+                                       url: 
"/metric/preview?startTime&endTime&site&metric&groups&fields",
+                                       templateUrl: 
"partials/metric/preview.html?_=" + window._TRS(),
+                                       controller: "metricPreviewCtrl",
+                                       reloadOnSearch: false,
+                                       resolve: routeResolve({ application: 
false, time: true })
+                               })
+
                                // ================================== Site 
==================================
                                .state('site', {
                                        url: "/site/:siteId",

http://git-wip-us.apache.org/repos/asf/eagle/blob/0d4f109f/eagle-server/src/main/webapp/app/dev/public/js/components/chart.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/components/chart.js 
b/eagle-server/src/main/webapp/app/dev/public/js/components/chart.js
index 99f74d5..63855b6 100644
--- a/eagle-server/src/main/webapp/app/dev/public/js/components/chart.js
+++ b/eagle-server/src/main/webapp/app/dev/public/js/components/chart.js
@@ -29,6 +29,10 @@
                };
        });
 
+       /**
+        * @param {{}?} chart Set chart reference
+        * @param {function} chart.refresh Refresh current chart
+        */
        eagleComponents.directive('chart', function(Chart) {
                var charts = Chart.charts;
 
@@ -61,14 +65,43 @@
                        },
                        controller: function ($scope, $element, $attrs, Time) {
                                var i;
+                               var lastSeriesCount = 0;
                                var lastTooltipEvent;
                                var chart = echarts.init($element[0]);
                                charts[chart.id] = chart;
 
+                               function wrapChart() {
+                                       chart.refresh = function () {
+                                               refreshChart();
+                                       };
+
+                                       chart.forceRefresh = function () {
+                                               delete charts[chart.id];
+                                               chart.dispose();
+
+                                               chart = 
echarts.init($element[0]);
+                                               charts[chart.id] = chart;
+                                               lastSeriesCount = 0;
+
+                                               refreshChart();
+
+                                               wrapChart();
+                                       };
+                               }
+
                                function refreshChart() {
                                        var maxYAxis = 0;
                                        var legendList = [];
                                        var categoryList = $scope.category ? 
$scope.category : [];
+                                       var currentSeriesCount = ($scope.series 
|| []).length;
+
+                                       if (lastSeriesCount > 
currentSeriesCount && chart.forceRefresh) {
+                                               console.log('Force refresh!');
+                                               // TODO: echart series bug. 
Need rebuild the chart. Ref: https://github.com/ecomfe/echarts/issues/4033
+                                               chart.forceRefresh();
+                                               return;
+                                       }
+                                       lastSeriesCount = currentSeriesCount;
 
                                        var seriesList = $.map($scope.series || 
[], function (series, id) {
                                                if(id === 0 && 
!$scope.category) {
@@ -166,13 +199,12 @@
                                        $scope.$parent.$parent[$attrs.chart] = 
chart;
                                }
 
-                               chart.refresh = function () {
-                                       refreshChart();
-                               };
+                               wrapChart();
 
                                // Render
                                refreshChart();
                                $scope.$watch("series", refreshChart);
+                               $scope.$watch("series.length", refreshChart);
 
                                $scope.$on('$destroy', function() {
                                        delete charts[chart.id];

http://git-wip-us.apache.org/repos/asf/eagle/blob/0d4f109f/eagle-server/src/main/webapp/app/dev/public/js/ctrls/metricCtrl.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/ctrls/metricCtrl.js 
b/eagle-server/src/main/webapp/app/dev/public/js/ctrls/metricCtrl.js
new file mode 100644
index 0000000..e0f0f15
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/js/ctrls/metricCtrl.js
@@ -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.
+ */
+
+(function() {
+       'use strict';
+
+       var eagleControllers = angular.module('eagleControllers');
+
+       // 
======================================================================================
+       // =                                        Alert                       
                =
+       // 
======================================================================================
+       eagleControllers.controller('metricPreviewCtrl', function ($scope, 
$wrapState, PageConfig, CompatibleEntity, Time, Site) {
+               PageConfig.title = "Metric Preview";
+
+               $scope.series = [];
+               $scope.loading = false;
+
+               $scope.site = $wrapState.param.site || Site.list[0].siteId;
+               $scope.metricName = $wrapState.param.metric;
+               $scope.groups = $wrapState.param.groups;
+               $scope.fields = $wrapState.param.fields;
+
+               $scope.commonOption = {};
+
+               $scope.metricList = [$scope.metricName];
+               CompatibleEntity.groups({
+                       query: 'MetricSchemaService',
+                       groups: 'metricName',
+                       fields: 'count',
+                       limit: 9999,
+               })._promise.then(function (res) {
+                       $scope.metricList = $.map(res.data.obj, function (obj) {
+                               return obj.key[0];
+                       }).sort();
+               });
+
+               $scope.loadSeries = function() {
+                       $scope.series = CompatibleEntity.timeSeries({
+                               condition: { site: $scope.site },
+                               groups: $scope.groups,
+                               fields: $scope.fields,
+                               top: 10,
+                               metric: $scope.metricName,
+                               limit: 100000,
+                       });
+
+                       // Update URL
+                       $wrapState.go(".", {
+                               site: $scope.site,
+                               metric: $scope.metricName,
+                               groups: $scope.groups,
+                               fields: $scope.fields,
+                       });
+               };
+
+               if ($scope.metricName && $scope.groups && $scope.fields) {
+                       $scope.loadSeries();
+               }
+
+               Time.onReload($scope.loadSeries, $scope);
+       });
+}());

http://git-wip-us.apache.org/repos/asf/eagle/blob/0d4f109f/eagle-server/src/main/webapp/app/dev/public/js/services/compatibleEntitySrv.js
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/public/js/services/compatibleEntitySrv.js
 
b/eagle-server/src/main/webapp/app/dev/public/js/services/compatibleEntitySrv.js
index d9d4ce7..8296451 100644
--- 
a/eagle-server/src/main/webapp/app/dev/public/js/services/compatibleEntitySrv.js
+++ 
b/eagle-server/src/main/webapp/app/dev/public/js/services/compatibleEntitySrv.js
@@ -55,15 +55,61 @@
                }
 
                function parseFields(fields) {
-                       fields = fields || [];
-                       if(fields.length === 0) return '*';
+                       fields = $.isArray(fields) ? fields : (
+                               fields && fields !== '*' ? 
fields.split(/\s*,\s*/) : []
+                       );
+                       if(fields.length === 0) return {
+                               fieldStr: '*',
+                               fields: [],
+                               order: ''
+                       };
+
+                       var fieldList = [];
+                       var fieldEntities = [];
+                       var orderId = -1;
+                       var fieldStr = $.map(fields, function (field, index) {
+                               var matches = field.match(/^([^\s]*)(\s+.*)?$/);
+                               var fieldName = matches[1];
+                               if(matches[2]) {
+                                       orderId = index;
+                               }
+                               var fieldMatches = 
fieldName.match(/^(.+)\((.+)\)$/);
+                               if (fieldName === 'count') {
+                                       fieldEntities.push({
+                                               method: 'count',
+                                               name: 'count',
+                                       });
+                                       fieldList.push('count');
+                                       return fieldName;
+                               }
+                               else if (fieldMatches) {
+                                       fieldEntities.push({
+                                               method: fieldMatches[1],
+                                               name: fieldMatches[2],
+                                       });
+                                       fieldList.push(fieldName);
+                                       return fieldName;
+                               } else {
+                                       fieldEntities.push({
+                                               method: '',
+                                               name: fieldName,
+                                       });
+                                       fieldList.push('@' + fieldName);
+                                       return '@' + fieldName;
+                               }
+                       }).join(", ");
 
-                       return $.map(fields, function (field) {
-                               return '@' + field;
-                       }).join(',');
+                       return {
+                               fieldStr: fieldStr,
+                               fields: fieldList,
+                               fieldEntities: fieldEntities,
+                               order: orderId === -1 ? "" : ".{" + 
fields[orderId] + "}"
+                       };
                }
 
-               CompatibleEntity.QUERY_LIST = 
'/rest/entities?query=${query}[${condition}]{${fields}}&pageSize=${size}';
+               CompatibleEntity.QUERY_LIST = 
'/rest/entities?query=${query}[${condition}]{${fields}}&pageSize=${limit}';
+               CompatibleEntity.QUERY_GROUPS = 
'/rest/entities?query=${query}[${condition}]<${groups}>{${fields}}&pageSize=${limit}';
+               CompatibleEntity.QUERY_METRICS_INTERVAL = 
'/rest/entities?query=GenericMetricService[${condition}]<${groups}>{${fields}}${order}${top}&metricName=${metric}&pageSize=${limit}&startTime=${startTime}&endTime=${endTime}&intervalmin=${intervalMin}&timeSeries=true';
 
                CompatibleEntity.query = function (queryName, param) {
                        var list = [];
@@ -71,10 +117,10 @@
 
                        list._refresh = function () {
                                var myParam = $.extend({
-                                       size: 10000,
+                                       limit: 10000,
                                }, param || {}, {
                                        condition: 
parseCondition(param.condition),
-                                       fields: parseFields(param.fields),
+                                       fields: 
parseFields(param.fields).fieldStr,
                                        startTime: Time.format(param.startTime),
                                        endTime: Time.format(param.endTime)
                                });
@@ -91,6 +137,86 @@
                        return list._refresh();
                };
 
+               /**
+                *
+                * @param {string} queryName
+                * @param {string} param.query
+                * @param {{}?} param.condition
+                * @param {string|[]} param.groups
+                * @param {string|[]} param.fields
+                * @param {number?} param.limit
+                */
+               CompatibleEntity.groups = function (param) {
+                       return CompatibleEntity.query('GROUPS', $.extend({}, 
param, {
+                               groups: parseFields(param.groups).fields,
+                       }));
+               };
+
+               /**
+                *
+                * @param {string} queryName
+                * @param {{}?} param.condition
+                * @param {string|[]} param.groups
+                * @param {string|[]} param.fields
+                * @param {string} param.metric
+                * @param {{}} param.startTime
+                * @param {{}} param.endTime
+                * @param {number?} param.top
+                * @param {number?} param.limit
+                * @param {number?} param.intervalMin
+                */
+               CompatibleEntity.timeSeries = function (param) {
+                       param = param || {};
+                       var fields = parseFields(param.fields);
+                       var startTime = new Time(param.startTime || 
'startTime');
+                       var endTime = new Time(param.endTime || 'endTime');
+
+                       var startTimestamp = startTime.valueOf();
+                       var intervalMin = param.intervalMin ? param.intervalMin 
: Time.diffInterval(startTime, endTime) / 1000 / 60;
+                       var interval = intervalMin * 1000 * 60;
+
+                       var innerList = 
CompatibleEntity.query('METRICS_INTERVAL', $.extend({}, param, {
+                               groups: parseFields(param.groups).fields,
+                               order: fields.order,
+                               top: param.top ? "&top=" + param.top : "",
+                               startTime: startTime,
+                               endTime: endTime,
+                               intervalMin: intervalMin,
+                       }));
+
+                       var list = [];
+                       list._done = false;
+                       list._promise = innerList._promise;
+
+                       innerList._promise.then(function () {
+                               var displayKey = innerList.length > 1;
+
+                               // Generate series
+                               var series = $.map(innerList, function (group) {
+                                       return $.map(fields.fieldEntities, 
function (entity, i) {
+                                               var data = group.value[i];
+                                               return {
+                                                       name: (displayKey ? 
group.key.join(',') + '-' : '') + (entity.method || entity.name),
+                                                       type: 'line',
+                                                       showSymbol: false,
+                                                       data: $.map(data, 
function (value, index) {
+                                                               return {
+                                                                       x: 
startTimestamp + interval * index,
+                                                                       y: value
+                                                               };
+                                                       })
+                                               };
+                                       });
+                               });
+
+                               list.splice(0);
+                               Array.prototype.push.apply(list, series);
+                               list._done = true;
+                       });
+
+                       return list;
+               };
+
                return CompatibleEntity;
        });
 })();

http://git-wip-us.apache.org/repos/asf/eagle/blob/0d4f109f/eagle-server/src/main/webapp/app/package.json
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/package.json 
b/eagle-server/src/main/webapp/app/package.json
index c1c652e..4ee3eda 100644
--- a/eagle-server/src/main/webapp/app/package.json
+++ b/eagle-server/src/main/webapp/app/package.json
@@ -23,7 +23,7 @@
     "angular-ui-router": "0.3.1",
     "bootstrap": "3.3.6",
     "d3": "3.5.16",
-    "echarts": "^3.2.3",
+    "echarts": "^3.3.2",
     "font-awesome": "4.7.0",
     "jquery": "2.2.4",
     "jquery-slimscroll": "1.3.6",

Reply via email to