mirror of https://github.com/grafana/grafana
Loki: alerting: handle variables like __interval and __range (#42126)
parent
ccd162f806
commit
24d4c8a9d1
@ -0,0 +1,75 @@ |
||||
package loki |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
"math" |
||||
"strconv" |
||||
"strings" |
||||
"time" |
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend" |
||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2" |
||||
) |
||||
|
||||
const ( |
||||
varInterval = "$__interval" |
||||
varIntervalMs = "$__interval_ms" |
||||
varRange = "$__range" |
||||
varRangeS = "$__range_s" |
||||
varRangeMs = "$__range_ms" |
||||
) |
||||
|
||||
func interpolateVariables(expr string, interval time.Duration, timeRange time.Duration) string { |
||||
intervalText := intervalv2.FormatDuration(interval) |
||||
intervalMsText := strconv.FormatInt(int64(interval/time.Millisecond), 10) |
||||
|
||||
rangeMs := timeRange.Milliseconds() |
||||
rangeSRounded := int64(math.Round(float64(rangeMs) / 1000.0)) |
||||
rangeMsText := strconv.FormatInt(rangeMs, 10) |
||||
rangeSText := strconv.FormatInt(rangeSRounded, 10) |
||||
|
||||
expr = strings.ReplaceAll(expr, varIntervalMs, intervalMsText) |
||||
expr = strings.ReplaceAll(expr, varInterval, intervalText) |
||||
expr = strings.ReplaceAll(expr, varRangeMs, rangeMsText) |
||||
expr = strings.ReplaceAll(expr, varRangeS, rangeSText) |
||||
expr = strings.ReplaceAll(expr, varRange, rangeSText+"s") |
||||
|
||||
return expr |
||||
} |
||||
|
||||
func parseQuery(dsInfo *datasourceInfo, queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) { |
||||
qs := []*lokiQuery{} |
||||
for _, query := range queryContext.Queries { |
||||
model := &ResponseModel{} |
||||
err := json.Unmarshal(query.JSON, model) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
start := query.TimeRange.From |
||||
end := query.TimeRange.To |
||||
|
||||
var resolution int64 = 1 |
||||
if model.Resolution >= 1 && model.Resolution <= 5 || model.Resolution == 10 { |
||||
resolution = model.Resolution |
||||
} |
||||
|
||||
interval := query.Interval |
||||
timeRange := query.TimeRange.To.Sub(query.TimeRange.From) |
||||
|
||||
step := calculateStep(interval, timeRange, resolution) |
||||
|
||||
expr := interpolateVariables(model.Expr, interval, timeRange) |
||||
|
||||
qs = append(qs, &lokiQuery{ |
||||
Expr: expr, |
||||
Step: step, |
||||
LegendFormat: model.LegendFormat, |
||||
Start: start, |
||||
End: end, |
||||
RefID: query.RefID, |
||||
}) |
||||
} |
||||
|
||||
return qs, nil |
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
package loki |
||||
|
||||
import ( |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend" |
||||
"github.com/stretchr/testify/require" |
||||
) |
||||
|
||||
func TestParseQuery(t *testing.T) { |
||||
t.Run("parsing query model", func(t *testing.T) { |
||||
queryContext := &backend.QueryDataRequest{ |
||||
Queries: []backend.DataQuery{ |
||||
{ |
||||
JSON: []byte(` |
||||
{ |
||||
"expr": "go_goroutines $__interval $__interval_ms $__range $__range_s $__range_ms", |
||||
"format": "time_series", |
||||
"refId": "A" |
||||
}`, |
||||
), |
||||
TimeRange: backend.TimeRange{ |
||||
From: time.Now().Add(-3000 * time.Second), |
||||
To: time.Now(), |
||||
}, |
||||
Interval: time.Second * 15, |
||||
MaxDataPoints: 200, |
||||
}, |
||||
}, |
||||
} |
||||
dsInfo := &datasourceInfo{} |
||||
models, err := parseQuery(dsInfo, queryContext) |
||||
require.NoError(t, err) |
||||
require.Equal(t, time.Second*15, models[0].Step) |
||||
require.Equal(t, "go_goroutines 15s 15000 3000s 3000 3000000", models[0].Expr) |
||||
}) |
||||
t.Run("interpolate variables, range between 1s and 0.5s", func(t *testing.T) { |
||||
expr := "go_goroutines $__interval $__interval_ms $__range $__range_s $__range_ms" |
||||
|
||||
interval := time.Millisecond * 50 |
||||
timeRange := time.Millisecond * 750 |
||||
|
||||
require.Equal(t, "go_goroutines 50ms 50 1s 1 750", interpolateVariables(expr, interval, timeRange)) |
||||
}) |
||||
t.Run("parsing query model, range below 0.5s", func(t *testing.T) { |
||||
expr := "go_goroutines $__interval $__interval_ms $__range $__range_s $__range_ms" |
||||
|
||||
interval := time.Millisecond * 50 |
||||
timeRange := time.Millisecond * 250 |
||||
|
||||
require.Equal(t, "go_goroutines 50ms 50 0s 0 250", interpolateVariables(expr, interval, timeRange)) |
||||
}) |
||||
} |
||||
Loading…
Reference in new issue