mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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
This commit is contained in:
parent
cdcffcd31e
commit
3de4707c98
@ -1,7 +1,8 @@
|
|||||||
# 2.5.1 (unreleased)
|
# 2.5.1 (unreleased)
|
||||||
|
|
||||||
### Enhancements
|
### 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
|
### Bug Fixes
|
||||||
* **dashboard**: fix for collapse row by clicking on row title, fixes [#3065](https://github.com/grafana/grafana/issues/3065)
|
* **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');
|
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 promiseCached;
|
||||||
var list = [];
|
var list = [];
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.init = function() {
|
this.init = function() {
|
||||||
$rootScope.onAppEvent('refresh', this.clearCache, $rootScope);
|
$rootScope.onAppEvent('refresh', this.clearCache, $rootScope);
|
||||||
$rootScope.onAppEvent('setup-dashboard', this.clearCache, $rootScope);
|
$rootScope.onAppEvent('dashboard-loaded', this.clearCache, $rootScope);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.clearCache = function() {
|
this.clearCache = function() {
|
||||||
@ -22,7 +22,7 @@ define([
|
|||||||
list = [];
|
list = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getAnnotations = function(rangeUnparsed, dashboard) {
|
this.getAnnotations = function(dashboard) {
|
||||||
if (dashboard.annotations.list.length === 0) {
|
if (dashboard.annotations.list.length === 0) {
|
||||||
return $q.when(null);
|
return $q.when(null);
|
||||||
}
|
}
|
||||||
@ -34,9 +34,13 @@ define([
|
|||||||
self.dashboard = dashboard;
|
self.dashboard = dashboard;
|
||||||
var annotations = _.where(dashboard.annotations.list, {enable: true});
|
var annotations = _.where(dashboard.annotations.list, {enable: true});
|
||||||
|
|
||||||
|
var range = timeSrv.timeRange();
|
||||||
|
var rangeRaw = timeSrv.timeRange(false);
|
||||||
|
|
||||||
var promises = _.map(annotations, function(annotation) {
|
var promises = _.map(annotations, function(annotation) {
|
||||||
return datasourceSrv.get(annotation.datasource).then(function(datasource) {
|
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(self.receiveAnnotationResults)
|
||||||
.then(null, errorHandler);
|
.then(null, errorHandler);
|
||||||
}, this);
|
}, this);
|
||||||
|
@ -129,7 +129,7 @@ function (angular, $, _, kbn, moment, TimeSeries, PanelMeta) {
|
|||||||
$scope.refreshData = function(datasource) {
|
$scope.refreshData = function(datasource) {
|
||||||
panelHelper.updateTimeRange($scope);
|
panelHelper.updateTimeRange($scope);
|
||||||
|
|
||||||
$scope.annotationsPromise = annotationsSrv.getAnnotations($scope.rangeRaw, $scope.dashboard);
|
$scope.annotationsPromise = annotationsSrv.getAnnotations($scope.dashboard);
|
||||||
|
|
||||||
return panelHelper.issueMetricQuery($scope, datasource)
|
return panelHelper.issueMetricQuery($scope, datasource)
|
||||||
.then($scope.dataHandler, function(err) {
|
.then($scope.dataHandler, function(err) {
|
||||||
|
@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
## Changelog
|
## 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
|
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
|
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
|
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) {
|
ElasticDatasource.prototype.annotationQuery = function(options) {
|
||||||
var range = {};
|
var annotation = options.annotation;
|
||||||
var timeField = annotation.timeField || '@timestamp';
|
var timeField = annotation.timeField || '@timestamp';
|
||||||
var queryString = annotation.query || '*';
|
var queryString = annotation.query || '*';
|
||||||
var tagsField = annotation.tagsField || 'tags';
|
var tagsField = annotation.tagsField || 'tags';
|
||||||
var titleField = annotation.titleField || 'desc';
|
var titleField = annotation.titleField || 'desc';
|
||||||
var textField = annotation.textField || null;
|
var textField = annotation.textField || null;
|
||||||
|
|
||||||
|
var range = {};
|
||||||
range[timeField]= {
|
range[timeField]= {
|
||||||
from: rangeUnparsed.from,
|
from: options.range.from.valueOf(),
|
||||||
to: rangeUnparsed.to,
|
to: options.range.to.valueOf(),
|
||||||
};
|
};
|
||||||
|
|
||||||
var queryInterpolated = templateSrv.replace(queryString);
|
var queryInterpolated = templateSrv.replace(queryString);
|
||||||
@ -82,9 +83,20 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
|
|||||||
"size": 10000
|
"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 list = [];
|
||||||
var hits = results.data.hits.hits;
|
var hits = res.responses[0].hits.hits;
|
||||||
|
|
||||||
var getFieldFromSource = function(source, fieldName) {
|
var getFieldFromSource = function(source, fieldName) {
|
||||||
if (!fieldName) { return; }
|
if (!fieldName) { return; }
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="editor-row">
|
<div class="editor-row">
|
||||||
<div class="section">
|
<div class="section" ng-if="currentAnnotation.index">
|
||||||
<h5>Index name</h5>
|
<h5>Index name</h5>
|
||||||
<div class="editor-option">
|
<div class="editor-option">
|
||||||
<input type="text" class="span4" ng-model='currentAnnotation.index' placeholder="events-*"></input>
|
<input type="text" class="span4" ng-model='currentAnnotation.index' placeholder="events-*"></input>
|
||||||
|
@ -70,12 +70,12 @@ function (angular, _, $, config, dateMath) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
GraphiteDatasource.prototype.annotationQuery = function(annotation, rangeUnparsed) {
|
GraphiteDatasource.prototype.annotationQuery = function(options) {
|
||||||
// Graphite metric as annotation
|
// Graphite metric as annotation
|
||||||
if (annotation.target) {
|
if (options.annotation.target) {
|
||||||
var target = templateSrv.replace(annotation.target);
|
var target = templateSrv.replace(options.annotation.target);
|
||||||
var graphiteQuery = {
|
var graphiteQuery = {
|
||||||
rangeRaw: rangeUnparsed,
|
rangeRaw: options.rangeRaw,
|
||||||
targets: [{ target: target }],
|
targets: [{ target: target }],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
maxDataPoints: 100
|
maxDataPoints: 100
|
||||||
@ -93,7 +93,7 @@ function (angular, _, $, config, dateMath) {
|
|||||||
if (!datapoint[0]) { continue; }
|
if (!datapoint[0]) { continue; }
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
annotation: annotation,
|
annotation: options.annotation,
|
||||||
time: datapoint[1],
|
time: datapoint[1],
|
||||||
title: target.target
|
title: target.target
|
||||||
});
|
});
|
||||||
@ -105,15 +105,15 @@ function (angular, _, $, config, dateMath) {
|
|||||||
}
|
}
|
||||||
// Graphite event as annotation
|
// Graphite event as annotation
|
||||||
else {
|
else {
|
||||||
var tags = templateSrv.replace(annotation.tags);
|
var tags = templateSrv.replace(options.annotation.tags);
|
||||||
return this.events({ range: rangeUnparsed, tags: tags })
|
return this.events({range: options.rangeRaw, tags: tags})
|
||||||
.then(function(results) {
|
.then(function(results) {
|
||||||
var list = [];
|
var list = [];
|
||||||
for (var i = 0; i < results.data.length; i++) {
|
for (var i = 0; i < results.data.length; i++) {
|
||||||
var e = results.data[i];
|
var e = results.data[i];
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
annotation: annotation,
|
annotation: options.annotation,
|
||||||
time: e.when * 1000,
|
time: e.when * 1000,
|
||||||
title: e.what,
|
title: e.what,
|
||||||
tags: e.tags,
|
tags: e.tags,
|
||||||
|
@ -77,16 +77,16 @@ function (angular, _, dateMath, InfluxSeries, InfluxQueryBuilder) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
InfluxDatasource.prototype.annotationQuery = function(annotation, rangeUnparsed) {
|
InfluxDatasource.prototype.annotationQuery = function(options) {
|
||||||
var timeFilter = getTimeFilter({ rangeRaw: rangeUnparsed });
|
var timeFilter = getTimeFilter({rangeRaw: options.rangeRaw});
|
||||||
var query = annotation.query.replace('$timeFilter', timeFilter);
|
var query = options.annotation.query.replace('$timeFilter', timeFilter);
|
||||||
query = templateSrv.replace(query);
|
query = templateSrv.replace(query);
|
||||||
|
|
||||||
return this._seriesQuery(query).then(function(data) {
|
return this._seriesQuery(query).then(function(data) {
|
||||||
if (!data || !data.results || !data.results[0]) {
|
if (!data || !data.results || !data.results[0]) {
|
||||||
throw { message: 'No results in response from InfluxDB' };
|
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) {
|
InfluxDatasource.prototype.annotationQuery = function(options) {
|
||||||
var timeFilter = getTimeFilter({ rangeRaw: rangeUnparsed });
|
var timeFilter = getTimeFilter({rangeRaw: options.rangeRaw});
|
||||||
var query = annotation.query.replace('$timeFilter', timeFilter);
|
var query = options.annotation.query.replace('$timeFilter', timeFilter);
|
||||||
query = templateSrv.replace(query);
|
query = templateSrv.replace(query);
|
||||||
|
|
||||||
return this._seriesQuery(query).then(function(results) {
|
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');
|
return str.replace('$server', 'backend_01');
|
||||||
};
|
};
|
||||||
ctx.$httpBackend.expect('GET', urlExpected).respond(response);
|
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();
|
ctx.$httpBackend.flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user