mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Elasticsearch: Add generic support for template variables (#32762)
* Elasticsearch: Add generic support for template variables * format MovingAverage settings as numbers * Move formatting logic to query builder & forma serial_diff settings as numbers * modify presence check * add todo * minor fixes * transform string values to numbers * Move casting logic * Slightly cleaner implementation * Add BE tests * Leverage elastic validation when string doesn't resolve to a numeric value * move newly introduced test to testify * add FE query_builder tests * check error * Parse values to float instead of int * Fix tests & ParseFloat bit size
This commit is contained in:
@@ -164,7 +164,7 @@ func (e *timeSeriesQuery) processQuery(q *Query, ms *es.MultiSearchRequestBuilde
|
||||
}
|
||||
|
||||
aggBuilder.Pipeline(m.ID, m.Type, bucketPath, func(a *es.PipelineAggregation) {
|
||||
a.Settings = m.Settings.MustMap()
|
||||
a.Settings = m.generateSettingsForDSL()
|
||||
})
|
||||
}
|
||||
} else {
|
||||
@@ -181,6 +181,31 @@ func (e *timeSeriesQuery) processQuery(q *Query, ms *es.MultiSearchRequestBuilde
|
||||
return nil
|
||||
}
|
||||
|
||||
// Casts values to int when required by Elastic's query DSL
|
||||
func (metricAggregation MetricAgg) generateSettingsForDSL() map[string]interface{} {
|
||||
setFloatPath := func(path ...string) {
|
||||
if stringValue, err := metricAggregation.Settings.GetPath(path...).String(); err == nil {
|
||||
if value, err := strconv.ParseFloat(stringValue, 64); err == nil {
|
||||
metricAggregation.Settings.SetPath(path, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch metricAggregation.Type {
|
||||
case "moving_avg":
|
||||
setFloatPath("window")
|
||||
setFloatPath("predict")
|
||||
setFloatPath("settings", "alpha")
|
||||
setFloatPath("settings", "beta")
|
||||
setFloatPath("settings", "gamma")
|
||||
setFloatPath("settings", "period")
|
||||
case "serial_diff":
|
||||
setFloatPath("lag")
|
||||
}
|
||||
|
||||
return metricAggregation.Settings.MustMap()
|
||||
}
|
||||
|
||||
func addDateHistogramAgg(aggBuilder es.AggBuilder, bucketAgg *BucketAgg, timeFrom, timeTo string) es.AggBuilder {
|
||||
aggBuilder.DateHistogram(bucketAgg.ID, bucketAgg.Field, func(a *es.DateHistogramAgg, b es.AggBuilder) {
|
||||
a.Interval = bucketAgg.Settings.Get("interval").MustString("auto")
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
|
||||
"github.com/grafana/grafana/pkg/tsdb/interval"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
@@ -856,6 +857,83 @@ func TestExecuteTimeSeriesQuery(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestSettingsCasting(t *testing.T) {
|
||||
from := time.Date(2018, 5, 15, 17, 50, 0, 0, time.UTC)
|
||||
to := time.Date(2018, 5, 15, 17, 55, 0, 0, time.UTC)
|
||||
|
||||
t.Run("Correctly transforms moving_average settings", func(t *testing.T) {
|
||||
c := newFakeClient(5)
|
||||
_, err := executeTsdbQuery(c, `{
|
||||
"timeField": "@timestamp",
|
||||
"bucketAggs": [
|
||||
{ "type": "date_histogram", "field": "@timestamp", "id": "2" }
|
||||
],
|
||||
"metrics": [
|
||||
{ "id": "1", "type": "average", "field": "@value" },
|
||||
{
|
||||
"id": "3",
|
||||
"type": "moving_avg",
|
||||
"field": "1",
|
||||
"pipelineAgg": "1",
|
||||
"settings": {
|
||||
"model": "holt_winters",
|
||||
"window": "10",
|
||||
"predict": "5",
|
||||
"settings": {
|
||||
"alpha": "0.5",
|
||||
"beta": "0.7",
|
||||
"gamma": "SHOULD NOT CHANGE",
|
||||
"period": "4"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}`, from, to, 15*time.Second)
|
||||
assert.Nil(t, err)
|
||||
sr := c.multisearchRequests[0].Requests[0]
|
||||
|
||||
movingAvgSettings := sr.Aggs[0].Aggregation.Aggs[1].Aggregation.Aggregation.(*es.PipelineAggregation).Settings
|
||||
|
||||
assert.Equal(t, 10., movingAvgSettings["window"])
|
||||
assert.Equal(t, 5., movingAvgSettings["predict"])
|
||||
|
||||
modelSettings := movingAvgSettings["settings"].(map[string]interface{})
|
||||
|
||||
assert.Equal(t, .5, modelSettings["alpha"])
|
||||
assert.Equal(t, .7, modelSettings["beta"])
|
||||
assert.Equal(t, "SHOULD NOT CHANGE", modelSettings["gamma"])
|
||||
assert.Equal(t, 4., modelSettings["period"])
|
||||
})
|
||||
|
||||
t.Run("Correctly transforms serial_diff settings", func(t *testing.T) {
|
||||
c := newFakeClient(5)
|
||||
_, err := executeTsdbQuery(c, `{
|
||||
"timeField": "@timestamp",
|
||||
"bucketAggs": [
|
||||
{ "type": "date_histogram", "field": "@timestamp", "id": "2" }
|
||||
],
|
||||
"metrics": [
|
||||
{ "id": "1", "type": "average", "field": "@value" },
|
||||
{
|
||||
"id": "3",
|
||||
"type": "serial_diff",
|
||||
"field": "1",
|
||||
"pipelineAgg": "1",
|
||||
"settings": {
|
||||
"lag": "1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}`, from, to, 15*time.Second)
|
||||
assert.Nil(t, err)
|
||||
sr := c.multisearchRequests[0].Requests[0]
|
||||
|
||||
serialDiffSettings := sr.Aggs[0].Aggregation.Aggs[1].Aggregation.Aggregation.(*es.PipelineAggregation).Settings
|
||||
|
||||
assert.Equal(t, 1., serialDiffSettings["lag"])
|
||||
})
|
||||
}
|
||||
|
||||
type fakeClient struct {
|
||||
version int
|
||||
timeField string
|
||||
|
||||
Reference in New Issue
Block a user