From 3de4707c983aa379249f07318b5c01725f78d2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 29 Oct 2015 14:05:05 +0100 Subject: [PATCH] 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 --- CHANGELOG.md | 3 ++- .../features/annotations/annotationsSrv.js | 12 ++++++---- public/app/panels/graph/module.js | 2 +- public/app/plugins/PLUGIN_CHANGES.md | 6 +++++ .../datasource/elasticsearch/datasource.js | 24 ++++++++++++++----- .../partials/annotations.editor.html | 2 +- .../plugins/datasource/graphite/datasource.js | 16 ++++++------- .../plugins/datasource/influxdb/datasource.js | 8 +++---- .../datasource/influxdb_08/datasource.js | 8 +++---- .../influxdb_08/specs/datasource-specs.ts | 2 +- 10 files changed, 53 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ff1f10a8b4..c5729e24f96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # 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) diff --git a/public/app/features/annotations/annotationsSrv.js b/public/app/features/annotations/annotationsSrv.js index 89c9b72ec1f..f131ad28393 100644 --- a/public/app/features/annotations/annotationsSrv.js +++ b/public/app/features/annotations/annotationsSrv.js @@ -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); diff --git a/public/app/panels/graph/module.js b/public/app/panels/graph/module.js index 5cdeab799de..1cbd59f8a18 100644 --- a/public/app/panels/graph/module.js +++ b/public/app/panels/graph/module.js @@ -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) { diff --git a/public/app/plugins/PLUGIN_CHANGES.md b/public/app/plugins/PLUGIN_CHANGES.md index 5627af4a706..b79a0b65948 100644 --- a/public/app/plugins/PLUGIN_CHANGES.md +++ b/public/app/plugins/PLUGIN_CHANGES.md @@ -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 diff --git a/public/app/plugins/datasource/elasticsearch/datasource.js b/public/app/plugins/datasource/elasticsearch/datasource.js index 374fc9da90d..6c216713368 100644 --- a/public/app/plugins/datasource/elasticsearch/datasource.js +++ b/public/app/plugins/datasource/elasticsearch/datasource.js @@ -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; } diff --git a/public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html b/public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html index dae7d2bdeba..637ae78ada7 100644 --- a/public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html +++ b/public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html @@ -1,5 +1,5 @@
-
+
Index name
diff --git a/public/app/plugins/datasource/graphite/datasource.js b/public/app/plugins/datasource/graphite/datasource.js index f9e747fb984..8362412fd55 100644 --- a/public/app/plugins/datasource/graphite/datasource.js +++ b/public/app/plugins/datasource/graphite/datasource.js @@ -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, diff --git a/public/app/plugins/datasource/influxdb/datasource.js b/public/app/plugins/datasource/influxdb/datasource.js index b8ee9b15d49..8460a0c1d0d 100644 --- a/public/app/plugins/datasource/influxdb/datasource.js +++ b/public/app/plugins/datasource/influxdb/datasource.js @@ -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(); }); }; diff --git a/public/app/plugins/datasource/influxdb_08/datasource.js b/public/app/plugins/datasource/influxdb_08/datasource.js index a5058db3eb6..3ed12ac2d08 100644 --- a/public/app/plugins/datasource/influxdb_08/datasource.js +++ b/public/app/plugins/datasource/influxdb_08/datasource.js @@ -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(); }); }; diff --git a/public/app/plugins/datasource/influxdb_08/specs/datasource-specs.ts b/public/app/plugins/datasource/influxdb_08/specs/datasource-specs.ts index c4ea81759e8..46459939828 100644 --- a/public/app/plugins/datasource/influxdb_08/specs/datasource-specs.ts +++ b/public/app/plugins/datasource/influxdb_08/specs/datasource-specs.ts @@ -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(); });