mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Elasticsearch: Adds support for region annotations (#17602)
It is now possible to specify a field containing time-end in Elasticsearch annotations. Any annotations with a time-end will become a region between time and time-end. Any annotations without the time-end field will remain a single-point annotation. Ref #10589
This commit is contained in:
committed by
Marcus Efraimsson
parent
16fa712b59
commit
66c6547e7c
@@ -180,6 +180,7 @@ Name | Description
|
|||||||
------------ | -------------
|
------------ | -------------
|
||||||
Query | You can leave the search query blank or specify a lucene query
|
Query | You can leave the search query blank or specify a lucene query
|
||||||
Time | The name of the time field, needs to be date field.
|
Time | The name of the time field, needs to be date field.
|
||||||
|
Time End | Optional name of the time end field, needs to be date field. If set, then annotations will be marked as a regions between time and time-end.
|
||||||
Text | Event description field.
|
Text | Event description field.
|
||||||
Tags | Optional field name to use for event tags (can be an array or a CSV string).
|
Tags | Optional field name to use for event tags (can be an array or a CSV string).
|
||||||
|
|
||||||
|
|||||||
@@ -119,22 +119,40 @@ export class ElasticDatasource extends DataSourceApi<ElasticsearchQuery, Elastic
|
|||||||
annotationQuery(options: any) {
|
annotationQuery(options: any) {
|
||||||
const annotation = options.annotation;
|
const annotation = options.annotation;
|
||||||
const timeField = annotation.timeField || '@timestamp';
|
const timeField = annotation.timeField || '@timestamp';
|
||||||
|
const timeEndField = annotation.timeEndField || null;
|
||||||
const queryString = annotation.query || '*';
|
const queryString = annotation.query || '*';
|
||||||
const tagsField = annotation.tagsField || 'tags';
|
const tagsField = annotation.tagsField || 'tags';
|
||||||
const textField = annotation.textField || null;
|
const textField = annotation.textField || null;
|
||||||
|
|
||||||
const range: any = {};
|
const dateRanges = [];
|
||||||
range[timeField] = {
|
const rangeStart: any = {};
|
||||||
|
rangeStart[timeField] = {
|
||||||
from: options.range.from.valueOf(),
|
from: options.range.from.valueOf(),
|
||||||
to: options.range.to.valueOf(),
|
to: options.range.to.valueOf(),
|
||||||
format: 'epoch_millis',
|
format: 'epoch_millis',
|
||||||
};
|
};
|
||||||
|
dateRanges.push({ range: rangeStart });
|
||||||
|
|
||||||
|
if (timeEndField) {
|
||||||
|
const rangeEnd: any = {};
|
||||||
|
rangeEnd[timeEndField] = {
|
||||||
|
from: options.range.from.valueOf(),
|
||||||
|
to: options.range.to.valueOf(),
|
||||||
|
format: 'epoch_millis',
|
||||||
|
};
|
||||||
|
dateRanges.push({ range: rangeEnd });
|
||||||
|
}
|
||||||
|
|
||||||
const queryInterpolated = this.templateSrv.replace(queryString, {}, 'lucene');
|
const queryInterpolated = this.templateSrv.replace(queryString, {}, 'lucene');
|
||||||
const query = {
|
const query = {
|
||||||
bool: {
|
bool: {
|
||||||
filter: [
|
filter: [
|
||||||
{ range: range },
|
{
|
||||||
|
bool: {
|
||||||
|
should: dateRanges,
|
||||||
|
minimum_should_match: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
query_string: {
|
query_string: {
|
||||||
query: queryInterpolated,
|
query: queryInterpolated,
|
||||||
@@ -201,13 +219,26 @@ export class ElasticDatasource extends DataSourceApi<ElasticsearchQuery, Elastic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = {
|
const event: {
|
||||||
|
annotation: any;
|
||||||
|
time: number;
|
||||||
|
timeEnd?: number;
|
||||||
|
text: string;
|
||||||
|
tags: string | string[];
|
||||||
|
} = {
|
||||||
annotation: annotation,
|
annotation: annotation,
|
||||||
time: toUtc(time).valueOf(),
|
time: toUtc(time).valueOf(),
|
||||||
text: getFieldFromSource(source, textField),
|
text: getFieldFromSource(source, textField),
|
||||||
tags: getFieldFromSource(source, tagsField),
|
tags: getFieldFromSource(source, tagsField),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (timeEndField) {
|
||||||
|
const timeEnd = getFieldFromSource(source, timeEndField);
|
||||||
|
if (timeEnd) {
|
||||||
|
event.timeEnd = toUtc(timeEnd).valueOf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// legacy support for title tield
|
// legacy support for title tield
|
||||||
if (annotation.titleField) {
|
if (annotation.titleField) {
|
||||||
const title = getFieldFromSource(source, annotation.titleField);
|
const title = getFieldFromSource(source, annotation.titleField);
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
<span class="gf-form-label">Time</span>
|
<span class="gf-form-label">Time</span>
|
||||||
<input type="text" class="gf-form-input max-width-14" ng-model='ctrl.annotation.timeField' placeholder="@timestamp"></input>
|
<input type="text" class="gf-form-input max-width-14" ng-model='ctrl.annotation.timeField' placeholder="@timestamp"></input>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<span class="gf-form-label">Time End</span>
|
||||||
|
<input type="text" class="gf-form-input max-width-14" ng-model='ctrl.annotation.timeEndField' placeholder=""></input>
|
||||||
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<span class="gf-form-label">Text</span>
|
<span class="gf-form-label">Text</span>
|
||||||
<input type="text" class="gf-form-input max-width-14" ng-model='ctrl.annotation.textField' placeholder=""></input>
|
<input type="text" class="gf-form-input max-width-14" ng-model='ctrl.annotation.textField' placeholder=""></input>
|
||||||
|
|||||||
Reference in New Issue
Block a user