Return-Path: X-Original-To: apmail-ambari-commits-archive@www.apache.org Delivered-To: apmail-ambari-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id F0D0F18BA9 for ; Thu, 4 Feb 2016 19:07:00 +0000 (UTC) Received: (qmail 70896 invoked by uid 500); 4 Feb 2016 19:06:57 -0000 Delivered-To: apmail-ambari-commits-archive@ambari.apache.org Received: (qmail 70866 invoked by uid 500); 4 Feb 2016 19:06:57 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 70857 invoked by uid 99); 4 Feb 2016 19:06:57 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 04 Feb 2016 19:06:57 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B4FEFE08E7; Thu, 4 Feb 2016 19:06:57 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: yusaku@apache.org To: commits@ambari.apache.org Message-Id: <45b8b8e8e9a946f6bdbf8c7c284838a4@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: ambari git commit: AMBARI-14893. Add Grafana-based Ambari Metrics Dashboard Builder. (Prajwal Rao via yusaku) Date: Thu, 4 Feb 2016 19:06:57 +0000 (UTC) Repository: ambari Updated Branches: refs/heads/branch-2.2 dc4c1cfbd -> df7ba1b1b AMBARI-14893. Add Grafana-based Ambari Metrics Dashboard Builder. (Prajwal Rao via yusaku) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/df7ba1b1 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/df7ba1b1 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/df7ba1b1 Branch: refs/heads/branch-2.2 Commit: df7ba1b1bf06ad21f321722f6055e39b35e98e40 Parents: dc4c1cf Author: Yusaku Sako Authored: Thu Feb 4 11:05:37 2016 -0800 Committer: Yusaku Sako Committed: Thu Feb 4 11:06:47 2016 -0800 ---------------------------------------------------------------------- ambari-metrics/ambari-metrics-grafana/README.md | 243 +++++++++++++++ .../ambari-metrics/datasource.js | 304 +++++++++++++++++++ .../ambari-metrics/directives.js | 36 +++ .../ambari-metrics/partials/config.html | 19 ++ .../ambari-metrics/partials/query.editor.html | 133 ++++++++ .../ambari-metrics/partials/query.options.html | 42 +++ .../ambari-metrics/plugin.json | 14 + .../ambari-metrics/queryCtrl.js | 131 ++++++++ ambari-metrics/pom.xml | 1 + 9 files changed, 923 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/df7ba1b1/ambari-metrics/ambari-metrics-grafana/README.md ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-grafana/README.md b/ambari-metrics/ambari-metrics-grafana/README.md new file mode 100644 index 0000000..0a138e8 --- /dev/null +++ b/ambari-metrics/ambari-metrics-grafana/README.md @@ -0,0 +1,243 @@ + +# AMS (Ambari Metrics Service) Datasource Plugin for Grafana + +Use **ambari-metrics** to visualize metrics exposed via AMS in Grafana. + +### If you already have Ambari Metrics UI as a part of your AMS Install, [go here](#createdash) to get started + + +**ToC** + - [Install Grafana](#installg) + - [Install Datasource Plugin](#installam) + - [Access Grafana](#accessgraf) + - [Add Datasource to Grafana](#addds) + - [Test Datasource](#testds) + - [Create Dashboard](#createdash) + - [Add a Graph](#addgraph) + - [Save Dashboard](#savedash) + - [Time Ranges](#timerange) + - [Edit Panel/Graph](#editpanel) + + +---------- +![enter image description here](screenshots/full-dashboard.png) + +---------- + +### Install Grafana + + +You can install Grafana on any host. It does not need to be co-located with Ambari Metrics Collector. The only requirement is that it has network access to Ambari Metrics Collector. + +**Install on CentOS/Red Hat:** +``` +sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-2.6.0-1.x86_64.rpm +``` + +**Install on Ubuntu/Debian:** +``` +wget https://grafanarel.s3.amazonaws.com/builds/grafana_2.6.0_amd64.deb +sudo apt-get install -y adduser libfontconfig +sudo dpkg -i grafana_2.6.0_amd64.deb +``` + +**Install on SUSE/SLES:** +``` +sudo rpm -i --nodeps grafana-2.6.0-1.x86_64.rpm +``` + +### Deploy ambari-metrics + +**On your Grafana Server** + +``` +cp -R ambari/ambari-metrics/ambari-metrics-grafana/ambari-metrics /usr/share/grafana/public/app/plugins/datasource +``` + +### Start Grafana + +``` +sudo service grafana-server start +``` + + +### Access Grafana + +``` +http://GRAFANA_HOST:3000 +``` + +--- + + +## Add Ambari Metrics Datasource in Grafana UI + +**Add a Datasource** +> - Click on "Datasources" +> - Click on "Add New" at the top + +![add-datasource](screenshots/1-add-datasource.png) + +**Add a Datasource (continued)** + +> 1. Name of your Datasource +> 2. Type = AmbariMetrics +> 3. Host+Port of your AMS installation. (usually host:6188) +> - No trailing slashes +> - Nothing else needs to be changed +> - Click on Save. + +![datasource-details](screenshots/2-datasource-details.png) + + + +**Test your Datasource** + +> To make sure it's all working, click on **Test Connection** and you should see a message that says "Data source is working". + + +![test-datasource](screenshots/3-test-datasource.png) + +--- + + +## Creating a Dashboard + +**To create a dashboard** + +> - Click on Dashboards on the left +> - Click on "Home" +> - Click on New at the bottom of the dropdown + +![Dashboard Dropdown](screenshots/4-dashboard-dropdown.png) + + + +**To add a panel to your newly created dashboard** + +> - Click on the green button on the left(see image below) +> - This will expand a flyout menu that will allow you to add a panel +> - Choose Graph / Table / Single Stat + +![Add Panel](screenshots/5-dashboard-graph-menu.png) + +![Types of Panels](screenshots/6-graph-panels.png) + + +--- + + +**To add a Graph** + + +> - Choose the Datasource you created earlier +> - Once you've chosen the datasource, you should see the query editor show you some options + +![Add a Graph](screenshots/7-choose-datasource.png) + + + +> - Choose the component you wish to see metrics for + +![Add a Graph](screenshots/8-choose-component.png) + + + +> - Based on the component chosen, you should now see a list of metrics for it + +![Add a Graph](screenshots/9-choose-metric.png) + + + +> - Choose hostname from the list of hosts if you wish to see metrics for a specific host. +> - if hostname isn't chosen, metrics will be shown on a service component level. + +![Add a Graph](screenshots/10-choose-hostname.png) + + +> - By default the aggregator is avg. You can change it via the dropdown +> - You can choose to enable Rate by selecting the checkbox. +> - You can specify precision by checking the box and then selecting "days, hours, minutes or seconds" + +![Select Options](screenshots/11-choose-agg-rate-precision.png) + + +**To change the title of the Panel** + +> - Click on the "General" tab +> - Enter the name to change the title of the panel + +![Change Panel Title](screenshots/12-change-panel-title.png) + +**To change the Units for your metric** + +> - You can edit the units of your graph by clicking on **Axes & Grid** tab and clicking on "unit" as shown. + +![Change Units](screenshots/15-change-units.png) + +**To customise your graphs** + +> - You can customise your graph by clicking on the **Display Styles** tab. +> - For ex: you can change the color of a specific metric by choosing a series specific override at the bottom. + +![series specific override](screenshots/17-series-specific-override.png) + + + +**To Save the Dashboard** + +> - Click on the save icon next to the dashboard list dropdown on the top to save your dashboard. + +![Save Dashboard](screenshots/13-save-dashboard.png) + + +**To Edit a Graph** + +> - Click on the title of your graph/panel and click on edit. + +![Edit Graph](screenshots/19-edit-graph.png) + + +--- + +### Time Ranges + +**To change the Time Range** + +> - To change the timerange click on the top right of your UI. +> - This setting affects all your graphs inside the dashboard. If you wish to customise time for a specific graph [look here](#timeshift) +> - You can use the quick ranges provided or choose a time range of your choice. You can also choose a refresh duration for your dashboard or leave it at "off" to manually refresh. + +![Timerange](screenshots/14-change-timerange.png) + + +**To change the time range of one graph only** + +> - Use this in case you wish to change the time range for a specific graph without affecting the other graphs in your dashboard +> - Click on the **Time Range** tab of your Graph +> - You can then enter a value in the "Override Relative time" input box +> - You will be able to confirm that this change has occured by looking at the top right of your graph which will show the override message. +> - You can choose to hide this message if you wish to do so (by checking the "hide time override info") + +![Timerange Override](screenshots/18-override-time.png) + + +--- + + http://git-wip-us.apache.org/repos/asf/ambari/blob/df7ba1b1/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js new file mode 100644 index 0000000..374501c --- /dev/null +++ b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js @@ -0,0 +1,304 @@ +/** + * 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. + */ +define([ + 'angular', + 'lodash', + 'jquery', + './directives', + './queryCtrl' + ], + function (angular, _) { + 'use strict'; + + var module = angular.module('grafana.services'); + + module.factory('AmbariMetricsDatasource', function ($q, backendSrv) { + /** + * AMS Datasource Constructor + */ + function AmbariMetricsDatasource(datasource) { + this.name = datasource.name; + this.url = datasource.url; + this.initMetricAppidMapping(); + } + var allMetrics = []; + var appIds = []; + AmbariMetricsDatasource.prototype.initMetricAppidMapping = function () { + backendSrv.get(this.url + '/ws/v1/timeline/metrics/metadata') + .then(function (items) { + allMetrics = []; + appIds = []; + var fake = "timeline_metric_store_watcher"; delete items[fake]; + for (var key in items) { + if (items.hasOwnProperty(key)) { + items[key].forEach(function (_item) { + allMetrics.push({ + metric: _item.metricname, + app: key + }); + }); + } + appIds = _.keys(items); + } + }); + }; + + /** + * AMS Datasource Authentication + */ + AmbariMetricsDatasource.prototype.doAmbariRequest = function (options) { + if (this.basicAuth || this.withCredentials) { + options.withCredentials = true; + } + if (this.basicAuth) { + options.headers = options.headers || {}; + options.headers.Authorization = this.basicAuth; + } + + options.url = this.url + options.url; + options.inspect = {type: 'discovery'}; + + return backendSrv.datasourceRequest(options); + }; + + /** + * AMS Datasource Query + */ + AmbariMetricsDatasource.prototype.query = function (options) { + var emptyData = function (metric) { + return { + data: { + target: metric, + datapoints: [] + } + }; + }; + var self = this; + var getMetricsData = function (target) { + return function (res) { + console.log('processing metric ' + target.metric); + if (!res.metrics[0] || target.hide) { + return $q.when(emptyData(target.metric)); + } + var series = []; + var metricData = res.metrics[0].metrics; + var timeSeries = {}; + if (target.hosts === undefined || target.hosts.trim() === "") { + timeSeries = { + target: target.metric, + datapoints: [] + }; + } else { + timeSeries = { + target: target.metric + ' on ' + target.hosts, + datapoints: [] + }; + } + for (var k in metricData){ + if (metricData.hasOwnProperty(k)) { + timeSeries.datapoints.push([metricData[k], (k - k % 1000)]); + } + } + series.push(timeSeries); + return $q.when({data: series}); + }; + + }; + var precisionSetting = ''; + var getHostAppIdData = function(target) { + if (target.shouldAddPrecision) { + precisionSetting = '&precision=' + target.precision; + } else { + precisionSetting = ''; + } + if (target.shouldAddPrecision && target.shouldComputeRate) { + return backendSrv.get(self.url + '/ws/v1/timeline/metrics?metricNames=' + target.metric + "._rate._" + + target.aggregator + "&hostname=" + target.hosts + '&appId=' + target.app + '&startTime=' + from + + '&endTime=' + to + precisionSetting).then( + getMetricsData(target) + ); + } else if (target.shouldComputeRate) { + return backendSrv.get(self.url + '/ws/v1/timeline/metrics?metricNames=' + target.metric + "._rate._" + + target.aggregator + "&hostname=" + target.hosts + '&appId=' + target.app + '&startTime=' + from + + '&endTime=' + to).then( + getMetricsData(target) + ); + } else if (target.shouldAddPrecision){ + return backendSrv.get(self.url + '/ws/v1/timeline/metrics?metricNames=' + target.metric + "._" + + target.aggregator + "&hostname=" + target.hosts + '&appId=' + target.app + '&startTime=' + from + + '&endTime=' + to + precisionSetting).then( + getMetricsData(target) + ); + } else { + return backendSrv.get(self.url + '/ws/v1/timeline/metrics?metricNames=' + target.metric + "._" + + target.aggregator + "&hostname=" + target.hosts + '&appId=' + target.app + '&startTime=' + from + + '&endTime=' + to).then( + getMetricsData(target) + ); + } + }; + + var getServiceAppIdData = function(target) { + if (target.shouldAddPrecision) { precisionSetting = '&precision=' + target.precision; + } else { precisionSetting = ''; } + if (target.shouldAddPrecision && target.shouldComputeRate) { + return backendSrv.get(self.url + '/ws/v1/timeline/metrics?metricNames=' + target.metric + "._rate._" + + target.aggregator + '&appId=' + target.app + '&startTime=' + from + '&endTime=' + to + precisionSetting) + .then( + getMetricsData(target) + ); + } else if (target.shouldAddPrecision) { + return backendSrv.get(self.url + '/ws/v1/timeline/metrics?metricNames=' + target.metric + "._" + + target.aggregator + '&appId=' + target.app + '&startTime=' + from + '&endTime=' + to + precisionSetting) + .then( + getMetricsData(target) + ); + } else if (target.shouldComputeRate) { + return backendSrv.get(self.url + '/ws/v1/timeline/metrics?metricNames=' + target.metric + "._rate._" + + target.aggregator + '&appId=' + target.app + '&startTime=' + from + '&endTime=' + to).then( + getMetricsData(target) + ); + } else { + return backendSrv.get(self.url + '/ws/v1/timeline/metrics?metricNames=' + target.metric + "._" + + target.aggregator + '&appId=' + target.app + '&startTime=' + from + '&endTime=' + to).then( + getMetricsData(target) + ); + } + }; + + // Time Ranges + var from = Math.floor(options.range.from.valueOf() / 1000); + var to = Math.floor(options.range.to.valueOf() / 1000); + + var metricsPromises = _.map(options.targets, function(target) { + console.debug('target app=' + target.app + ',' + + 'target metric=' + target.metric + ' on host=' + target.hosts); + if (!!target.hosts) { + return getHostAppIdData(target); + } else { + return getServiceAppIdData(target); + } + }); + return $q.all(metricsPromises).then(function(metricsDataArray) { + var data = _.map(metricsDataArray, function(metricsData) { + return metricsData.data; + }); + var metricsDataResult = {data: _.flatten(data)}; + return $q.when(metricsDataResult); + }); + }; + + /** + * AMS Datasource List Series. + */ + AmbariMetricsDatasource.prototype.listSeries = function (query) { + // wrap in regex + if (query && query.length > 0 && query[0] !== '/') { + query = '/' + query + '/'; + } + return $q.when([]); + }; + + /** + * AMS Datasource - Test Data Source Connection. + * + * Added Check to see if Datasource is working. Throws up an error in the + * Datasources page if incorrect info is passed on. + */ + AmbariMetricsDatasource.prototype.testDatasource = function () { + return backendSrv.datasourceRequest({ + url: this.url + '/ws/v1/timeline/metrics/metadata', + method: 'GET' + }).then(function(response) { + console.log(response); + if (response.status === 200) { + return { status: "success", message: "Data source is working", title: "Success" }; + } + }); + }; + + /** + * AMS Datasource - Suggest AppId. + * + * Read AppIds from cache. + */ + AmbariMetricsDatasource.prototype.suggestApps = function (query) { + console.log(query); + + appIds = appIds.sort(); + var appId = _.map(appIds, function (k) { + return {text: k}; + }); + return $q.when(appId); + }; + + /** + * AMS Datasource - Suggest Metrics. + * + * Read Metrics based on AppId chosen. + */ + AmbariMetricsDatasource.prototype.suggestMetrics = function (query, app) { + if (!app) { + return $q.when([]); + } + var metrics = allMetrics.filter(function(item) { + return (item.app === app); + }); + var keys = []; + _.forEach(metrics, function (k) { keys.push(k.metric); }); + keys = _.map(keys,function(m) { + return {text: m}; + }); + keys = _.sortBy(keys, function (i) { return i.text.toLowerCase(); }); + return $q.when(keys); + }; + + /** + * AMS Datasource - Suggest Hosts. + * + * Query Hosts on the cluster. + */ + AmbariMetricsDatasource.prototype.suggestHosts = function (query) { + console.log(query); + return this.doAmbariRequest({method: 'GET', url: '/ws/v1/timeline/metrics/hosts'}) + .then(function (results) { + var fake = "fakehostname"; delete results.data[fake]; + return _.map(Object.keys(results.data), function (hostName) { + return {text: hostName}; + }); + }); + }; + + /** + * AMS Datasource Aggregators. + */ + var aggregatorsPromise = null; + AmbariMetricsDatasource.prototype.getAggregators = function () { + if (aggregatorsPromise) { + return aggregatorsPromise; + } + aggregatorsPromise = $q.when([ + 'avg', 'sum', 'min', 'max' + ]); + return aggregatorsPromise; + }; + + return AmbariMetricsDatasource; + }); + } +); http://git-wip-us.apache.org/repos/asf/ambari/blob/df7ba1b1/ambari-metrics/ambari-metrics-grafana/ambari-metrics/directives.js ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/directives.js b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/directives.js new file mode 100644 index 0000000..aade7d7 --- /dev/null +++ b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/directives.js @@ -0,0 +1,36 @@ +/** + * 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. + */ + define([ + 'angular', +], +function (angular) { + 'use strict'; + var module = angular.module('grafana.directives'); + + module.directive('metricQueryEditorAmbarimetrics', function() { + return { + controller: 'AmbariMetricsQueryCtrl', + templateUrl: 'app/plugins/datasource/ambari-metrics/partials/query.editor.html', + }; + }); + + module.directive('metricQueryOptionsAmbarimetrics', function() { + return {templateUrl: 'app/plugins/datasource/ambari-metrics/partials/query.options.html'}; + }); + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/df7ba1b1/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/config.html ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/config.html b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/config.html new file mode 100644 index 0000000..360c15c --- /dev/null +++ b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/config.html @@ -0,0 +1,19 @@ + +
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/df7ba1b1/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/query.editor.html ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/query.editor.html b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/query.editor.html new file mode 100644 index 0000000..d4dffb4 --- /dev/null +++ b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/query.editor.html @@ -0,0 +1,133 @@ + +
+ + +
    +
  • + {{target.refId}} +
  • +
  • + + + +
  • +
+ + + +
+
+ +
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/df7ba1b1/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/query.options.html ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/query.options.html b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/query.options.html new file mode 100644 index 0000000..e58ca64 --- /dev/null +++ b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/partials/query.options.html @@ -0,0 +1,42 @@ + +
+
+ +
+
+
+ +
+
+
+
Single Stats
+
To get the current value of the metric selected, Click on the Options tab above + and set the Big Value's value to "current".
+
+
+
\ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/df7ba1b1/ambari-metrics/ambari-metrics-grafana/ambari-metrics/plugin.json ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/plugin.json b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/plugin.json new file mode 100644 index 0000000..5226ae7 --- /dev/null +++ b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/plugin.json @@ -0,0 +1,14 @@ +{ + "pluginType": "datasource", + "name": "AmbariMetrics", + + "type": "ambarimetrics", + "serviceName": "AmbariMetricsDatasource", + + "module": "app/plugins/datasource/ambari-metrics/datasource", + "partials": { + "config": "app/plugins/datasource/ambari-metrics/partials/config.html" + }, + + "metrics": true +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/df7ba1b1/ambari-metrics/ambari-metrics-grafana/ambari-metrics/queryCtrl.js ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/queryCtrl.js b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/queryCtrl.js new file mode 100644 index 0000000..d6e93a8 --- /dev/null +++ b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/queryCtrl.js @@ -0,0 +1,131 @@ +/** + * 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. + */ +define([ + 'angular', + 'lodash' + ], + function (angular, _) { + 'use strict'; + + var module = angular.module('grafana.controllers'); + + module.controller('AmbariMetricsQueryCtrl', function($scope) { + + $scope.init = function() { + $scope.target.errors = validateTarget($scope.target); + $scope.aggregators = ['avg', 'sum', 'min', 'max']; + $scope.precisions = ['seconds', 'minutes', 'hours', 'days']; + + if (!$scope.target.aggregator) { + $scope.target.aggregator = 'avg'; + } + + if (!$scope.target.downsampleAggregator) { + $scope.target.downsampleAggregator = 'avg'; + } + + $scope.datasource.getAggregators().then(function(aggs) { + $scope.aggregators = aggs; + }); + }; + + $scope.targetBlur = function() { + $scope.target.errors = validateTarget($scope.target); + + // this does not work so good + if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) { + $scope.oldTarget = angular.copy($scope.target); + $scope.get_data(); + } + }; + + $scope.getTextValues = function(metricFindResult) { + return _.map(metricFindResult, function(value) { return value.text; }); + }; + + $scope.suggestApps = function(query, callback) { + $scope.datasource.suggestApps(query) + .then($scope.getTextValues) + .then(callback); + }; + + $scope.suggestHosts = function(query, callback) { + $scope.datasource.suggestHosts(query) + .then($scope.getTextValues) + .then(callback); + }; + + $scope.suggestMetrics = function(query, callback) { + $scope.datasource.suggestMetrics(query, $scope.target.app) + .then($scope.getTextValues) + .then(callback); + }; + + $scope.suggestTagKeys = function(query, callback) { + $scope.datasource.metricFindQuery('tag_names(' + $scope.target.metric + ')') + .then($scope.getTextValues) + .then(callback); + }; + + $scope.suggestTagValues = function(query, callback) { + $scope.datasource.metricFindQuery('tag_values(' + $scope.target.metric + ',' + $scope.target.currentTagKey + ')') + .then($scope.getTextValues) + .then(callback); + }; + + $scope.addTag = function() { + if (!$scope.addTagMode) { + $scope.addTagMode = true; + return; + } + + if (!$scope.target.tags) { + $scope.target.tags = {}; + } + + $scope.target.errors = validateTarget($scope.target); + + if (!$scope.target.errors.tags) { + $scope.target.tags[$scope.target.currentTagKey] = $scope.target.currentTagValue; + $scope.target.currentTagKey = ''; + $scope.target.currentTagValue = ''; + $scope.targetBlur(); + } + + $scope.addTagMode = false; + }; + + $scope.removeTag = function(key) { + delete $scope.target.tags[key]; + $scope.targetBlur(); + }; + + function validateTarget(target) { + var errs = {}; + + if (target.tags && _.has(target.tags, target.currentTagKey)) { + errs.tags = "Duplicate tag key '" + target.currentTagKey + "'."; + } + + return errs; + } + + $scope.init(); + }); + + }); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/df7ba1b1/ambari-metrics/pom.xml ---------------------------------------------------------------------- diff --git a/ambari-metrics/pom.xml b/ambari-metrics/pom.xml index b3b4e87..8a10faf 100644 --- a/ambari-metrics/pom.xml +++ b/ambari-metrics/pom.xml @@ -263,6 +263,7 @@ pass.txt derby.log **/*.nuspec + **/*.json