Prometheus: Fix calculating rate interval when there is no interval specified (#78193)

* Use data source scrape interval when no interval is specified

* scrape interval as 15s
pull/78179/head^2
ismail simsek 2 years ago committed by GitHub
parent 40152922d3
commit 0214b25663
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      pkg/tsdb/prometheus/models/query.go
  2. 73
      pkg/tsdb/prometheus/models/query_test.go

@ -96,6 +96,7 @@ func Parse(query backend.DataQuery, dsScrapeInterval string, intervalCalculator
query.Interval, query.Interval,
calculatedMinStep, calculatedMinStep,
model.Interval, model.Interval,
dsScrapeInterval,
timeRange, timeRange,
) )
var rangeQuery, instantQuery bool var rangeQuery, instantQuery bool
@ -227,12 +228,14 @@ func calculateRateInterval(
// queryInterval Requested interval in milliseconds. This value may be overridden by MinStep in query options // queryInterval Requested interval in milliseconds. This value may be overridden by MinStep in query options
// calculatedMinStep Calculated final step value. It was calculated in calculatePrometheusInterval // calculatedMinStep Calculated final step value. It was calculated in calculatePrometheusInterval
// requestedMinStep Requested minimum step value. QueryModel.interval // requestedMinStep Requested minimum step value. QueryModel.interval
// dsScrapeInterval Data source scrape interval in the config
// timeRange Requested time range for query // timeRange Requested time range for query
func interpolateVariables( func interpolateVariables(
expr string, expr string,
queryInterval time.Duration, queryInterval time.Duration,
calculatedMinStep time.Duration, calculatedMinStep time.Duration,
requestedMinStep string, requestedMinStep string,
dsScrapeInterval string,
timeRange time.Duration, timeRange time.Duration,
) string { ) string {
rangeMs := timeRange.Milliseconds() rangeMs := timeRange.Milliseconds()
@ -245,6 +248,9 @@ func interpolateVariables(
if requestedMinStep == varInterval || requestedMinStep == varIntervalAlt { if requestedMinStep == varInterval || requestedMinStep == varIntervalAlt {
requestedMinStep = calculatedMinStep.String() requestedMinStep = calculatedMinStep.String()
} }
if requestedMinStep == "" {
requestedMinStep = dsScrapeInterval
}
rateInterval = calculateRateInterval(queryInterval, requestedMinStep) rateInterval = calculateRateInterval(queryInterval, requestedMinStep)
} }

@ -571,7 +571,7 @@ func TestRateInterval(t *testing.T) {
}, },
}, },
want: &models.Query{ want: &models.Query{
Expr: "rate(rpc_durations_seconds_count[2m30s])", Expr: "rate(rpc_durations_seconds_count[2m0s])",
Step: time.Second * 30, Step: time.Second * 30,
}, },
}, },
@ -637,6 +637,75 @@ func TestRateInterval(t *testing.T) {
require.Equal(t, tt.want.Step, res.Step) require.Equal(t, tt.want.Step, res.Step)
}) })
} }
t.Run("minStep is auto and ds scrape interval 30s and time range 1 hour", func(t *testing.T) {
query := backend.DataQuery{
RefID: "G",
QueryType: "",
MaxDataPoints: 1613,
Interval: 30 * time.Second,
TimeRange: backend.TimeRange{
From: now,
To: now.Add(1 * time.Hour),
},
JSON: []byte(`{
"datasource":{"type":"prometheus","uid":"zxS5e5W4k"},
"datasourceId":38,
"editorMode":"code",
"exemplar":false,
"expr":"sum(rate(process_cpu_seconds_total[$__rate_interval]))",
"instant":false,
"interval":"",
"intervalMs":30000,
"key":"Q-f96b6729-c47a-4ea8-8f71-a79774cf9bd5-0",
"legendFormat":"__auto",
"maxDataPoints":1613,
"range":true,
"refId":"G",
"requestId":"1G",
"utcOffsetSec":3600
}`),
}
res, err := models.Parse(query, "30s", intervalCalculator, false)
require.NoError(t, err)
require.Equal(t, "sum(rate(process_cpu_seconds_total[2m0s]))", res.Expr)
require.Equal(t, 30*time.Second, res.Step)
})
t.Run("minStep is auto and ds scrape interval 15s and time range 5 minutes", func(t *testing.T) {
query := backend.DataQuery{
RefID: "A",
QueryType: "",
MaxDataPoints: 1055,
Interval: 15 * time.Second,
TimeRange: backend.TimeRange{
From: now,
To: now.Add(5 * time.Minute),
},
JSON: []byte(`{
"datasource": {
"type": "prometheus",
"uid": "2z9d6ElGk"
},
"editorMode": "code",
"expr": "sum(rate(cache_requests_total[$__rate_interval]))",
"legendFormat": "__auto",
"range": true,
"refId": "A",
"exemplar": false,
"requestId": "1A",
"utcOffsetSec": 0,
"interval": "",
"datasourceId": 508,
"intervalMs": 15000,
"maxDataPoints": 1055
}`),
}
res, err := models.Parse(query, "15s", intervalCalculator, false)
require.NoError(t, err)
require.Equal(t, "sum(rate(cache_requests_total[1m0s]))", res.Expr)
require.Equal(t, 15*time.Second, res.Step)
})
} }
func mockQuery(expr string, interval string, intervalMs int64, timeRange *backend.TimeRange) backend.DataQuery { func mockQuery(expr string, interval string, intervalMs int64, timeRange *backend.TimeRange) backend.DataQuery {
@ -647,7 +716,7 @@ func mockQuery(expr string, interval string, intervalMs int64, timeRange *backen
} }
} }
return backend.DataQuery{ return backend.DataQuery{
Interval: 2 * time.Minute, Interval: time.Duration(intervalMs) * time.Millisecond,
JSON: []byte(fmt.Sprintf(`{ JSON: []byte(fmt.Sprintf(`{
"expr": "%s", "expr": "%s",
"format": "time_series", "format": "time_series",

Loading…
Cancel
Save