mirror of https://github.com/grafana/grafana.git
feat(elasticsearch): worked on elasticsearch templating support, #2696
This commit is contained in:
parent
0ef8e086a2
commit
bc3c394210
|
|
@ -39,7 +39,7 @@ function (angular, _, queryDef) {
|
||||||
case 'date_histogram':
|
case 'date_histogram':
|
||||||
case 'terms': {
|
case 'terms': {
|
||||||
delete $scope.agg.query;
|
delete $scope.agg.query;
|
||||||
$scope.agg.type = 'select field';
|
$scope.agg.field = 'select field';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'filters': {
|
case 'filters': {
|
||||||
|
|
@ -120,6 +120,14 @@ function (angular, _, queryDef) {
|
||||||
$scope.orderByOptions = queryDef.getOrderByOptions($scope.target);
|
$scope.orderByOptions = queryDef.getOrderByOptions($scope.target);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.getFieldsInternal = function() {
|
||||||
|
if ($scope.agg.type === 'date_histogram') {
|
||||||
|
return $scope.getFields({$fieldType: 'date'});
|
||||||
|
} else {
|
||||||
|
return $scope.getFields();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$scope.addBucketAgg = function() {
|
$scope.addBucketAgg = function() {
|
||||||
// if last is date histogram add it before
|
// if last is date histogram add it before
|
||||||
var lastBucket = bucketAggs[bucketAggs.length - 1];
|
var lastBucket = bucketAggs[bucketAggs.length - 1];
|
||||||
|
|
@ -133,7 +141,7 @@ function (angular, _, queryDef) {
|
||||||
return parseInt(val.id) > max ? parseInt(val.id) : max;
|
return parseInt(val.id) > max ? parseInt(val.id) : max;
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
bucketAggs.splice(addIndex, 0, {type: "terms", field: "select field", id: (id+1).toString()});
|
bucketAggs.splice(addIndex, 0, {type: "terms", field: "select field", id: (id+1).toString(), fake: true});
|
||||||
$scope.onChange();
|
$scope.onChange();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
|
||||||
|
|
||||||
var module = angular.module('grafana.services');
|
var module = angular.module('grafana.services');
|
||||||
|
|
||||||
module.factory('ElasticDatasource', function($q, backendSrv, templateSrv) {
|
module.factory('ElasticDatasource', function($q, backendSrv, templateSrv, timeSrv) {
|
||||||
|
|
||||||
function ElasticDatasource(datasource) {
|
function ElasticDatasource(datasource) {
|
||||||
this.type = 'elasticsearch';
|
this.type = 'elasticsearch';
|
||||||
|
|
@ -168,7 +168,6 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
|
||||||
payload = payload.replace(/\$interval/g, options.interval);
|
payload = payload.replace(/\$interval/g, options.interval);
|
||||||
payload = payload.replace(/\$timeFrom/g, options.range.from.valueOf());
|
payload = payload.replace(/\$timeFrom/g, options.range.from.valueOf());
|
||||||
payload = payload.replace(/\$timeTo/g, options.range.to.valueOf());
|
payload = payload.replace(/\$timeTo/g, options.range.to.valueOf());
|
||||||
payload = payload.replace(/\$maxDataPoints/g, options.maxDataPoints);
|
|
||||||
payload = templateSrv.replace(payload, options.scopedVars);
|
payload = templateSrv.replace(payload, options.scopedVars);
|
||||||
|
|
||||||
return this._post('/_msearch?search_type=count', payload).then(function(res) {
|
return this._post('/_msearch?search_type=count', payload).then(function(res) {
|
||||||
|
|
@ -176,9 +175,17 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ElasticDatasource.prototype.metricFindQuery = function() {
|
ElasticDatasource.prototype.getFields = function(query) {
|
||||||
return this._get('/_mapping').then(function(res) {
|
return this._get('/_mapping').then(function(res) {
|
||||||
var fields = {};
|
var fields = {};
|
||||||
|
var typeMap = {
|
||||||
|
'float': 'number',
|
||||||
|
'double': 'number',
|
||||||
|
'integer': 'number',
|
||||||
|
'long': 'number',
|
||||||
|
'date': 'date',
|
||||||
|
'string': 'string',
|
||||||
|
};
|
||||||
|
|
||||||
for (var indexName in res) {
|
for (var indexName in res) {
|
||||||
var index = res[indexName];
|
var index = res[indexName];
|
||||||
|
|
@ -188,21 +195,53 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
|
||||||
var properties = mappings[typeName].properties;
|
var properties = mappings[typeName].properties;
|
||||||
for (var field in properties) {
|
for (var field in properties) {
|
||||||
var prop = properties[field];
|
var prop = properties[field];
|
||||||
|
if (query.type && typeMap[prop.type] !== query.type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (prop.type && field[0] !== '_') {
|
if (prop.type && field[0] !== '_') {
|
||||||
fields[field] = prop;
|
fields[field] = {text: field, type: prop.type};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fields = _.map(_.keys(fields), function(field) {
|
// transform to array
|
||||||
return {text: field};
|
return _.map(fields, function(value) {
|
||||||
|
return value;
|
||||||
});
|
});
|
||||||
|
|
||||||
return fields;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ElasticDatasource.prototype.getTerms = function(queryDef) {
|
||||||
|
var range = timeSrv.timeRange();
|
||||||
|
var header = this.getQueryHeader(range.from, range.to);
|
||||||
|
var esQuery = angular.toJson(this.queryBuilder.getTermsQuery(queryDef));
|
||||||
|
|
||||||
|
esQuery = esQuery.replace("$lucene_query", queryDef.query || '*');
|
||||||
|
esQuery = esQuery.replace(/\$timeFrom/g, range.from.valueOf());
|
||||||
|
esQuery = esQuery.replace(/\$timeTo/g, range.to.valueOf());
|
||||||
|
esQuery = header + '\n' + esQuery + '\n';
|
||||||
|
|
||||||
|
return this._post('/_msearch?search_type=count', esQuery).then(function(res) {
|
||||||
|
var buckets = res.responses[0].aggregations["1"].buckets;
|
||||||
|
return _.map(buckets, function(bucket) {
|
||||||
|
return {text: bucket.key, value: bucket.key};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ElasticDatasource.prototype.metricFindQuery = function(query) {
|
||||||
|
query = templateSrv.replace(query);
|
||||||
|
query = angular.fromJson(query);
|
||||||
|
|
||||||
|
if (query.find === 'fields') {
|
||||||
|
return this.getFields(query);
|
||||||
|
}
|
||||||
|
if (query.find === 'terms') {
|
||||||
|
return this.getTerms(query);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ElasticDatasource.prototype.getDashboard = function(id) {
|
ElasticDatasource.prototype.getDashboard = function(id) {
|
||||||
return this._get('/dashboard/' + id)
|
return this._get('/dashboard/' + id)
|
||||||
.then(function(result) {
|
.then(function(result) {
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,10 @@ function (angular, _, queryDef) {
|
||||||
$scope.onChange();
|
$scope.onChange();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.getFieldsInternal = function() {
|
||||||
|
return $scope.getFields({$fieldType: 'number'});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.addMetricAgg = function() {
|
$scope.addMetricAgg = function() {
|
||||||
var addIndex = metricAggs.length;
|
var addIndex = metricAggs.length;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="tight-form-item-large"></metric-segment-model>
|
<metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="tight-form-item-large"></metric-segment-model>
|
||||||
</li>
|
</li>
|
||||||
<li ng-if="agg.field">
|
<li ng-if="agg.field">
|
||||||
<metric-segment-model property="agg.field" get-options="getFields()" on-change="onChange()" css-class="tight-form-item-xxlarge"></metric-segment>
|
<metric-segment-model property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="tight-form-item-xxlarge"></metric-segment>
|
||||||
</li>
|
</li>
|
||||||
<li ng-if="!agg.field">
|
<li ng-if="!agg.field">
|
||||||
<span class="tight-form-item tight-form-item-xxlarge"> </span>
|
<span class="tight-form-item tight-form-item-xxlarge"> </span>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<metric-segment-model property="agg.type" options="metricAggTypes" on-change="onTypeChange()" custom="false" css-class="tight-form-item-large"></metric-segment-model>
|
<metric-segment-model property="agg.type" options="metricAggTypes" on-change="onTypeChange()" custom="false" css-class="tight-form-item-large"></metric-segment-model>
|
||||||
</li>
|
</li>
|
||||||
<li ng-if="agg.type !== 'count'">
|
<li ng-if="agg.type !== 'count'">
|
||||||
<metric-segment-model property="agg.field" get-options="getFields()" on-change="onChange()" css-class="tight-form-item-xxlarge"></metric-segment>
|
<metric-segment-model property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="tight-form-item-xxlarge"></metric-segment>
|
||||||
</li>
|
</li>
|
||||||
<li class="tight-form-item last" ng-if="settingsLinkText">
|
<li class="tight-form-item last" ng-if="settingsLinkText">
|
||||||
<a ng-click="toggleOptions()">{{settingsLinkText}}</a>
|
<a ng-click="toggleOptions()">{{settingsLinkText}}</a>
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
<div ng-repeat="agg in target.metrics">
|
<div ng-repeat="agg in target.metrics">
|
||||||
<elastic-metric-agg
|
<elastic-metric-agg
|
||||||
target="target" index="$index"
|
target="target" index="$index"
|
||||||
get-fields="getFields()"
|
get-fields="getFields($fieldType)"
|
||||||
on-change="queryUpdated()">
|
on-change="queryUpdated()">
|
||||||
</elastic-metric-agg>
|
</elastic-metric-agg>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
<div ng-repeat="agg in target.bucketAggs">
|
<div ng-repeat="agg in target.bucketAggs">
|
||||||
<elastic-bucket-agg
|
<elastic-bucket-agg
|
||||||
target="target" index="$index"
|
target="target" index="$index"
|
||||||
get-fields="getFields()"
|
get-fields="getFields($fieldType)"
|
||||||
on-change="queryUpdated()">
|
on-change="queryUpdated()">
|
||||||
</elastic-bucket-agg>
|
</elastic-bucket-agg>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,39 @@ function (angular) {
|
||||||
return query;
|
return query;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ElasticQueryBuilder.prototype.getTermsQuery = function(queryDef) {
|
||||||
|
var query = {
|
||||||
|
"size": 0,
|
||||||
|
"query": {
|
||||||
|
"filtered": {
|
||||||
|
"query": {
|
||||||
|
"query_string": {
|
||||||
|
"analyze_wildcard": true,
|
||||||
|
"query": '$lucene_query',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filter": {
|
||||||
|
"bool": {
|
||||||
|
"must": [{"range": this.getRangeFilter()}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
query.aggs = {
|
||||||
|
"1": {
|
||||||
|
"terms": {
|
||||||
|
"field": queryDef.field,
|
||||||
|
"order": {
|
||||||
|
"_term": "asc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return query;
|
||||||
|
};
|
||||||
|
|
||||||
return ElasticQueryBuilder;
|
return ElasticQueryBuilder;
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,9 @@ function (angular, _) {
|
||||||
target.timeField = $scope.datasource.timeField;
|
target.timeField = $scope.datasource.timeField;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.getFields = function() {
|
$scope.getFields = function(type) {
|
||||||
return $scope.datasource.metricFindQuery('fields()')
|
var jsonStr = angular.toJson({find: 'fields', type: type});
|
||||||
|
return $scope.datasource.metricFindQuery(jsonStr)
|
||||||
.then($scope.transformToSegments(false))
|
.then($scope.transformToSegments(false))
|
||||||
.then(null, $scope.handleQueryError);
|
.then(null, $scope.handleQueryError);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue