diff --git a/v2/src/app/app.js b/v2/src/app/app.js index 531ff2b..96b84e8 100644 --- a/v2/src/app/app.js +++ b/v2/src/app/app.js @@ -44,6 +44,7 @@ define([ $httpProvider.interceptors.push('authenticationInterceptor'); }); compassModule.run(function($rootScope, $state, authService, rememberMe) { + $rootScope.Object = Object; //Object can be used in anywhere. e.g. : Object.key({}).length == 0 $rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) { if (toState.authenticate && !authService.isAuthenticated) { if (rememberMe.getCookie("isAuthenticated")) { diff --git a/v2/src/app/appDev.js b/v2/src/app/appDev.js index d768680..13af985 100644 --- a/v2/src/app/appDev.js +++ b/v2/src/app/appDev.js @@ -1577,6 +1577,22 @@ compassAppDev.run(function($httpBackend, settings, $http) { //var metricsName = ["cpu.0.cpu.idle.value","cpu.0.cpu.interrupt.value"]; return [200, metricsName, {}]; }); + $httpBackend.whenPOST(/\.*\/monit.*\/([0-9]|[1-9][0-9])\/datapointtags$/).respond(function(method, url, data) { + console.log(method, url, data); + + var tag = '{"queries":[{"results":[{"name":"cpu.0.cpu.idle.value","tags":{"cluster":["no_cluster_defined"],"host":["controller-node","host-1","host-2","host-4","host-5","network-node","ws-compute1","ws-compute2","ws-compute3","ws-controller-1","ws-controller1","ws-network-1","ws-network-node1","ws-network1"],"location":["China_Beijing_TsingHua"],"role":["OSROLE"]},"values":[]}]}]}'; + return [200, tag, {}]; + }); + $httpBackend.whenPOST(/\.*\/monit.*\/([0-9]|[1-9][0-9])\/datapoints$/).respond(function(method, url, data) { + console.log(method, url, data); + var temp = JSON.parse(data); + var name = temp.metrics[0].name; + var returnData = '{"queries":[{"sample_size":70,"results":[{"name":"'+name+'","group_by":[{"name":"type","type":"number"}],"tags":{"host":["compass"],"metric_name":["abc.123","cpu.0.cpu.idle.value","cpu.0.cpu.idle.valued","cpu.0.cpu.interrupt.value","cpu.0.cpu.nice.value","disk.sda1.disk_time.read","disk.sda3.disk_time.read","disk.sdb.disk_ops.read","interface.br-tun.if_packets.tx","interface.eth1.if_octets.tx","interface.ovs-system.if_errors.rx","interface.ovs-system.if_octets.tx","kairosdb.datastore.cassandra.key_query_time","kairosdb.datastore.write_size","kairosdb.http.query_time","kairosdb.jvm.free_memory","kairosdb.metric_counters","kairosdb.protocol.http_request_count","xyz.123"],"query_index":["1","2"],"request":["/datapoints/query"]},"values":[[1415644662297,2],[1415644936452,2],[1415649105761,2],[1415649133036,3],[1415649149375,2],[1415649394291,3],[1415649400565,2],[1415649410542,2],[1415649424551,2],[1415649428733,2],[1415649438466,13],[1415649444112,2],[1415649451616,1],[1415649455418,2],[1415649461539,7],[1415649466140,3],[1415649471111,2],[1415649480943,2],[1415649492421,8],[1415649501825,2],[1415649545118,2],[1415649554317,2],[1415649559818,2],[1415649566444,4],[1415649597100,2],[1415649602176,3],[1415649631102,2],[1415649645477,1],[1415649668532,2],[1415649682906,2],[1415649688626,2],[1415649694573,2],[1415649697620,2],[1415649701637,4],[1415649714586,3],[1415649720301,3],[1415649745416,4],[1415649768064,20],[1415649796993,17],[1415655678192,5],[1415655715682,5],[1415655781993,3],[1415656049377,2],[1415656060996,3],[1415656086790,2],[1415656309450,2],[1415656471533,2],[1415656607109,3],[1415656748677,2],[1415662600041,9],[1415662673534,2],[1415663014707,23],[1415663033765,2],[1415663042641,2],[1415663137052,2],[1415663188992,2],[1415664367333,2],[1415665535212,1],[1415665671592,2],[1415666048027,2],[1415666069368,2],[1415666086166,2],[1415666111794,3],[1415666135228,2],[1415666179974,2],[1415666287690,9],[1415666321824,2],[1415666341186,3],[1415666370086,2]]}]}]}'; + if (temp.end_relative) { + returnData = '{"queries":[{"sample_size":70,"results":[{"name":"'+name+'","group_by":[{"name":"type","type":"number"}],"tags":{"host":["compass"],"metric_name":["abc.123","cpu.0.cpu.idle.value","cpu.0.cpu.idle.valued","cpu.0.cpu.interrupt.value","cpu.0.cpu.nice.value","disk.sda1.disk_time.read","disk.sda3.disk_time.read","disk.sdb.disk_ops.read","interface.br-tun.if_packets.tx","interface.eth1.if_octets.tx","interface.ovs-system.if_errors.rx","interface.ovs-system.if_octets.tx","kairosdb.datastore.cassandra.key_query_time","kairosdb.datastore.write_size","kairosdb.http.query_time","kairosdb.jvm.free_memory","kairosdb.metric_counters","kairosdb.protocol.http_request_count","xyz.123"],"query_index":["1","2"],"request":["/datapoints/query"]},"values":[[1415644662297,2],[1415644936452,2],[1415649105761,2],[1415649133036,3],[1415649149375,2],[1415649394291,3],[1415649400565,2],[1415649410542,2],[1415649424551,2],[1415649428733,2],[1415649438466,13],[1415649444112,2],[1415649451616,1],[1415649455418,2],[1415649461539,7],[1415649466140,3],[1415649471111,2],[1415649480943,2],[1415649492421,8],[1415649501825,2],[1415649545118,2],[1415649554317,2],[1415649559818,2],[1415649566444,4],[1415649597100,2],[1415649602176,3],[1415649631102,2],[1415649645477,1],[1415649668532,2],[1415649682906,2],[1415649688626,2],[1415649694573,2],[1415649697620,2],[1415649701637,4],[1415649714586,3],[1415649720301,3],[1415649745416,4],[1415649768064,20],[1415649796993,17],[1415655678192,5],[1415655715682,5],[1415655781993,3],[1415656049377,2],[1415656060996,3],[1415656086790,2],[1415656309450,2],[1415656471533,2],[1415656607109,3],[1415656748677,2],[1415662600041,9],[1415662673534,2],[1415663014707,23],[1415663033765,2],[1415663042641,2],[1415663137052,2],[1415663188992,2],[1415664367333,2],[1415665535212,1],[1415665671592,2],[1415666048027,2],[1415666069368,2],[1415666086166,2],[1415666111794,3],[1415666135228,2],[1415666179974,2],[1415666287690,9],[1415666321824,2],[1415666341186,3],[1415666370086,100]]}]}]}'; + } + return [200, returnData, {}]; + }); $httpBackend.whenGET(/\.*\/monit.*clusters\/([0-9]|[1-9][0-9])\/metrics\/.*/).respond(function(method, url, data) { console.log(method, url, data); diff --git a/v2/src/app/monitoring/metrics.tpl.html b/v2/src/app/monitoring/metrics.tpl.html index aacdb18..da2682c 100644 --- a/v2/src/app/monitoring/metrics.tpl.html +++ b/v2/src/app/monitoring/metrics.tpl.html @@ -43,6 +43,22 @@

Metrics Chart

+ +
+ From + + ago + To + + ago + +
-1) - { + if ((start = node.title.indexOf("(")) > -1) { var end = node.title.indexOf(")"); - var insideWord = node.title.substring(start+1,end); - node.id = name +"."+node.title.substring(0,start-1)+"."+insideWord; + var insideWord = node.title.substring(start + 1, end); + node.id = name + "." + node.title.substring(0, start - 1) + "." + insideWord; // console.log(node.title); - } - else - { - node.id = name+"."+node.title; + } else { + node.id = name + "." + node.title; } return; } - dataPreprocessing(node,name+"."+node.title); + dataPreprocessing(node, name + "." + node.title); }) } dataService.monitorMetricsTree().success(function(data) { - angular.forEach(data,function(node){ - dataPreprocessing(node,node.title); + angular.forEach(data, function(node) { + dataPreprocessing(node, node.title); }); $scope.metricsTree = data; $scope.loading++; }).error(function(response) { // TODO }); - /*$scope.metrics = []; - dataService.monitorMetrics().success(function(data) { - $scope.metrics = data; - }).error(function(response) { - // TODO - });*/ + $scope.metricsName = []; dataService.monitorMetricsName().success(function(data) { $scope.metricsName = data; @@ -161,25 +159,35 @@ define(['angularAnimate', 'angularUiTree', 'nvd3Directive','ngSpinner'], functio $scope.metricsData = []; $scope.metricsDataKey = []; + /*==== ui tree draw graph ====*/ $scope.generate = function(node) { - var checked = $scope.metricsDataKey.indexOf(node.id) > -1? false: true; + var checked = $scope.metricsDataKey.indexOf(node.id) > -1 ? false : true; if (checked) { - dataService.monitorClusterMetric(clusterId, node.id).success(function(data) { - $scope.metricsData.push(data); - $scope.metricsDataKey.push(data.key); - }).error(function(response) { - // TODO - }); - } else{ + var selected = node.id; + var index = metricsFactory.addSelectedMetrics(selected); //store the initial query + + var query = metricsFactory.getSelectedMetricsQuery(index); + var clusterId = $stateParams.id; + dataService.monitorMetricsQuery(clusterId, query).success(function(data) { + var index = metricsFactory.addDisplayData(data); + $scope.metricsData.push(metricsFactory.getDisplayData(index)); + $scope.metricsDataKey.push(selected); // show selected on both multi-selection and ui-tree + }).error(function(response) { + // TODO + }); + + } else { + metricsFactory.removeSelectedMetrics(node.id); var index = $scope.metricsDataKey.indexOf(node.id); $scope.metricsData.splice(index, 1); $scope.metricsDataKey.splice(index, 1); - } + } + }; - $scope.isChecked = function(node){ - return $scope.metricsDataKey.indexOf(node.id) > -1? true: false; + $scope.isChecked = function(node) { + return $scope.metricsDataKey.indexOf(node.id) > -1 ? true : false; } // For Angular UI Tree @@ -215,8 +223,8 @@ define(['angularAnimate', 'angularUiTree', 'nvd3Directive','ngSpinner'], functio } }; - $scope.yAxisTickFormatFunction = function(){ - return function(d){ + $scope.yAxisTickFormatFunction = function() { + return function(d) { return d3.format(',d')(d); } }; @@ -229,6 +237,21 @@ define(['angularAnimate', 'angularUiTree', 'nvd3Directive','ngSpinner'], functio } }; + $scope.changeTimeRange = function() { + metricsFactory.setStartRelative($scope.start_relative); + + metricsFactory.setEndRelative($scope.end_relative); + var clusterId = $stateParams.id; + for (var i = 0; i < metricsFactory.getSelectedSize(); i++) { + var query = metricsFactory.getSelectedMetricsQuery(i); + console.log(query); + dataService.monitorMetricsQuery(clusterId, query).success(function(data) { + var index = metricsFactory.updateDisplayData(data); + }).error(function(response) { + // TODO + }); + } + }; /* // customize stack/line chart colors $scope.colorFunction = function() { @@ -239,32 +262,56 @@ define(['angularAnimate', 'angularUiTree', 'nvd3Directive','ngSpinner'], functio } */ }); - monitoringModule.directive('multiSelect', function($filter, dataService, $stateParams) {   + + // this is the helper function to find index for a target object in an array + var findTargetIndex = function(container, target) { + var index = -1; + var count = 0; + + angular.forEach(container, function(t) { + if (t.key == target) { + index = count; + } + count++; + }); + if (index > -1) + return index; + return -1; + }; + monitoringModule.directive('multiSelect', function($filter, dataService, $modal, $stateParams, metricsFactory) {   return { templateUrl: "src/app/monitoring/multiSelect.tpl.html", scope: { - metricsData: "=metricsdata", + metricsData: "=metricsdata", //metricsData is the data that show on the graph names: "=allnames", metricsDataKey: "=metricsdatakey" }, link: function(scope, elem, attrs) { + var selected = ""; // set focus on input text area $(".chosen-choices").click(function(event) { event.stopPropagation(); - $(".search-field > input").focus(); - $(".chosen-container").addClass("chosen-with-drop chosen-container-active"); + if(event.target.nodeName != "A") + { + $(".search-field > input").focus(); + $(".chosen-container").addClass("chosen-with-drop chosen-container-active"); + } scope.$apply(); }); // select one and put it in input area $(".chosen-results").on("click", "li.active-result", function() { var clusterId = $stateParams.id; - var selected = $(this).text(); - dataService.monitorClusterMetric(clusterId, selected).success(function(data) { - console.log(data); - scope.metricsData.push(data); - scope.metricsDataKey.push(data.key); + selected = $(this).text(); + + var index = metricsFactory.addSelectedMetrics(selected); //store the initial query + + var query = metricsFactory.getSelectedMetricsQuery(index); + dataService.monitorMetricsQuery(clusterId, query).success(function(data) { + var index = metricsFactory.addDisplayData(data); + scope.metricsData.push(metricsFactory.getDisplayData(index)); + scope.metricsDataKey.push(selected); // show selected on both multi-selection and ui-tree }).error(function(response) { // TODO }); @@ -273,25 +320,128 @@ define(['angularAnimate', 'angularUiTree', 'nvd3Directive','ngSpinner'], functio scope.searchText = ""; scope.$apply(); }); - //hight light + + //high light $(".chosen-results").on('mouseenter', 'li.active-result', function() { $(this).addClass("highlighted"); }).on('mouseleave', 'li', function() { $(this).removeClass("highlighted"); }); // remove the selected one - scope.removeSelected = function(target){ + scope.removeSelected = function(target) { + metricsFactory.removeSelectedMetrics(target.data); var index = scope.metricsDataKey.indexOf(target.data); scope.metricsData.splice(index, 1); - scope.metricsDataKey.splice(index,1); + scope.metricsDataKey.splice(index, 1); }; //hide options when a user clicks other places $(document).click(function(e) { $(".chosen-container").removeClass("chosen-with-drop chosen-container-active"); }); + scope.filter = function(target) { + var modalInstance = $modal.open({ + templateUrl: 'filter.html', + controller: 'metricsModalInstanceCtrl', + resolve: { + tags: function($q, dataService) { + var deferred = $q.defer(); + var clusterId = $stateParams.id; + dataService.monitorMetricsTagName(clusterId, target.data).success(function(data) { + deferred.resolve(data.queries[0].results[0].tags); + }).error(function(response) { + // TODO + }); + return deferred.promise; + }, + metricsName: function() { + return target.data; + } + } + }); + }; }   }; }); + monitoringModule.controller('metricsModalInstanceCtrl', function($rootScope, $scope, $modalInstance,$stateParams, tags, metricsName, metricsFactory, dataService) { -}); + $scope.groups = ["tag", "time", "value"]; + $scope.timeUnit = ["milliseconds","seconds","minutes", "hours", "days", "months", "years"]; + $scope.aggregatorTypes = ["avg", "dev", "div","min", "max", "rate", "sampler", "sum", "scale", "count", "least_squares","percentile"]; + + + $scope.allTags = []; + $scope.displayTags = tags; + + var index = metricsFactory.getIndex(metricsName); + $scope.metrics = metricsFactory.getSelectedMetricsQuery(index).metrics; + if (!jQuery.isEmptyObject($scope.metrics[0].tags)) { + angular.forEach($scope.metrics[0].tags, function(value, key) { + console.log(value) + angular.forEach(value, function(v) { + var temp = {}; + temp.selectedTag = key; + temp.tagValue = v; + $scope.allTags.push(temp); + }); + }); + } + $scope.addGroup = function() { + if (!$scope.metrics[0].group_by) { + $scope.metrics[0].group_by = []; + } + $scope.metrics[0].group_by.push({}); + }; + $scope.removeGroup = function(index) { + $scope.metrics[0].group_by.splice(index, 1); + }; + $scope.addAggregator = function() { + $scope.metrics[0].aggregators.push({}); + }; + $scope.removeAggregator = function(index) { + $scope.metrics[0].aggregators.splice(index, 1); + } + $scope.addTag = function() { + $scope.allTags.push({}); + }; + $scope.removeTag = function(index) { + $scope.allTags.splice(index, 1); + } + $scope.ok = function() { + $scope.metrics[0].tags = {}; + angular.forEach($scope.allTags, function(tag) { + if (!$scope.metrics[0].tags[tag.selectedTag]) { + $scope.metrics[0].tags[tag.selectedTag] = []; + } + $scope.metrics[0].tags[tag.selectedTag].push(tag.tagValue); + }); + var index = metricsFactory.getIndex(metricsName); + var query = metricsFactory.getSelectedMetricsQuery(index); + var clusterId = $stateParams.id; + dataService.monitorMetricsQuery(clusterId,query).success(function(data) { + var index = metricsFactory.updateDisplayData(data); + }).error(function(response) { + // TODO + }); + $modalInstance.close(); + }; + $scope.cleanGroupBy = function(index) { + var temp = $scope.metrics[0].group_by[index].name; + $scope.metrics[0].group_by[index] = {}; + $scope.metrics[0].group_by[index].name = temp; + }; + $scope.cheanAggregator = function(index){ + var temp = $scope.metrics[0].aggregators[index].name; + $scope.metrics[0].aggregators[index]= {}; + if(temp != "div" && temp != "rate" && temp != "sampler" && temp !="scale") + { + $scope.metrics[0].aggregators[index].align_sampling = true; + } + $scope.metrics[0].aggregators[index].name= temp; + }; + $scope.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + }); + +}); \ No newline at end of file diff --git a/v2/src/app/monitoring/multiSelect.tpl.html b/v2/src/app/monitoring/multiSelect.tpl.html index bceb228..0a940ea 100644 --- a/v2/src/app/monitoring/multiSelect.tpl.html +++ b/v2/src/app/monitoring/multiSelect.tpl.html @@ -1,8 +1,9 @@
    -
  • +
  • {{data}} - + +
  • @@ -15,4 +16,151 @@
  • Showing {{filtered.length}} records
-
\ No newline at end of file +
+ + \ No newline at end of file diff --git a/v2/src/app/services.js b/v2/src/app/services.js index b3f8aa9..6401030 100644 --- a/v2/src/app/services.js +++ b/v2/src/app/services.js @@ -50,6 +50,10 @@ define(['angular','uiBootstrap'], function(ng, uiBootstrap) { return $http.get(settings.metadataUrlBase + '/adapter_config'); }; + // this.getMetricsQuery = function() { + // return $http.get(settings.metadataUrlBase + '/metrics.json'); + // }; + this.getAllMachineHosts = function(os) { if (os) { return $http.get(settings.apiUrlBase + '/switches-machines-hosts?os_id=' + os); @@ -241,6 +245,14 @@ define(['angular','uiBootstrap'], function(ng, uiBootstrap) { return $http.get(settings.monitoringUrlBase + '/metricnames'); }; + this.monitorMetricsTagName = function(id, selectedMetrics) { + var metrics = '{"metrics":[{"tags":{},"name":"'+selectedMetrics+'"}],"cache_time":0,"start_absolute":0}'; + return $http.post(settings.monitoringUrlBase + '/clusters/'+ id +'/datapointtags',metrics); + }; + this.monitorMetricsQuery = function(clusterId,query) { + return $http.post(settings.monitoringUrlBase + '/clusters/'+clusterId+'/datapoints',query); + }; + this.monitorMetricsTree = function() { // This will also order the metrics in a tree // /monit/api/metricstree @@ -328,7 +340,149 @@ define(['angular','uiBootstrap'], function(ng, uiBootstrap) { }; }); + servicesModule.factory('metricsFactory', ['dataService', + function(dataService) { + var metrics = {}; + metrics.init = function() { + metrics.selectedMetrics = []; + metrics.selectedMetricsQuery = []; + metrics.displayData = []; + + metrics.start_relative = { + value: "1", + unit: "hours" + }; + metrics.end_relative = { + value: null, + unit: null + }; + + metrics.selectedSize = 0; + }; + + metrics.init(); + + metrics.getIndex = function(metricsName) { + for (var i = 0; i < metrics.selectedMetrics.length; i++) { + if (metrics.selectedMetrics[i] == metricsName) { + return i; + } + } + }; + + metrics.getSelectedSize = function() { + return this.selectedSize; + }; + + /* ================ relative time ====================*/ + metrics.setStartRelative = function(new_start_relative) { + metrics.start_relative.value = new_start_relative.value; + metrics.start_relative.unit = new_start_relative.unit; + }; + + metrics.setEndRelative = function(new_end_relative) { + if(new_end_relative) + { + console.log(new_end_relative) + metrics.end_relative.value = new_end_relative.value; + metrics.end_relative.unit = new_end_relative.unit; + } + }; + + /* ================= selected Metrics ================*/ + metrics.addSelectedMetrics = function(metricsName) { + metrics.selectedMetrics.push(metricsName); + metrics.addSelectedMetricsQuery(metricsName); + metrics.selectedSize++; + return metrics.selectedMetrics.length - 1; + }; + metrics.removeSelectedMetrics = function(metricsName) { + for (var i = 0; i < metrics.selectedMetrics.length; i++) { + if (metrics.selectedMetrics[i] == metricsName) { + metrics.selectedMetrics.splice(i, 1); + metrics.removeSelectedMetricsQuery(i); + metrics.removeDisplayData(i); + metrics.selectedSize--; + } + } + } + /* ============== selected Metrics Query ===============*/ + metrics.addSelectedMetricsQuery = function(metricsName) { + var query = { + metrics: [{ + tags: {}, + name: "", + aggregators: [{ + name: "sum", + align_sampling: true, + sampling: { + value: "1", + unit: "milliseconds" + } + }] + }], + cache_time: 0, + start_relative: { + value: "1", + unit: "hours" + } + }; + query.start_relative = metrics.start_relative; + if (metrics.end_relative.value != null && metrics.end_relative.unit != null) { + query.end_relative = metrics.end_relative; + } + query.metrics[0].name = metricsName; + metrics.selectedMetricsQuery.push(query); + }; + + metrics.removeSelectedMetricsQuery = function(index) { + metrics.selectedMetricsQuery.splice(index, 1); + }; + metrics.updateStartRelativeInQuery = function(index) { + if (metrics.end_relative.value != null && metrics.end_relative.unit != null) { + this.selectedMetricsQuery[index].end_relative = metrics.end_relative; + } else if (this.selectedMetricsQuery[index].end_relative) { + delete this.selectedMetricsQuery[index].end_relative; + } + + }; + metrics.getSelectedMetricsQuery = function(index) { + this.updateStartRelativeInQuery(index); + return metrics.selectedMetricsQuery[index]; + }; + + /* ================== display data on the char ====================*/ + metrics.addDisplayData = function(data) { + var tempObj = {}; + tempObj.key = data.queries[0].results[0].name; + tempObj.values = data.queries[0].results[0].values; + metrics.displayData.push(tempObj); + return metrics.displayData.length - 1; + }; + metrics.updateDisplayData = function(data) { + if(data.errors) + { + alert(data.errors[0]); + return -1; + } + var index = metrics.getIndex(data.queries[0].results[0].name); + metrics.displayData[index].values = data.queries[0].results[0].values; + return index; + + }; + metrics.getDisplayData = function(index) { + return metrics.displayData[index]; + }; + metrics.removeDisplayData = function(index) { + metrics.displayData.splice(index, 1); + }; + + return metrics; + + + } + ]); servicesModule.factory('wizardFactory', [ function() { diff --git a/v2/src/main.js b/v2/src/main.js index 43facd9..ad3da1e 100644 --- a/v2/src/main.js +++ b/v2/src/main.js @@ -104,11 +104,11 @@ require.config({ exports: "moment" }, "daterangepicker": { - deps: ["twitterBootstrap", "angular", "moment"], + deps: ["twitterBootstrap", "moment"], exports: "daterangepicker" }, "ngBsDaterangepicker": { - deps: ["daterangepicker"], + deps: ["moment","daterangepicker", "angular"], exports: "ngBsDaterangepicker" } },