From f739856e7ef3847edd3940918b1c220ad37ed96e Mon Sep 17 00:00:00 2001 From: zombieJ Date: Tue, 10 Jan 2017 17:36:22 +0800 Subject: [PATCH] support metric check --- .../src/main/webapp/app/dev/index.html | 2 + .../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(-) create mode 100644 eagle-server/src/main/webapp/app/dev/partials/metric/preview.html create mode 100644 eagle-server/src/main/webapp/app/dev/public/js/ctrls/metricCtrl.js diff --git a/eagle-server/src/main/webapp/app/dev/index.html b/eagle-server/src/main/webapp/app/dev/index.html index ec0a76a4fe..74d5c579e2 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 @@
  • How to install application
  • How to manage application
  • How to develop application
  • +
  • Preview eagle metric
  • @@ -293,6 +294,7 @@ + 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 0000000000..0c16ec03a1 --- /dev/null +++ b/eagle-server/src/main/webapp/app/dev/partials/metric/preview.html @@ -0,0 +1,68 @@ + + +
    +
    +
    +
    +

    Configure

    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + +
    +
    +
    +
    +
    +

    Preview

    +
    +
    +
    +
    +
    +
    +
    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 e1f5b7779d..79c2df5861 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", 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 99f74d5135..63855b6c82 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]; 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 0000000000..e0f0f15c82 --- /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); + }); +}()); 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 d9d4ce7a5c..8296451827 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; }); })(); diff --git a/eagle-server/src/main/webapp/app/package.json b/eagle-server/src/main/webapp/app/package.json index c1c652e758..4ee3eda924 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",