Prometheus: Implement stepMode for alerting queries (#36796)
* Add select component for choosing step option * Add onStepChange * Add functionality for max step * Rename minInterval to stepInterval to describe min, max and exact step interval * Change select option from standard to exact * Add new type StepType for better type safety * Add tests for adjustInterval * Add functionality and tests for exact step option * Prometheus: Spell out min and max in select component * Prometheus: Change width of step select component and add placeholder * Prometheus: Adjust for the factor in exact step * Prometheus: Update tooltip of step lable to include max and exact options and add padding to select component to give it some breathing room from other components * Update snapshot for step tooltip * Prometheus: make tooltip more informative * Prometheus: add tooltip to interval input element * Prometheus: extract default step option * Prometheus: update snapshot for PromQueryEditor * Prometheus: change step labels to uppercase * Prometheus: define a default step option * Prometheus: use default step option in both ui component and logic * Prometheus: update snapshot for PromQueryEditor * Prometheus: refactor datasource.ts for better readability * Prometheus: change tool tip for step * Prometheus: update snapshots * Prometheus: add correct styling * Prometheus: update snapshots * Prometheus change variable name to something less superfluous * Prometheus: refactor * Prometheus: add new test for adjustInterval * Docs: Update docummentation on the step parameter for prometheus * Prometheus: make step input field smaller and change placeholder text to 15s * Prometheus: update snapshots * Prometheus: Make stepMode uniform in all places in the code * Adjust step based on stepMode * Adjust comment * Check if we have queryInterval * Refactor, add safe interval * Fix merge resolutions * Fix tests and add tests * Update snapshot * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Implement calculation with intervalMode in calculator.go * Update tests, add calculate safe interval method * Replace panic with error * Update pkg/tsdb/interval/interval_test.go Co-authored-by: idafurjes <36131195+idafurjes@users.noreply.github.com> * Update pkg/tsdb/calculator_test.go Co-authored-by: idafurjes <36131195+idafurjes@users.noreply.github.com> * Impotrt require * Remove lint errors Co-authored-by: Olof Bourghardt <ob655088@gmail.com> Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Co-authored-by: idafurjes <36131195+idafurjes@users.noreply.github.com>
This commit is contained in:
co-authored by
achatterjee-grafana
idafurjes
Olof Bourghardt
parent
d49ce5ad47
commit
1083bef030
@@ -29,7 +29,8 @@ type intervalCalculator struct {
|
||||
}
|
||||
|
||||
type Calculator interface {
|
||||
Calculate(timeRange plugins.DataTimeRange, minInterval time.Duration) Interval
|
||||
Calculate(timeRange plugins.DataTimeRange, interval time.Duration, intervalMode string) (Interval, error)
|
||||
CalculateSafeInterval(timeRange plugins.DataTimeRange, resolution int64) Interval
|
||||
}
|
||||
|
||||
type CalculatorOptions struct {
|
||||
@@ -54,16 +55,37 @@ func (i *Interval) Milliseconds() int64 {
|
||||
return i.Value.Nanoseconds() / int64(time.Millisecond)
|
||||
}
|
||||
|
||||
func (ic *intervalCalculator) Calculate(timerange plugins.DataTimeRange, minInterval time.Duration) Interval {
|
||||
func (ic *intervalCalculator) Calculate(timerange plugins.DataTimeRange, interval time.Duration, intervalMode string) (Interval, error) {
|
||||
to := timerange.MustGetTo().UnixNano()
|
||||
from := timerange.MustGetFrom().UnixNano()
|
||||
interval := time.Duration((to - from) / defaultRes)
|
||||
calculatedInterval := time.Duration((to - from) / defaultRes)
|
||||
|
||||
if interval < minInterval {
|
||||
return Interval{Text: FormatDuration(minInterval), Value: minInterval}
|
||||
switch intervalMode {
|
||||
case "min":
|
||||
if calculatedInterval < interval {
|
||||
return Interval{Text: FormatDuration(interval), Value: interval}, nil
|
||||
}
|
||||
case "max":
|
||||
if calculatedInterval > interval {
|
||||
return Interval{Text: FormatDuration(interval), Value: interval}, nil
|
||||
}
|
||||
case "exact":
|
||||
return Interval{Text: FormatDuration(interval), Value: interval}, nil
|
||||
|
||||
default:
|
||||
return Interval{}, fmt.Errorf("unrecognized intervalMode: %v", intervalMode)
|
||||
}
|
||||
|
||||
rounded := roundInterval(interval)
|
||||
rounded := roundInterval(calculatedInterval)
|
||||
return Interval{Text: FormatDuration(rounded), Value: rounded}, nil
|
||||
}
|
||||
|
||||
func (ic *intervalCalculator) CalculateSafeInterval(timerange plugins.DataTimeRange, safeRes int64) Interval {
|
||||
to := timerange.MustGetTo().UnixNano()
|
||||
from := timerange.MustGetFrom().UnixNano()
|
||||
safeInterval := time.Duration((to - from) / safeRes)
|
||||
|
||||
rounded := roundInterval(safeInterval)
|
||||
return Interval{Text: FormatDuration(rounded), Value: rounded}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,19 +15,52 @@ func TestIntervalCalculator_Calculate(t *testing.T) {
|
||||
calculator := NewCalculator(CalculatorOptions{})
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
timeRange plugins.DataTimeRange
|
||||
expected string
|
||||
name string
|
||||
timeRange plugins.DataTimeRange
|
||||
intervalMode string
|
||||
expected string
|
||||
}{
|
||||
{"from 5m to now", plugins.NewDataTimeRange("5m", "now"), "200ms"},
|
||||
{"from 15m to now", plugins.NewDataTimeRange("15m", "now"), "500ms"},
|
||||
{"from 30m to now", plugins.NewDataTimeRange("30m", "now"), "1s"},
|
||||
{"from 1h to now", plugins.NewDataTimeRange("1h", "now"), "2s"},
|
||||
{"from 5m to now", plugins.NewDataTimeRange("5m", "now"), "min", "200ms"},
|
||||
{"from 5m to now", plugins.NewDataTimeRange("5m", "now"), "exact", "1ms"},
|
||||
{"from 5m to now", plugins.NewDataTimeRange("5m", "now"), "max", "1ms"},
|
||||
{"from 15m to now", plugins.NewDataTimeRange("15m", "now"), "min", "500ms"},
|
||||
{"from 15m to now", plugins.NewDataTimeRange("15m", "now"), "max", "1ms"},
|
||||
{"from 15m to now", plugins.NewDataTimeRange("15m", "now"), "exact", "1ms"},
|
||||
{"from 30m to now", plugins.NewDataTimeRange("30m", "now"), "min", "1s"},
|
||||
{"from 30m to now", plugins.NewDataTimeRange("30m", "now"), "max", "1ms"},
|
||||
{"from 30m to now", plugins.NewDataTimeRange("30m", "now"), "exact", "1ms"},
|
||||
{"from 24h to now", plugins.NewDataTimeRange("24h", "now"), "min", "1m"},
|
||||
{"from 24h to now", plugins.NewDataTimeRange("24h", "now"), "max", "1ms"},
|
||||
{"from 24h to now", plugins.NewDataTimeRange("24h", "now"), "exact", "1ms"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
interval := calculator.Calculate(tc.timeRange, time.Millisecond*1)
|
||||
interval, err := calculator.Calculate(tc.timeRange, time.Millisecond*1, tc.intervalMode)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, tc.expected, interval.Text)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntervalCalculator_CalculateSafeInterval(t *testing.T) {
|
||||
calculator := NewCalculator(CalculatorOptions{})
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
timeRange plugins.DataTimeRange
|
||||
safeResolution int64
|
||||
expected string
|
||||
}{
|
||||
{"from 5m to now", plugins.NewDataTimeRange("5m", "now"), 11000, "20ms"},
|
||||
{"from 15m to now", plugins.NewDataTimeRange("15m", "now"), 11000, "100ms"},
|
||||
{"from 30m to now", plugins.NewDataTimeRange("30m", "now"), 11000, "200ms"},
|
||||
{"from 24h to now", plugins.NewDataTimeRange("24h", "now"), 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)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user