mirror of
https://github.com/grafana/grafana.git
synced 2025-09-20 05:53:07 +08:00
Prometheus: Remove all intervalv2 imports and use gtime functions wherever it's possible (#82064)
* Remove all intervalv2 imports and use gtime functions where ever it's possible * Add a comment line * use roundInterval from grafana-plugin-sdk-go
This commit is contained in:
74
pkg/tsdb/prometheus/intervalv2/intervalv2.go
Normal file
74
pkg/tsdb/prometheus/intervalv2/intervalv2.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// Package intervalv2 partially copied from https://github.com/grafana/grafana/blob/main/pkg/tsdb/intervalv2/intervalv2.go
|
||||||
|
package intervalv2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend/gtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultRes int64 = 1500
|
||||||
|
defaultMinInterval = time.Millisecond * 1
|
||||||
|
)
|
||||||
|
|
||||||
|
type Interval struct {
|
||||||
|
Text string
|
||||||
|
Value time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
type intervalCalculator struct {
|
||||||
|
minInterval time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
type Calculator interface {
|
||||||
|
Calculate(timerange backend.TimeRange, minInterval time.Duration, maxDataPoints int64) Interval
|
||||||
|
CalculateSafeInterval(timerange backend.TimeRange, resolution int64) Interval
|
||||||
|
}
|
||||||
|
|
||||||
|
type CalculatorOptions struct {
|
||||||
|
MinInterval time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCalculator(opts ...CalculatorOptions) *intervalCalculator {
|
||||||
|
calc := &intervalCalculator{}
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
if o.MinInterval == 0 {
|
||||||
|
calc.minInterval = defaultMinInterval
|
||||||
|
} else {
|
||||||
|
calc.minInterval = o.MinInterval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return calc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ic *intervalCalculator) Calculate(timerange backend.TimeRange, minInterval time.Duration, maxDataPoints int64) Interval {
|
||||||
|
to := timerange.To.UnixNano()
|
||||||
|
from := timerange.From.UnixNano()
|
||||||
|
resolution := maxDataPoints
|
||||||
|
if resolution == 0 {
|
||||||
|
resolution = DefaultRes
|
||||||
|
}
|
||||||
|
|
||||||
|
calculatedInterval := time.Duration((to - from) / resolution)
|
||||||
|
|
||||||
|
if calculatedInterval < minInterval {
|
||||||
|
return Interval{Text: gtime.FormatInterval(minInterval), Value: minInterval}
|
||||||
|
}
|
||||||
|
|
||||||
|
rounded := gtime.RoundInterval(calculatedInterval)
|
||||||
|
|
||||||
|
return Interval{Text: gtime.FormatInterval(rounded), Value: rounded}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ic *intervalCalculator) CalculateSafeInterval(timerange backend.TimeRange, safeRes int64) Interval {
|
||||||
|
to := timerange.To.UnixNano()
|
||||||
|
from := timerange.From.UnixNano()
|
||||||
|
safeInterval := time.Duration((to - from) / safeRes)
|
||||||
|
|
||||||
|
rounded := gtime.RoundInterval(safeInterval)
|
||||||
|
return Interval{Text: gtime.FormatInterval(rounded), Value: rounded}
|
||||||
|
}
|
63
pkg/tsdb/prometheus/intervalv2/intervalv2_test.go
Normal file
63
pkg/tsdb/prometheus/intervalv2/intervalv2_test.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package intervalv2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIntervalCalculator_Calculate(t *testing.T) {
|
||||||
|
calculator := NewCalculator(CalculatorOptions{})
|
||||||
|
|
||||||
|
timeNow := time.Now()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
timeRange backend.TimeRange
|
||||||
|
resolution int64
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"from 5m to now and default resolution", backend.TimeRange{From: timeNow, To: timeNow.Add(5 * time.Minute)}, 0, "200ms"},
|
||||||
|
{"from 5m to now and 500 resolution", backend.TimeRange{From: timeNow, To: timeNow.Add(5 * time.Minute)}, 500, "500ms"},
|
||||||
|
{"from 15m to now and default resolution", backend.TimeRange{From: timeNow, To: timeNow.Add(15 * time.Minute)}, 0, "500ms"},
|
||||||
|
{"from 15m to now and 100 resolution", backend.TimeRange{From: timeNow, To: timeNow.Add(15 * time.Minute)}, 100, "10s"},
|
||||||
|
{"from 30m to now and default resolution", backend.TimeRange{From: timeNow, To: timeNow.Add(30 * time.Minute)}, 0, "1s"},
|
||||||
|
{"from 30m to now and 3000 resolution", backend.TimeRange{From: timeNow, To: timeNow.Add(30 * time.Minute)}, 3000, "500ms"},
|
||||||
|
{"from 1h to now and default resolution", backend.TimeRange{From: timeNow, To: timeNow.Add(time.Hour)}, 0, "2s"},
|
||||||
|
{"from 1h to now and 1000 resolution", backend.TimeRange{From: timeNow, To: timeNow.Add(time.Hour)}, 1000, "5s"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
interval := calculator.Calculate(tc.timeRange, time.Millisecond*1, tc.resolution)
|
||||||
|
assert.Equal(t, tc.expected, interval.Text)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntervalCalculator_CalculateSafeInterval(t *testing.T) {
|
||||||
|
calculator := NewCalculator(CalculatorOptions{})
|
||||||
|
|
||||||
|
timeNow := time.Now()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
timeRange backend.TimeRange
|
||||||
|
safeResolution int64
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"from 5m to now", backend.TimeRange{From: timeNow, To: timeNow.Add(5 * time.Minute)}, 11000, "20ms"},
|
||||||
|
{"from 15m to now", backend.TimeRange{From: timeNow, To: timeNow.Add(15 * time.Minute)}, 11000, "100ms"},
|
||||||
|
{"from 30m to now", backend.TimeRange{From: timeNow, To: timeNow.Add(30 * time.Minute)}, 11000, "200ms"},
|
||||||
|
{"from 24h to now", backend.TimeRange{From: timeNow, To: timeNow.Add(1440 * time.Minute)}, 11000, "10s"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
interval := calculator.CalculateSafeInterval(tc.timeRange, tc.safeResolution)
|
||||||
|
assert.Equal(t, tc.expected, interval.Text)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -9,10 +9,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend/gtime"
|
||||||
"github.com/prometheus/prometheus/model/labels"
|
"github.com/prometheus/prometheus/model/labels"
|
||||||
"github.com/prometheus/prometheus/promql/parser"
|
"github.com/prometheus/prometheus/promql/parser"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/intervalv2"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/prometheus/kinds/dataquery"
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/kinds/dataquery"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -194,7 +195,7 @@ func calculatePrometheusInterval(
|
|||||||
queryInterval = ""
|
queryInterval = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
minInterval, err := intervalv2.GetIntervalFrom(dsScrapeInterval, queryInterval, intervalMs, 15*time.Second)
|
minInterval, err := gtime.GetIntervalFrom(dsScrapeInterval, queryInterval, intervalMs, 15*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Duration(0), err
|
return time.Duration(0), err
|
||||||
}
|
}
|
||||||
@ -233,7 +234,7 @@ func calculateRateInterval(
|
|||||||
scrape = "15s"
|
scrape = "15s"
|
||||||
}
|
}
|
||||||
|
|
||||||
scrapeIntervalDuration, err := intervalv2.ParseIntervalStringToTimeDuration(scrape)
|
scrapeIntervalDuration, err := gtime.ParseIntervalStringToTimeDuration(scrape)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Duration(0)
|
return time.Duration(0)
|
||||||
}
|
}
|
||||||
@ -274,7 +275,7 @@ func interpolateVariables(
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr = strings.ReplaceAll(expr, varIntervalMs, strconv.FormatInt(int64(calculatedStep/time.Millisecond), 10))
|
expr = strings.ReplaceAll(expr, varIntervalMs, strconv.FormatInt(int64(calculatedStep/time.Millisecond), 10))
|
||||||
expr = strings.ReplaceAll(expr, varInterval, intervalv2.FormatDuration(calculatedStep))
|
expr = strings.ReplaceAll(expr, varInterval, gtime.FormatInterval(calculatedStep))
|
||||||
expr = strings.ReplaceAll(expr, varRangeMs, strconv.FormatInt(rangeMs, 10))
|
expr = strings.ReplaceAll(expr, varRangeMs, strconv.FormatInt(rangeMs, 10))
|
||||||
expr = strings.ReplaceAll(expr, varRangeS, strconv.FormatInt(rangeSRounded, 10))
|
expr = strings.ReplaceAll(expr, varRangeS, strconv.FormatInt(rangeSRounded, 10))
|
||||||
expr = strings.ReplaceAll(expr, varRange, strconv.FormatInt(rangeSRounded, 10)+"s")
|
expr = strings.ReplaceAll(expr, varRange, strconv.FormatInt(rangeSRounded, 10)+"s")
|
||||||
@ -283,7 +284,7 @@ func interpolateVariables(
|
|||||||
|
|
||||||
// Repetitive code, we should have functionality to unify these
|
// Repetitive code, we should have functionality to unify these
|
||||||
expr = strings.ReplaceAll(expr, varIntervalMsAlt, strconv.FormatInt(int64(calculatedStep/time.Millisecond), 10))
|
expr = strings.ReplaceAll(expr, varIntervalMsAlt, strconv.FormatInt(int64(calculatedStep/time.Millisecond), 10))
|
||||||
expr = strings.ReplaceAll(expr, varIntervalAlt, intervalv2.FormatDuration(calculatedStep))
|
expr = strings.ReplaceAll(expr, varIntervalAlt, gtime.FormatInterval(calculatedStep))
|
||||||
expr = strings.ReplaceAll(expr, varRangeMsAlt, strconv.FormatInt(rangeMs, 10))
|
expr = strings.ReplaceAll(expr, varRangeMsAlt, strconv.FormatInt(rangeMs, 10))
|
||||||
expr = strings.ReplaceAll(expr, varRangeSAlt, strconv.FormatInt(rangeSRounded, 10))
|
expr = strings.ReplaceAll(expr, varRangeSAlt, strconv.FormatInt(rangeSRounded, 10))
|
||||||
expr = strings.ReplaceAll(expr, varRangeAlt, strconv.FormatInt(rangeSRounded, 10)+"s")
|
expr = strings.ReplaceAll(expr, varRangeAlt, strconv.FormatInt(rangeSRounded, 10)+"s")
|
||||||
@ -303,7 +304,7 @@ func isVariableInterval(interval string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function aligns query range to step and handles the time offset.
|
// AlignTimeRange aligns query range to step and handles the time offset.
|
||||||
// It rounds start and end down to a multiple of step.
|
// It rounds start and end down to a multiple of step.
|
||||||
// Prometheus caching is dependent on the range being aligned with the step.
|
// Prometheus caching is dependent on the range being aligned with the step.
|
||||||
// Rounding to the step can significantly change the start and end of the range for larger steps, i.e. a week.
|
// Rounding to the step can significantly change the start and end of the range for larger steps, i.e. a week.
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/intervalv2"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/prometheus/models"
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
|
||||||
"github.com/grafana/grafana/pkg/tsdb/prometheus/client"
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/client"
|
||||||
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/intervalv2"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/prometheus/models"
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/models"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/prometheus/querydata/exemplar"
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/querydata/exemplar"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/prometheus/utils"
|
"github.com/grafana/grafana/pkg/tsdb/prometheus/utils"
|
||||||
|
Reference in New Issue
Block a user