Elastic search annotations are working, need to refactor and unify datasource abstraction more, #201

This commit is contained in:
Torkel Ödegaard 2014-07-29 17:24:42 +02:00
parent 4e47447dec
commit fa3b84a615
11 changed files with 126 additions and 9 deletions

View File

@ -12,6 +12,7 @@
- [Issue #610](https://github.com/grafana/grafana/issues/610). InfluxDB: Support for InfluxdB v0.8 list series response schemea (series typeahead)
- [Issue #266](https://github.com/grafana/grafana/issues/266). Graphite: New option cacheTimeout to override graphite default memcache timeout
- [Issue #606](https://github.com/grafana/grafana/issues/606). General: New global option in config.js to specify admin password (useful to hinder users from accidentally make changes)
- [Issue #201](https://github.com/grafana/grafana/issues/201). Annotations: Elasticsearch datasource support for events
**Changes**
- [Issue #536](https://github.com/grafana/grafana/issues/536). Graphite: Use unix epoch for Graphite from/to for absolute time ranges

View File

@ -12,7 +12,7 @@ function (angular, app, _) {
var module = angular.module('grafana.panels.annotations', []);
app.useModule(module);
module.controller('AnnotationsEditorCtrl', function($scope, datasourceSrv, $rootScope) {
module.controller('AnnotationsEditorCtrl', function($scope, datasourceSrv) {
var annotationDefaults = {
name: '',

View File

@ -27,7 +27,7 @@
<li ng-show="dashboard.loader.save_elasticsearch">
<form class="input-prepend nomargin save-dashboard-dropdown-save-form">
<input class='input-medium' ng-model="dashboard.title" type="text" ng-model="elasticsearch.title"/>
<input class='input-medium' ng-model="dashboard.title" type="text" />
<button class="btn" ng-click="saveDashboard()"><i class="icon-save"></i></button>
</form>
</li>

View File

@ -1 +1,39 @@
<h2>Elasticsearch</h2>
<div class="editor-row">
<div class="section">
<h5>Index name</h5>
<div class="editor-option">
<input type="text" class="span4" ng-model='currentAnnotation.index' placeholder="events-*"></input>
</div>
</div>
<div class="section">
<h5>Search query (lucene) <tip>Use [[filterName]] in query to replace part of the query with a filter value</h5>
<div class="editor-option">
<input type="text" class="span6" ng-model='currentAnnotation.query' placeholder="tags:deploy"></input>
</div>
</div>
</div>
<div class="editor-row">
<div class="section">
<h5>Field mappings</h5>
<div class="editor-option">
<label class="small">Time</label>
<input type="text" class="input-small" ng-model='currentAnnotation.timeField' placeholder="@timestamp"></input>
</div>
<div class="editor-option">
<label class="small">Title</label>
<input type="text" class="input-small" ng-model='currentAnnotation.titleField' placeholder="desc"></input>
</div>
<div class="editor-option">
<label class="small">Tags</label>
<input type="text" class="input-small" ng-model='currentAnnotation.tagsField' placeholder="tags"></input>
</div>
<div class="editor-option">
<label class="small">Text</label>
<input type="text" class="input-small" ng-model='currentAnnotation.textField' placeholder=""></input>
</div>
</div>
</div>

View File

@ -64,7 +64,7 @@ define([
function addAnnotation(options) {
var tooltip = "<small><b>" + options.title + "</b><br/>";
if (options.tags) {
tooltip += (options.tags || '') + '<br/>';
tooltip += '<span class="tag label label-tag">' + (options.tags || '') + '</span><br/>';
}
if (timezone === 'browser') {

View File

@ -19,10 +19,87 @@ function (angular, _, $, config, kbn, moment) {
this.url = datasource.url;
this.name = datasource.name;
this.supportAnnotations = true;
this.index = datasource.index;
this.annotationEditorSrc = 'app/partials/elasticsearch/annotation_editor.html';
}
ElasticDatasource.prototype._request = function(method, url, data) {
var options = {
url: this.url + "/" + this.index + url,
method: method,
data: data
};
if (config.elasticsearchBasicAuth) {
options.headers = {
"Authorization": "Basic " + config.elasticsearchBasicAuth
};
}
return $http(options);
};
ElasticDatasource.prototype._get = function(url) {
return this._request('GET', url)
.then(function(results) {
return results.data;
});
};
ElasticDatasource.prototype._post = function(url, data) {
return this._request('POST', url, data)
.then(function(results) {
return results.data;
});
};
ElasticDatasource.prototype.annotationQuery = function(annotation, filterSrv, rangeUnparsed) {
var range = {};
var timeField = annotation.timeField || '@timestamp';
var queryString = annotation.query || '*';
var tagsField = annotation.tagsField || 'tags';
var titleField = annotation.titleField || 'desc';
var textField = annotation.textField || null;
range[annotation.timeField]= {
from: rangeUnparsed.from,
to: rangeUnparsed.to,
};
var filter = { "bool": { "must": [{ "range": range }] } };
var query = { "bool": { "should": [{ "query_string": { "query": queryString } }] } };
var data = { "query" : { "filtered": { "query" : query, "filter": filter } }, "size": 100 };
this.index = annotation.index;
return this._request('POST', '/_search', data).then(function(results) {
var list = [];
var hits = results.data.hits.hits;
for (var i = 0; i < hits.length; i++) {
var source = hits[i]._source;
var event = {
annotation: annotation,
time: moment.utc(source[timeField]).valueOf(),
title: source[titleField],
};
if (source[tagsField]) {
if (_.isArray(source[tagsField])) {
event.tags = source[tagsField].join(', ');
}
else {
event.tags = source[tagsField];
}
}
if (textField && source[textField]) {
event.text = source[textField];
}
list.push(event);
}
return list;
});
};
return ElasticDatasource;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -128,4 +128,6 @@
}
}
.annotation-tags {
color: @purple;
}

View File

@ -12,7 +12,6 @@ module.exports = function(config) {
'app/routes/**/*.js',
'app/app.js',
'vendor/angular/**/*.js',
'vendor/elasticjs/elastic-angular-client.js'
],
dest: '<%= tempDir %>'
}