diff --git a/public/app/plugins/datasource/cloudwatch/queryCtrl.js b/public/app/plugins/datasource/cloudwatch/queryCtrl.js index e0835002692..ee63e317c55 100644 --- a/public/app/plugins/datasource/cloudwatch/queryCtrl.js +++ b/public/app/plugins/datasource/cloudwatch/queryCtrl.js @@ -19,17 +19,9 @@ function (angular, _) { $scope.target.region = $scope.target.region || $scope.datasource.getDefaultRegion(); $scope.target.errors = validateTarget(); - $scope.regionSegment = $scope.getSegmentForValue($scope.target.region, 'select region'); - $scope.namespaceSegment = $scope.getSegmentForValue($scope.target.namespace, 'select namespace'); - $scope.metricSegment = $scope.getSegmentForValue($scope.target.metricName, 'select metric'); - }; - - $scope.getSegmentForValue = function(value, fallbackText) { - if (value) { - return uiSegmentSrv.newSegment(value); - } else { - return uiSegmentSrv.newSegment({value: fallbackText, fake: true}); - } + $scope.regionSegment = uiSegmentSrv.getSegmentForValue($scope.target.region, 'select region'); + $scope.namespaceSegment = uiSegmentSrv.getSegmentForValue($scope.target.namespace, 'select namespace'); + $scope.metricSegment = uiSegmentSrv.getSegmentForValue($scope.target.metricName, 'select metric'); }; $scope.getRegions = function() { diff --git a/public/app/plugins/datasource/elasticsearch/datasource.js b/public/app/plugins/datasource/elasticsearch/datasource.js index 8f72dea25e9..49a51d63ae5 100644 --- a/public/app/plugins/datasource/elasticsearch/datasource.js +++ b/public/app/plugins/datasource/elasticsearch/datasource.js @@ -138,13 +138,21 @@ function (angular, _, config, kbn, moment, ElasticQueryBuilder) { var queryBuilder = new ElasticQueryBuilder; var query = queryBuilder.build(options.targets); query = query.replace(/\$interval/g, options.interval); - query = query.replace(/\$rangeFrom/g, options.range.from); - query = query.replace(/\$rangeTo/g, options.range.to); + query = query.replace(/\$rangeFrom/g, this.translateTime(options.range.from)); + query = query.replace(/\$rangeTo/g, this.translateTime(options.range.to)); query = query.replace(/\$maxDataPoints/g, options.maxDataPoints); query = templateSrv.replace(query, options.scopedVars); return this._post('/_search?search_type=count', query).then(this._getTimeSeries); }; + ElasticDatasource.prototype.translateTime = function(date) { + if (_.isString(date)) { + return date; + } + + return date.toJSON(); + }; + ElasticDatasource.prototype._getTimeSeries = function(results) { var _aggregation2timeSeries = function(aggregation) { var datapoints = aggregation.date_histogram.buckets.map(function(entry) { @@ -169,6 +177,26 @@ function (angular, _, config, kbn, moment, ElasticQueryBuilder) { return { data: data }; }; + ElasticDatasource.prototype.metricFindQuery = function(query) { + var region; + var namespace; + var metricName; + + var transformSuggestData = function(suggestData) { + return _.map(suggestData, function(v) { + return { text: v }; + }); + }; + + var d = $q.defer(); + + var regionQuery = query.match(/^region\(\)/); + if (regionQuery) { + d.resolve(transformSuggestData(this.performSuggestRegion())); + return d.promise; + } + }; + return ElasticDatasource; }); }); diff --git a/public/app/plugins/datasource/elasticsearch/partials/query.editor.html b/public/app/plugins/datasource/elasticsearch/partials/query.editor.html index b7ec5b75488..7767e58ab82 100644 --- a/public/app/plugins/datasource/elasticsearch/partials/query.editor.html +++ b/public/app/plugins/datasource/elasticsearch/partials/query.editor.html @@ -37,32 +37,12 @@ - - - - -
- - -
@@ -71,14 +51,11 @@
@@ -87,11 +64,7 @@
    -
  • - -
  • - -
  • +
  • Term
  • diff --git a/public/app/plugins/datasource/elasticsearch/queryBuilder.js b/public/app/plugins/datasource/elasticsearch/queryBuilder.js index 86f48005a05..dd24daa6746 100644 --- a/public/app/plugins/datasource/elasticsearch/queryBuilder.js +++ b/public/app/plugins/datasource/elasticsearch/queryBuilder.js @@ -3,52 +3,55 @@ define([ function () { 'use strict'; - function ElasticQueryBuilder() { - } + function ElasticQueryBuilder() { } ElasticQueryBuilder.prototype.build = function(targets) { var query = { "aggs": {}, "size": "$maxDataPoints" }; + var self = this; - targets.forEach(function(target) { - if (!target.hide) { - query["aggs"][target.termKey + "_" + target.termValue] = { - "filter": { - "and": [ - self._buildRangeFilter(target), - self._buildTermFilter(target) - ] - }, - "aggs": { + targets.forEach(function(target, index) { + if (target.hide) { + return; + } + + var esQuery = { + "filter": { + "and": [ + self._buildRangeFilter(target) + ] + }, + "aggs": { + "date_histogram": { "date_histogram": { - "date_histogram": { - "interval": target.interval || "$interval", - "field": target.keyField, - "min_doc_count": 0, - }, - "aggs": { + "interval": target.interval || "$interval", + "field": target.timestampField, + "min_doc_count": 0, + }, + "aggs": { + "stats": { "stats": { - "stats": { - "field": target.valueField - } + "field": target.valueField } } } } - }; - if (target.groupByField) { - query["aggs"][target.termKey + "_" + target.termValue]["aggs"] = { - "terms": { - "terms": { - "field": target.groupByField - }, - "aggs": query["aggs"][target.termKey + "_" + target.termValue]["aggs"] - } - }; } + }; + if (target.groupByField) { + query["aggs"][target.termKey + "_" + target.termValue]["aggs"] = { + "terms": { + "terms": { + "field": target.groupByField + }, + "aggs": query["aggs"][target.termKey + "_" + target.termValue]["aggs"] + } + }; } + + query["aggs"]['query:' + index] = esQuery; }); query = JSON.stringify(query); return query; @@ -56,7 +59,7 @@ function () { ElasticQueryBuilder.prototype._buildRangeFilter = function(target) { var filter = {"range":{}}; - filter["range"][target.keyField] = { + filter["range"][target.timestampField] = { "gte": "$rangeFrom", "lte": "$rangeTo" }; diff --git a/public/app/plugins/datasource/elasticsearch/queryCtrl.js b/public/app/plugins/datasource/elasticsearch/queryCtrl.js index e5f47d95ce5..35d89c931a8 100644 --- a/public/app/plugins/datasource/elasticsearch/queryCtrl.js +++ b/public/app/plugins/datasource/elasticsearch/queryCtrl.js @@ -8,7 +8,7 @@ function (angular, _, ElasticQueryBuilder) { var module = angular.module('grafana.controllers'); - module.controller('ElasticQueryCtrl', function($scope, $timeout, $sce, templateSrv, $q) { + module.controller('ElasticQueryCtrl', function($scope, $timeout, uiSegmentSrv, templateSrv, $q) { $scope.functionList = ['count', 'min', 'max', 'total', 'mean']; @@ -17,63 +17,40 @@ function (angular, _, ElasticQueryBuilder) { }); $scope.init = function() { - var target = $scope.target; - target.function = target.function || 'mean'; - $scope.queryBuilder = new ElasticQueryBuilder(target); - if (!target.keyField) { - target.keyField = '@timestamp'; - } - $scope.keyFieldSegment = new MetricSegment({value: target.keyField}); + var target = $scope.target; + target.function = target.function || 'mean'; + target.timestampField = target.timestampField || '@timestamp'; + target.valueField = target.valueField || 'value' ; - if (!target.valueField) { - target.valueField = 'metric'; - } - $scope.valueFieldSegment = new MetricSegment({value: target.valueField}); + $scope.timestampSegment = uiSegmentSrv.newSegment(target.timestampField); + $scope.valueFieldSegment = uiSegmentSrv.newSegment(target.valueField); - if (!target.termKey) { - target.termKey = 'service.raw'; - } - $scope.termKeySegment = new MetricSegment({value: target.termKey}); + $scope.termKeySegment = uiSegmentSrv.getSegmentForValue(target.termKey, 'select term field'); + $scope.termValueSegment = uiSegmentSrv.getSegmentForValue(target.termValue, 'select term value'); + $scope.groupByFieldSegment = uiSegmentSrv.getSegmentForValue(target.groupByField, 'add group by'); + }; - if (!target.termValue) { - target.termValue = 'cpu-average/cpu-user'; - } - $scope.termValueSegment = new MetricSegment({value: target.termValue}); + $scope.getFields = function() { + return $scope.datasource.metricFindQuery('fields()') + .then($scope.transformToSegments(true)); + }; - if (!target.groupByField) { - target.groupByField = 'host.raw'; - } - $scope.groupByFieldSegment = new MetricSegment({value: target.groupByField}); + $scope.transformToSegments = function(addTemplateVars) { + return function(results) { + var segments = _.map(results, function(segment) { + return uiSegmentSrv.newSegment({ value: segment.text, expandable: segment.expandable }); + }); - if (!target.measurement) { - $scope.measurementSegment = MetricSegment.newSelectMeasurement(); - } else { - $scope.measurementSegment = new MetricSegment(target.measurement); - } - - $scope.tagSegments = []; - _.each(target.tags, function(tag) { - if (tag.condition) { - $scope.tagSegments.push(MetricSegment.newCondition(tag.condition)); + if (addTemplateVars) { + _.each(templateSrv.variables, function(variable) { + segments.unshift(uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true })); + }); } - $scope.tagSegments.push(new MetricSegment({value: tag.key, type: 'key', cssClass: 'query-segment-key' })); - $scope.tagSegments.push(new MetricSegment.newOperator("=")); - $scope.tagSegments.push(new MetricSegment({value: tag.value, type: 'value', cssClass: 'query-segment-value'})); - }); - $scope.fixTagSegments(); - - $scope.groupBySegments = []; - _.each(target.groupByTags, function(tag) { - $scope.groupBySegments.push(new MetricSegment(tag)); - }); - - $scope.groupBySegments.push(MetricSegment.newPlusButton()); - - $scope.removeTagFilterSegment = new MetricSegment({fake: true, value: '-- remove tag filter --'}); - $scope.removeGroupBySegment = new MetricSegment({fake: true, value: '-- remove group by --'}); + return segments; + }; }; $scope.valueFieldChanged = function() { @@ -101,48 +78,11 @@ function (angular, _, ElasticQueryBuilder) { $scope.$parent.get_data(); }; - $scope.fixTagSegments = function() { - var count = $scope.tagSegments.length; - var lastSegment = $scope.tagSegments[Math.max(count-1, 0)]; - - if (!lastSegment || lastSegment.type !== 'plus-button') { - $scope.tagSegments.push(MetricSegment.newPlusButton()); - } - }; - - $scope.groupByTagUpdated = function(segment, index) { - if (segment.value === $scope.removeGroupBySegment.value) { - $scope.target.groupByTags.splice(index, 1); - $scope.groupBySegments.splice(index, 1); - $scope.$parent.get_data(); - return; - } - - if (index === $scope.groupBySegments.length-1) { - $scope.groupBySegments.push(MetricSegment.newPlusButton()); - } - - segment.type = 'group-by-key'; - segment.fake = false; - - $scope.target.groupByTags[index] = segment.value; - $scope.$parent.get_data(); - }; - $scope.changeFunction = function(func) { $scope.target.function = func; $scope.$parent.get_data(); }; - $scope.measurementChanged = function() { - $scope.target.measurement = $scope.measurementSegment.value; - $scope.$parent.get_data(); - }; - - $scope.toggleQueryMode = function () { - $scope.target.rawQuery = !$scope.target.rawQuery; - }; - $scope.handleQueryError = function(err) { $scope.parserError = err.message || 'Failed to issue metric query'; return []; diff --git a/public/app/services/uiSegmentSrv.js b/public/app/services/uiSegmentSrv.js index 492008b88c8..539808cb01e 100644 --- a/public/app/services/uiSegmentSrv.js +++ b/public/app/services/uiSegmentSrv.js @@ -32,6 +32,14 @@ function (angular, _) { this.html = options.html || $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value)); } + this.getSegmentForValue = function(value, fallbackText) { + if (value) { + return this.newSegment(value); + } else { + return this.newSegment({value: fallbackText, fake: true}); + } + }; + this.newSelectMeasurement = function() { return new MetricSegment({value: 'select measurement', fake: true}); };