Commit 3de4707c by Torkel Ödegaard

feat(elasticsearch): Annotation queries now use the daily index patterns defined…

feat(elasticsearch): Annotation queries now use the daily index patterns defined in data source options, for old annotations that have an index property that will be used, so will not break existing dashboard/annotation configs, closes #3061
parent cdcffcd3
# 2.5.1 (unreleased)
### Enhancements
* **cloudwatch**: Support for multiple AWS Credentials, closes [#3053](https://github.com/grafana/grafana/issues/3053), [#3080](https://github.com/grafana/grafana/issues/3080)
* **CloudWatch**: Support for multiple AWS Credentials, closes [#3053](https://github.com/grafana/grafana/issues/3053), [#3080](https://github.com/grafana/grafana/issues/3080)
* **Elasticsearch**: Support for dynamic daily indices for annotations, closes [#3061](https://github.com/grafana/grafana/issues/3061)
### Bug Fixes
* **dashboard**: fix for collapse row by clicking on row title, fixes [#3065](https://github.com/grafana/grafana/issues/3065)
......
......@@ -7,14 +7,14 @@ define([
var module = angular.module('grafana.services');
module.service('annotationsSrv', function(datasourceSrv, $q, alertSrv, $rootScope) {
module.service('annotationsSrv', function($rootScope, $q, datasourceSrv, alertSrv, timeSrv) {
var promiseCached;
var list = [];
var self = this;
this.init = function() {
$rootScope.onAppEvent('refresh', this.clearCache, $rootScope);
$rootScope.onAppEvent('setup-dashboard', this.clearCache, $rootScope);
$rootScope.onAppEvent('dashboard-loaded', this.clearCache, $rootScope);
};
this.clearCache = function() {
......@@ -22,7 +22,7 @@ define([
list = [];
};
this.getAnnotations = function(rangeUnparsed, dashboard) {
this.getAnnotations = function(dashboard) {
if (dashboard.annotations.list.length === 0) {
return $q.when(null);
}
......@@ -34,9 +34,13 @@ define([
self.dashboard = dashboard;
var annotations = _.where(dashboard.annotations.list, {enable: true});
var range = timeSrv.timeRange();
var rangeRaw = timeSrv.timeRange(false);
var promises = _.map(annotations, function(annotation) {
return datasourceSrv.get(annotation.datasource).then(function(datasource) {
return datasource.annotationQuery(annotation, rangeUnparsed)
var query = {range: range, rangeRaw: rangeRaw, annotation: annotation};
return datasource.annotationQuery(query)
.then(self.receiveAnnotationResults)
.then(null, errorHandler);
}, this);
......
......@@ -129,7 +129,7 @@ function (angular, $, _, kbn, moment, TimeSeries, PanelMeta) {
$scope.refreshData = function(datasource) {
panelHelper.updateTimeRange($scope);
$scope.annotationsPromise = annotationsSrv.getAnnotations($scope.rangeRaw, $scope.dashboard);
$scope.annotationsPromise = annotationsSrv.getAnnotations($scope.dashboard);
return panelHelper.issueMetricQuery($scope, datasource)
.then($scope.dataHandler, function(err) {
......
......@@ -2,6 +2,12 @@
## Changelog
2.5.1
datasource annotationQuery changed. now single options parameter with:
- range
- rangeRaw
- annotation
2.5 changed the `range` parameter in the `datasource.query` function's options parameter. This
parameter now holds a parsed range with `moment` dates `form` and `to`. To get
millisecond epoc from a `moment` you the function `valueOf`. The raw date range as represented
......
......@@ -60,17 +60,18 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
});
};
ElasticDatasource.prototype.annotationQuery = function(annotation, rangeUnparsed) {
var range = {};
ElasticDatasource.prototype.annotationQuery = function(options) {
var annotation = options.annotation;
var timeField = annotation.timeField || '@timestamp';
var queryString = annotation.query || '*';
var tagsField = annotation.tagsField || 'tags';
var titleField = annotation.titleField || 'desc';
var textField = annotation.textField || null;
var range = {};
range[timeField]= {
from: rangeUnparsed.from,
to: rangeUnparsed.to,
from: options.range.from.valueOf(),
to: options.range.to.valueOf(),
};
var queryInterpolated = templateSrv.replace(queryString);
......@@ -82,9 +83,20 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
"size": 10000
};
return this._request('POST', annotation.index + '/_search', data).then(function(results) {
var header = {search_type: "query_then_fetch", "ignore_unavailable": true};
// old elastic annotations had index specified on them
if (annotation.index) {
header.index = annotation.index;
} else {
header.index = this.indexPattern.getIndexList(options.range.from, options.range.to);
}
var payload = angular.toJson(header) + '\n' + angular.toJson(data) + '\n';
return this._post('/_msearch', payload).then(function(res) {
var list = [];
var hits = results.data.hits.hits;
var hits = res.responses[0].hits.hits;
var getFieldFromSource = function(source, fieldName) {
if (!fieldName) { return; }
......
<div class="editor-row">
<div class="section">
<div class="section" ng-if="currentAnnotation.index">
<h5>Index name</h5>
<div class="editor-option">
<input type="text" class="span4" ng-model='currentAnnotation.index' placeholder="events-*"></input>
......
......@@ -70,12 +70,12 @@ function (angular, _, $, config, dateMath) {
return result;
};
GraphiteDatasource.prototype.annotationQuery = function(annotation, rangeUnparsed) {
GraphiteDatasource.prototype.annotationQuery = function(options) {
// Graphite metric as annotation
if (annotation.target) {
var target = templateSrv.replace(annotation.target);
if (options.annotation.target) {
var target = templateSrv.replace(options.annotation.target);
var graphiteQuery = {
rangeRaw: rangeUnparsed,
rangeRaw: options.rangeRaw,
targets: [{ target: target }],
format: 'json',
maxDataPoints: 100
......@@ -93,7 +93,7 @@ function (angular, _, $, config, dateMath) {
if (!datapoint[0]) { continue; }
list.push({
annotation: annotation,
annotation: options.annotation,
time: datapoint[1],
title: target.target
});
......@@ -105,15 +105,15 @@ function (angular, _, $, config, dateMath) {
}
// Graphite event as annotation
else {
var tags = templateSrv.replace(annotation.tags);
return this.events({ range: rangeUnparsed, tags: tags })
var tags = templateSrv.replace(options.annotation.tags);
return this.events({range: options.rangeRaw, tags: tags})
.then(function(results) {
var list = [];
for (var i = 0; i < results.data.length; i++) {
var e = results.data[i];
list.push({
annotation: annotation,
annotation: options.annotation,
time: e.when * 1000,
title: e.what,
tags: e.tags,
......
......@@ -77,16 +77,16 @@ function (angular, _, dateMath, InfluxSeries, InfluxQueryBuilder) {
});
};
InfluxDatasource.prototype.annotationQuery = function(annotation, rangeUnparsed) {
var timeFilter = getTimeFilter({ rangeRaw: rangeUnparsed });
var query = annotation.query.replace('$timeFilter', timeFilter);
InfluxDatasource.prototype.annotationQuery = function(options) {
var timeFilter = getTimeFilter({rangeRaw: options.rangeRaw});
var query = options.annotation.query.replace('$timeFilter', timeFilter);
query = templateSrv.replace(query);
return this._seriesQuery(query).then(function(data) {
if (!data || !data.results || !data.results[0]) {
throw { message: 'No results in response from InfluxDB' };
}
return new InfluxSeries({ series: data.results[0].series, annotation: annotation }).getAnnotations();
return new InfluxSeries({series: data.results[0].series, annotation: options.annotation}).getAnnotations();
});
};
......
......@@ -57,13 +57,13 @@ function (angular, _, dateMath, InfluxSeries, InfluxQueryBuilder) {
});
};
InfluxDatasource.prototype.annotationQuery = function(annotation, rangeUnparsed) {
var timeFilter = getTimeFilter({ rangeRaw: rangeUnparsed });
var query = annotation.query.replace('$timeFilter', timeFilter);
InfluxDatasource.prototype.annotationQuery = function(options) {
var timeFilter = getTimeFilter({rangeRaw: options.rangeRaw});
var query = options.annotation.query.replace('$timeFilter', timeFilter);
query = templateSrv.replace(query);
return this._seriesQuery(query).then(function(results) {
return new InfluxSeries({ seriesList: results, annotation: annotation }).getAnnotations();
return new InfluxSeries({seriesList: results, annotation: options.annotation}).getAnnotations();
});
};
......
......@@ -84,7 +84,7 @@ describe('InfluxDatasource', function() {
return str.replace('$server', 'backend_01');
};
ctx.$httpBackend.expect('GET', urlExpected).respond(response);
ctx.ds.annotationQuery(annotation, range).then(function(data) { results = data; });
ctx.ds.annotationQuery({annotation: annotation, rangeRaw: range}).then(function(data) { results = data; });
ctx.$httpBackend.flush();
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment